summaryrefslogtreecommitdiff
path: root/source/luametatex/source/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2022-12-01 13:43:10 +0100
committerContext Git Mirror Bot <phg@phi-gamma.net>2022-12-01 13:43:10 +0100
commit08fa92c1c94d9faddee48590a1a20506e89c191c (patch)
tree12bbf6fa56b69c47340d4c15f8f601be2d9487b5 /source/luametatex/source/tex
parent2593c827482f6c5a315d504cd5316879d6172656 (diff)
downloadcontext-08fa92c1c94d9faddee48590a1a20506e89c191c.tar.gz
2022-12-01 12:41:00
Diffstat (limited to 'source/luametatex/source/tex')
-rw-r--r--source/luametatex/source/tex/texcommands.c7
-rw-r--r--source/luametatex/source/tex/texcommands.h3
-rw-r--r--source/luametatex/source/tex/texdumpdata.h2
-rw-r--r--source/luametatex/source/tex/texequivalents.c2
-rw-r--r--source/luametatex/source/tex/texequivalents.h11
-rw-r--r--source/luametatex/source/tex/texexpand.c19
-rw-r--r--source/luametatex/source/tex/texfont.c804
-rw-r--r--source/luametatex/source/tex/texfont.h3
-rw-r--r--source/luametatex/source/tex/texinputstack.h4
-rw-r--r--source/luametatex/source/tex/texinserts.c2
-rw-r--r--source/luametatex/source/tex/texlinebreak.c6
-rw-r--r--source/luametatex/source/tex/texmaincontrol.c57
-rw-r--r--source/luametatex/source/tex/texmath.c183
-rw-r--r--source/luametatex/source/tex/texmath.h7
-rw-r--r--source/luametatex/source/tex/texmathcodes.c12
-rw-r--r--source/luametatex/source/tex/texmathcodes.h2
-rw-r--r--source/luametatex/source/tex/texmlist.c39
-rw-r--r--source/luametatex/source/tex/texnesting.c7
-rw-r--r--source/luametatex/source/tex/texnesting.h2
-rw-r--r--source/luametatex/source/tex/texnodes.c18
-rw-r--r--source/luametatex/source/tex/texnodes.h136
-rw-r--r--source/luametatex/source/tex/texprimitive.c4
-rw-r--r--source/luametatex/source/tex/texprinting.h5
-rw-r--r--source/luametatex/source/tex/texscanning.c9
-rw-r--r--source/luametatex/source/tex/texscanning.h2
-rw-r--r--source/luametatex/source/tex/texstringpool.c4
-rw-r--r--source/luametatex/source/tex/texstringpool.h64
-rw-r--r--source/luametatex/source/tex/textextcodes.c51
-rw-r--r--source/luametatex/source/tex/textextcodes.h2
-rw-r--r--source/luametatex/source/tex/textoken.c45
-rw-r--r--source/luametatex/source/tex/textoken.h39
31 files changed, 991 insertions, 560 deletions
diff --git a/source/luametatex/source/tex/texcommands.c b/source/luametatex/source/tex/texcommands.c
index 5a4cc48b3..0e9bb7ac9 100644
--- a/source/luametatex/source/tex/texcommands.c
+++ b/source/luametatex/source/tex/texcommands.c
@@ -138,7 +138,6 @@ void tex_initialize_commands(void)
tex_primitive(tex_command, "exhyphenchar", internal_int_cmd, ex_hyphen_char_code, internal_int_base);
tex_primitive(tex_command, "exhyphenpenalty", internal_int_cmd, ex_hyphen_penalty_code, internal_int_base);
tex_primitive(tex_command, "fam", internal_int_cmd, family_code, internal_int_base);
- tex_primitive(luatex_command, "variablefam", internal_int_cmd, variable_family_code, internal_int_base);
tex_primitive(tex_command, "finalhyphendemerits", internal_int_cmd, final_hyphen_demerits_code, internal_int_base);
tex_primitive(tex_command, "floatingpenalty", internal_int_cmd, floating_penalty_code, internal_int_base);
tex_primitive(tex_command, "globaldefs", internal_int_cmd, global_defs_code, internal_int_base);
@@ -198,7 +197,8 @@ void tex_initialize_commands(void)
tex_primitive(luatex_command, "tracingnodes", internal_int_cmd, tracing_nodes_code, internal_int_base);
tex_primitive(luatex_command, "tracingfullboxes", internal_int_cmd, tracing_full_boxes_code, internal_int_base);
tex_primitive(luatex_command, "tracingpenalties", internal_int_cmd, tracing_penalties_code, internal_int_base);
- tex_primitive(tex_command, "uchyph", internal_int_cmd, uc_hyph_code, internal_int_base); /* obsolete */
+ tex_primitive(tex_command, "uchyph", internal_int_cmd, uc_hyph_code, internal_int_base); /* obsolete, not needed */
+ tex_primitive(luatex_command, "variablefam", internal_int_cmd, variable_family_code, internal_int_base); /* obsolete, not used */
tex_primitive(tex_command, "vbadness", internal_int_cmd, vbadness_code, internal_int_base);
tex_primitive(tex_command, "widowpenalty", internal_int_cmd, widow_penalty_code, internal_int_base);
tex_primitive(tex_command, "year", internal_int_cmd, year_code, internal_int_base);
@@ -386,6 +386,7 @@ void tex_initialize_commands(void)
tex_primitive(luatex_command, "expandtoken", expand_after_cmd, expand_token_code, 0);
tex_primitive(luatex_command, "expandcstoken", expand_after_cmd, expand_cs_token_code, 0);
tex_primitive(luatex_command, "expand", expand_after_cmd, expand_code, 0);
+ tex_primitive(luatex_command, "expandactive", expand_after_cmd, expand_active_code, 0);
tex_primitive(luatex_command, "semiexpand", expand_after_cmd, semi_expand_code, 0);
tex_primitive(luatex_command, "expandedafter", expand_after_cmd, expand_after_toks_code, 0);
/* tex_primitive(luatex_command, "expandafterfi", expand_after_cmd, expand_after_fi, 0); */
@@ -655,6 +656,7 @@ void tex_initialize_commands(void)
tex_primitive(tex_command, "string", convert_cmd, string_code, 0);
tex_primitive(luatex_command, "directlua", convert_cmd, lua_code, 0);
tex_primitive(luatex_command, "csstring", convert_cmd, cs_string_code, 0);
+ tex_primitive(luatex_command, "csactive", convert_cmd, cs_active_code, 0);
tex_primitive(luatex_command, "detokenized", convert_cmd, detokenized_code, 0);
tex_primitive(luatex_command, "expanded", convert_cmd, expanded_code, 0);
tex_primitive(luatex_command, "semiexpanded", convert_cmd, semi_expanded_code, 0);
@@ -759,6 +761,7 @@ void tex_initialize_commands(void)
tex_primitive(tex_command, "sfcode", define_char_code_cmd, sfcode_charcode, 0);
tex_primitive(luatex_command, "hccode", define_char_code_cmd, hccode_charcode, 0);
tex_primitive(luatex_command, "hmcode", define_char_code_cmd, hmcode_charcode, 0);
+ tex_primitive(luatex_command, "amcode", define_char_code_cmd, amcode_charcode, 0);
tex_primitive(tex_command, "mathcode", define_char_code_cmd, mathcode_charcode, 0);
tex_primitive(tex_command, "delcode", define_char_code_cmd, delcode_charcode, 0);
diff --git a/source/luametatex/source/tex/texcommands.h b/source/luametatex/source/tex/texcommands.h
index 6d85f1ed7..a5c157a44 100644
--- a/source/luametatex/source/tex/texcommands.h
+++ b/source/luametatex/source/tex/texcommands.h
@@ -442,6 +442,7 @@ typedef enum convert_codes {
semi_expanded_code, /*tex command code for |\constantexpanded| */
string_code, /*tex command code for |\string| */
cs_string_code, /*tex command code for |\csstring| */
+ cs_active_code, /*tex command code for |\csactive| */
detokenized_code, /*tex command code for |\detokenized| */
roman_numeral_code, /*tex command code for |\romannumeral| */
meaning_code, /*tex command code for |\meaning| */
@@ -743,6 +744,7 @@ typedef enum expand_after_codes {
expand_token_code,
expand_cs_token_code,
expand_code,
+ expand_active_code,
semi_expand_code,
expand_after_toks_code,
/* expand_after_fi, */
@@ -1034,6 +1036,7 @@ typedef enum charcode_codes {
sfcode_charcode,
hccode_charcode,
hmcode_charcode,
+ amcode_charcode,
mathcode_charcode,
extmathcode_charcode,
delcode_charcode,
diff --git a/source/luametatex/source/tex/texdumpdata.h b/source/luametatex/source/tex/texdumpdata.h
index e6f51d323..d9b4e5cdd 100644
--- a/source/luametatex/source/tex/texdumpdata.h
+++ b/source/luametatex/source/tex/texdumpdata.h
@@ -55,7 +55,7 @@
*/
-# define luametatex_format_fingerprint 675
+# define luametatex_format_fingerprint 676
/* These end up in the string pool. */
diff --git a/source/luametatex/source/tex/texequivalents.c b/source/luametatex/source/tex/texequivalents.c
index 4de7617c9..bdf21446e 100644
--- a/source/luametatex/source/tex/texequivalents.c
+++ b/source/luametatex/source/tex/texequivalents.c
@@ -1125,7 +1125,7 @@ void tex_geq_word_define(halfword p, int w)
a side effect of looking at the code through a visual studio lense.)
*/
-static inline void tex_aux_set_eq_data(halfword p, singleword t, halfword e, singleword f, quarterword l)
+inline static void tex_aux_set_eq_data(halfword p, singleword t, halfword e, singleword f, quarterword l)
{
singleword flag = eq_flag(p);
set_eq_level(p, l);
diff --git a/source/luametatex/source/tex/texequivalents.h b/source/luametatex/source/tex/texequivalents.h
index 2feab6858..1a6c41b2a 100644
--- a/source/luametatex/source/tex/texequivalents.h
+++ b/source/luametatex/source/tex/texequivalents.h
@@ -571,7 +571,12 @@ typedef enum int_codes {
alignment_wrap_source_code,
/* page_boundary_penalty_code, */
line_break_criterium_code,
- variable_family_code,
+ /*
+ This one was added as experiment to \LUATEX\ (answer to a forwarded question) but as it
+ didn't get tested it will go away. \CONTEXT\ doesn't need it and we don't need to be
+ compatible anyway. Lesson learned.
+ */
+ variable_family_code,
/* those below these are not interfaced via primitives */
internal_par_state_code,
internal_dir_state_code,
@@ -601,7 +606,7 @@ typedef enum int_codes {
} int_codes;
# define first_int_code pre_tolerance_code
-# define last_int_code line_break_criterium_code
+# define last_int_code variable_family_code
typedef enum dimen_codes {
par_indent_code, /*tex indentation of paragraphs */
@@ -836,7 +841,7 @@ extern save_state_info lmt_save_state;
# define saved_value(A) lmt_save_state.save_stack[lmt_save_state.save_stack_data.ptr + (A)].saved_value
# define saved_word(A) lmt_save_state.save_stack[lmt_save_state.save_stack_data.ptr + (A)].saved_word
-inline void tex_set_saved_record(halfword ptr, quarterword type, quarterword level, halfword value)
+inline static void tex_set_saved_record(halfword ptr, quarterword type, quarterword level, halfword value)
{
saved_type(ptr) = type;
saved_level(ptr) = level;
diff --git a/source/luametatex/source/tex/texexpand.c b/source/luametatex/source/tex/texexpand.c
index e74a9c08d..cec254d2b 100644
--- a/source/luametatex/source/tex/texexpand.c
+++ b/source/luametatex/source/tex/texexpand.c
@@ -251,7 +251,7 @@ void tex_expand_current_token(void)
case expand_token_code:
{
/* we can share code with lmtokenlib .. todo */
- halfword cat = tex_scan_category_code();
+ halfword cat = tex_scan_category_code(0);
halfword chr = tex_scan_char_number(0);
/* too fragile:
halfword tok = null;
@@ -304,6 +304,7 @@ void tex_expand_current_token(void)
case spacer_cmd:
case letter_cmd:
case other_char_cmd:
+ case active_char_cmd: /* new */
cur_tok = token_val(cmd, eq_value(cur_cs));
break;
}
@@ -322,6 +323,20 @@ void tex_expand_current_token(void)
}
break;
}
+ case expand_active_code:
+ {
+ tex_get_token();
+ if (cur_cmd == active_char_cmd) {
+ cur_cs = tex_active_to_cs(cur_chr, ! lmt_hash_state.no_new_cs);
+ if (cur_cs) {
+ cur_tok = cs_token_flag + cur_cs;
+ } else {
+ cur_tok = token_val(cur_cmd, cur_chr);
+ }
+ }
+ tex_back_input(cur_tok);
+ break;
+ }
case semi_expand_code:
{
tex_get_token();
@@ -618,12 +633,12 @@ static int tex_aux_collect_cs_tokens(halfword *p, int *n)
case spacer_cmd:
case letter_cmd:
case other_char_cmd:
+ case active_char_cmd: /* new */
// cur_tok = token_val(cur_cmd, cur_chr);
// *p = tex_store_new_token(*p, cur_tok);
*p = tex_store_new_token(*p, token_val(cur_cmd, cur_chr));
*n += 1;
break;
- /* case active_char_cmd: */
/* case comment_cmd: */
/* case invalid_char_cmd: */
/*
diff --git a/source/luametatex/source/tex/texfont.c b/source/luametatex/source/tex/texfont.c
index f3b26d99a..ac0ea1290 100644
--- a/source/luametatex/source/tex/texfont.c
+++ b/source/luametatex/source/tex/texfont.c
@@ -26,6 +26,65 @@
# include "luametatex.h"
+/*tex
+ Finally the base mode ligaturing and kerning code has also been made more consistent with the
+ rest: abstraction, more tight equality testing, helpers, merged some experiments, etc. It will
+ probably evolve a bit more; not that we use basemode frequently in \CONTEXT. Keep in mind that
+ it is not that hard to mess up the list when using \LUA\ but we do little checking here.
+
+ From now on base mode ligaturing and kerning will only be applied when |text_font_control|
+ have the |text_control_base_ligaturing| and |text_control_base_kerning| bits set.
+*/
+
+inline static halfword tex_aux_discretionary_node(halfword target, int location)
+{
+ switch (location) {
+ case pre_break_code : return disc_pre_break_node(target);
+ case post_break_code: return disc_post_break_node(target);
+ case no_break_code : return disc_no_break_node(target);
+ default : return null;
+ }
+}
+
+inline static int tex_aux_same_font_properties(halfword a, halfword b) // also in kern
+{
+ return node_type(a) == glyph_node && node_type(b) == glyph_node
+ && glyph_font(a) == glyph_font(b)
+ && glyph_x_scale(a) == glyph_x_scale(b)
+ && glyph_y_scale(a) == glyph_y_scale(b)
+ && glyph_scale(a) == glyph_scale(b);
+}
+
+inline static int tex_aux_apply_base_kerning(halfword n)
+{
+ if (glyph_protected(n)) {
+ return 0;
+ } else {
+ halfword f = glyph_font(n);
+ if (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f]) {
+ return has_font_text_control(f, text_control_base_kerning);
+ } else {
+ return 0;
+ }
+ }
+}
+
+inline static int tex_aux_apply_base_ligaturing(halfword n)
+{
+ if (glyph_protected(n)) {
+ return 0;
+ } else {
+ halfword f = glyph_font(n);
+ if (f >= 0 && f <= lmt_font_state.font_data.ptr && lmt_font_state.fonts[f]) {
+ return has_font_text_control(f, text_control_base_ligaturing);
+ } else {
+ return 0;
+ }
+ }
+}
+
+/* */
+
inline static scaled tex_aux_font_x_scaled(scaled v)
{
return v ? scaledround(0.000001 * (glyph_scale_par ? glyph_scale_par : 1000) * (glyph_x_scale_par ? glyph_x_scale_par : 1000) * v) : 0;
@@ -135,34 +194,34 @@ void tex_undump_font_data(dumpstream f) {
void tex_set_charinfo_extensible_recipe(charinfo *ci, extinfo *ext)
{
if (ci->math) {
- extinfo *lst = ci->math->extensible_recipe;
- if (lst) {
- while (lst) {
- extinfo *c = lst->next;
- lmt_memory_free(lst);
- lst = c;
+ extinfo *list = ci->math->extensible_recipe;
+ if (list) {
+ while (list) {
+ extinfo *c = list->next;
+ lmt_memory_free(list);
+ list = c;
}
}
ci->math->extensible_recipe = ext;
}
}
-void tex_set_font_parameters(halfword f, int b)
+void tex_set_font_parameters(halfword f, int index)
{
int i = font_parameter_count(f);
- if (b > i) {
+ if (index > i) {
/*tex If really needed this can be a calloc. */
- int s = (b + 2) * (int) sizeof(int);
- int *a = lmt_memory_realloc(font_parameter_base(f), (size_t) s);
- if (a) {
- lmt_font_state.font_data.allocated += (b - i + 1) * (int) sizeof(scaled);
- font_parameter_base(f) = a;
- font_parameter_count(f) = b;
- while (i < b) {
+ int size = (index + 2) * (int) sizeof(int);
+ int *list = lmt_memory_realloc(font_parameter_base(f), (size_t) size);
+ if (list) {
+ lmt_font_state.font_data.allocated += (index - i + 1) * (int) sizeof(scaled);
+ font_parameter_base(f) = list;
+ font_parameter_count(f) = index;
+ while (i < index) {
font_parameter(f, ++i) = 0;
}
} else {
- tex_overflow_error("font", s);
+ tex_overflow_error("font", size);
}
}
}
@@ -174,14 +233,14 @@ int tex_new_font(void)
int size = sizeof(charinfo);
charinfo *ci = lmt_memory_calloc(1, (size_t) size);
if (ci) {
- texfont *t = NULL;
+ texfont *tf = NULL;
size = sizeof(texfont);
- t = lmt_memory_calloc(1, (size_t) size);
- if (t) {
+ tf = lmt_memory_calloc(1, (size_t) size);
+ if (tf) {
sa_tree_item sa_value = { 0 };
int id = tex_new_font_id();
lmt_font_state.font_data.allocated += size;
- lmt_font_state.fonts[id] = t;
+ lmt_font_state.fonts[id] = tf;
set_font_name(id, NULL);
set_font_original(id, NULL);
set_font_left_boundary(id, NULL);
@@ -194,13 +253,13 @@ int tex_new_font(void)
set_font_skew_char(id, -1);
/*tex allocate eight values including 0 */
tex_set_font_parameters(id, 7);
- for (int k = 0; k <= 7; k++) {
- tex_set_font_parameter(id, k, 0);
+ for (int i = 0; i <= 7; i++) {
+ tex_set_font_parameter(id, i, 0);
}
/*tex character info zero is reserved for |notdef|. The stack size 1, default item value 0. */
- t->characters = sa_new_tree(1, 4, sa_value);
- t->chardata = ci;
- t->chardata_size = 1;
+ tf->characters = sa_new_tree(1, 4, sa_value);
+ tf->chardata = ci;
+ tf->chardata_size = 1;
return id;
}
}
@@ -208,16 +267,16 @@ int tex_new_font(void)
return 0;
}
-void tex_font_malloc_charinfo(halfword f, int num)
+void tex_font_malloc_charinfo(halfword f, int index)
{
int glyph = lmt_font_state.fonts[f]->chardata_size;
- int size = (glyph + num) * sizeof(charinfo);
+ int size = (glyph + index) * sizeof(charinfo);
charinfo *data = lmt_memory_realloc(lmt_font_state.fonts[f]->chardata , (size_t) size);
if (data) {
- lmt_font_state.font_data.allocated += num * sizeof(charinfo);
+ lmt_font_state.font_data.allocated += index * sizeof(charinfo);
lmt_font_state.fonts[f]->chardata = data;
- memset(&data[glyph], 0, (size_t) num * sizeof(charinfo));
- lmt_font_state.fonts[f]->chardata_size += num;
+ memset(&data[glyph], 0, (size_t) index * sizeof(charinfo));
+ lmt_font_state.fonts[f]->chardata_size += index;
} else {
tex_overflow_error("font", size);
}
@@ -690,10 +749,8 @@ halfword tex_get_font_identifier(halfword fontspec)
}
/*tex
-
Here come some subroutines to deal with expanded fonts. Returning 1 means that they are
identical.
-
*/
ligatureinfo tex_get_ligature(halfword f, int lc, int rc)
@@ -793,11 +850,7 @@ halfword tex_checked_font_adjust(halfword adjust_spacing, halfword adjust_spacin
return adjust_spacing;
}
-/*tex
-
- This returns the multiple of |font_step(f)| that is nearest to |e|.
-
-*/
+/*tex This returns the multiple of |font_step(f)| that is nearest to |e|. */
int tex_fix_expand_value(halfword f, int e)
{
@@ -936,34 +989,39 @@ halfword tex_get_parameter_glue(quarterword p, quarterword s)
/*tex Ligaturing starts here */
-static void tex_aux_nesting_append(halfword nest1, halfword newn)
+static void tex_aux_discretionary_append(halfword target, int location, halfword n)
{
- halfword tail = node_tail(nest1);
- tex_couple_nodes(tail ? tail : nest1, newn);
- node_tail(nest1) = newn;
+ halfword node = tex_aux_discretionary_node(target, location);
+ if (node_tail(node)) {
+ tex_couple_nodes(node_tail(node), n);
+ } else {
+ node_head(node) = n;
+ }
+ node_tail(node) = n;
}
-static void tex_aux_nesting_prepend(halfword nest1, halfword newn)
+static void tex_aux_discretionary_prepend(halfword target, int location, halfword n)
{
- halfword head = node_next(nest1);
- tex_couple_nodes(nest1, newn);
- if (head) {
- tex_couple_nodes(newn, head);
+ halfword node = tex_aux_discretionary_node(target, location);
+ if (node_head(node)) {
+ tex_couple_nodes(n, node_head(node));
} else {
- node_tail(nest1) = newn;
- }
+ node_tail(node) = n;
+ }
+ node_head(node) = n;
}
-static void tex_aux_nesting_prepend_list(halfword nest1, halfword newn)
+static void tex_aux_nesting_prepend_list(halfword target, int location, halfword n) /* n is prepended to target */
{
- halfword head = node_next(nest1);
- halfword tail = tex_tail_of_node_list(newn);
- tex_couple_nodes(nest1, newn);
- if (head) {
- tex_couple_nodes(tail, head);
- } else {
- node_tail(nest1) = tail;
+ halfword node = tex_aux_discretionary_node(target, location);
+ halfword copy = tex_copy_node_list(n, null);
+ halfword tail = tex_tail_of_node_list(copy);
+ if (node_head(node)) {
+ tex_couple_nodes(tail, node_head(node));
+ } else {
+ node_tail(node) = tail;
}
+ node_head(node) = copy;
}
int tex_valid_ligature(halfword left, halfword right, int *slot)
@@ -987,7 +1045,9 @@ int tex_valid_ligature(halfword left, halfword right, int *slot)
static int tex_aux_found_ligature(halfword left, halfword right)
{
- if (node_type(left) != glyph_node) {
+ if (! left || ! right) {
+ return 0;
+ } else if (node_type(left) != glyph_node || node_type(right) != glyph_node) {
return 0;
} else if (glyph_font(left) != glyph_font(right)) {
return 0;
@@ -999,77 +1059,101 @@ static int tex_aux_found_ligature(halfword left, halfword right)
}
/*tex
- We could be more efficient and reuse the possibly later removed node but it takes more code and
- we don't have that many ligatures anyway.
+ In principle we only support simple ligatures, i.e.\ |move_after|, |keep_right| and |keep_left|
+ are zero. At some point we might even drop special ones, including those with boundaries because
+ the likelyhood of encountering these in the \OPENTYPE\ arena is close to zero.
*/
-static int tex_aux_try_ligature(halfword *first, halfword forward)
-{
- halfword cur = *first;
- if (glyph_scale(cur) == glyph_scale(forward) && glyph_x_scale(cur) == glyph_x_scale(forward) && glyph_y_scale(cur) == glyph_y_scale(forward)) {
- halfword slot;
- halfword type = tex_valid_ligature(cur, forward, &slot);
- if (type >= 0) {
- int move_after = (type & 0x0C) >> 2;
- int keep_right = (type & 0x01) != 0;
- int keep_left = (type & 0x02) != 0;
- halfword parent = (glyph_character(cur) >= 0) ? cur : ((glyph_character(forward) >= 0) ? forward : null);
- halfword ligature = tex_new_glyph_node(glyph_ligature_subtype, glyph_font(cur), slot, parent);
- if (keep_left) {
- tex_couple_nodes(cur, ligature);
- if (move_after) {
- move_after--;
- cur = ligature;
- }
- } else {
- halfword prev = node_prev(cur);
- tex_uncouple_node(cur);
- tex_flush_node(cur);
- tex_couple_nodes(prev, ligature);
- cur = ligature;
+static int tex_aux_try_ligature(halfword *first, halfword second, halfword *nextone)
+{
+ halfword current = *first;
+ halfword slot;
+ halfword type = tex_valid_ligature(current, second, &slot);
+ if (type >= 0) {
+ int move_after = (type & 0x0C) >> 2;
+ int keep_right = (type & 0x01) != 0;
+ int keep_left = (type & 0x02) != 0;
+ halfword next = node_next(second);
+ if (keep_left && keep_right) {
+ halfword ligature = tex_copy_node(current);
+ glyph_character(ligature) = slot;
+ tex_couple_nodes(*first, ligature);
+ tex_couple_nodes(ligature, second);
+ if (nextone) {
+ *nextone = second;
}
- if (keep_right) {
- tex_couple_nodes(ligature, forward);
- if (move_after) {
- move_after--;
- cur = forward;
- }
- } else {
- halfword next = node_next(forward);
- tex_uncouple_node(forward);
- tex_flush_node(forward);
- if (next) {
- tex_couple_nodes(ligature, next);
- }
+ } else if (keep_right) {
+ glyph_character(*first) = slot;
+ if (nextone) {
+ *nextone = second;
+ }
+ } else if (keep_left) {
+ glyph_character(second) = slot;
+ if (nextone) {
+ *nextone = second;
+ }
+ } else {
+ glyph_character(*first) = slot;
+ tex_uncouple_node(second);
+ tex_flush_node(second);
+ tex_try_couple_nodes(*first, next);
+ if (nextone) {
+ *nextone = *first;
+ }
+ }
+ /* untested */
+ if (nextone) {
+ while (move_after-- > 0 && *nextone) {
+ *nextone = node_next(*nextone);
}
- *first = cur;
- return 1;
}
+ return 1;
+ } else {
+ return 0;
}
- return 0;
}
-/*tex
-
- There shouldn't be any ligatures here - we only add them at the end of |xxx_break| in a |DISC-1
- - DISC-2| situation and we stop processing |DISC-1| (we continue with |DISC-1|'s |post_| and
- |no_break|.
-
-*/
+static void tex_aux_handle_ligature_list(halfword target, int location)
+{
+ halfword node = tex_aux_discretionary_node(target, location);
+ halfword head = node_head(node);
+ halfword tail = node_tail(node);
+ if (head && head != tail) {
+ halfword current = head;
+ while (node_next(current)) {
+ halfword next = node_next(current);
+ int ishead = current == head;
+ halfword nextone = next;
+ if (tex_aux_same_font_properties(current, next) && tex_aux_try_ligature(&current, next, &nextone)) {
+ if (ishead) {
+ head = current;
+ node_head(node) = current;
+ }
+ current = nextone;
+ } else {
+ current = next;
+ }
+ }
+ node_tail(node) = current;
+ }
+}
-static halfword tex_aux_handle_ligature_nesting(halfword root, halfword cur)
+static void tex_aux_handle_ligature_pair(halfword target, int location)
{
- if (cur) {
- while (node_next(cur)) {
- halfword fwd = node_next(cur);
- if (node_type(cur) == glyph_node && node_type(fwd) == glyph_node && glyph_font(cur) == glyph_font(fwd) && tex_aux_try_ligature(&cur, fwd)) {
- continue;
+ halfword node = tex_aux_discretionary_node(target, location);
+ halfword head = node_head(node);
+ halfword tail = node_tail(node);
+ if (head && head != tail) {
+ halfword previous = node_prev(tail);
+ int ishead = previous == head;
+ if (tex_aux_same_font_properties(previous, tail) && tex_aux_try_ligature(&previous, tail, NULL)) {
+ if (ishead) {
+ head = previous;
+ node_head(node) = previous;
}
- cur = node_next(cur);
+ node_tail(node) = previous;
}
- node_tail(root) = cur;
}
- return root;
}
/*tex
@@ -1083,207 +1167,204 @@ static halfword tex_aux_handle_ligature_nesting(halfword root, halfword cur)
have (any kind of) discretionaries. It is still on my agenda to look into nested discretionaries
i.e. discs nodes in disc fields but it might never result in useable code.
+ Todo: check this boundary mess (check for subtype too).
+ Todo: maybe get rid of weird ligatures, turn boundary into space and such.
+
*/
-static halfword tex_aux_handle_ligature_word(halfword cur)
+static halfword tex_aux_handle_ligature_word(halfword current)
{
halfword right = null;
- if (node_type(cur) == boundary_node) {
- halfword prev = node_prev(cur);
- halfword fwd = node_next(cur);
+ halfword last = null; /* cf LuaTeX patch, an ancient border case buglet. */
+ if (node_type(current) == boundary_node) {
+ halfword previous = node_prev(current);
+ halfword next = node_next(current);
/*tex There is no need to uncouple |cur|, it is freed. */
- tex_flush_node(cur);
- if (fwd) {
- tex_couple_nodes(prev, fwd);
- if (node_type(fwd) != glyph_node) {
- return prev;
+ tex_flush_node(current);
+ if (next) {
+ tex_couple_nodes(previous, next);
+ if (node_type(next) != glyph_node) {
+ return previous;
} else {
- cur = fwd;
+ current = next;
}
} else {
- node_next(prev) = fwd;
- return prev;
+ node_next(previous) = next;
+ return previous;
}
- } else if (font_has_left_boundary(glyph_font(cur))) {
- halfword prev = node_prev(cur);
- halfword p = tex_new_glyph_node(glyph_unset_subtype, glyph_font(cur), left_boundary_char, cur);
- tex_couple_nodes(prev, p);
- tex_couple_nodes(p, cur);
- cur = p;
+ } else if (node_type(current) == glyph_node && font_has_left_boundary(glyph_font(current))) {
+ halfword previous = node_prev(current);
+ halfword glyph = tex_new_glyph_node(glyph_unset_subtype, glyph_font(current), left_boundary_char, current);
+ tex_couple_nodes(previous, glyph);
+ tex_couple_nodes(glyph, current);
+ current = glyph;
}
- if (font_has_right_boundary(glyph_font(cur))) {
- right = tex_new_glyph_node(glyph_unset_subtype, glyph_font(cur), right_boundary_char, cur);
+ if (node_type(current) == glyph_node && font_has_right_boundary(glyph_font(current))) {
+ right = tex_new_glyph_node(glyph_unset_subtype, glyph_font(current), right_boundary_char, current);
}
- /* todo: switch */
+ // tex_print_node_list(current, "GOING",max_integer, max_integer);
while (1) {
- halfword t = node_type(cur);
+ halfword currenttype = node_type(current);
/*tex A glyph followed by \unknown */
- if (t == glyph_node) {
- halfword fwd = node_next(cur);
- if (fwd) {
- t = node_type(fwd);
- if (t == glyph_node) {
- /*tex a glyph followed by a glyph */
- if (glyph_font(cur) != glyph_font(fwd)) {
+ if (currenttype == glyph_node) {
+ if (tex_aux_apply_base_ligaturing(current)) {
+ halfword forward = node_next(current);
+ if (forward) {
+ halfword forwardtype = node_type(forward);
+ if (forwardtype == glyph_node) {
+ if (! tex_aux_apply_base_ligaturing(forward)) {
+ // break;
+ } else if (! tex_aux_same_font_properties(current, forward)) {
+ // break;
+ } else {
+ halfword nextone = current;
+ if (tex_aux_try_ligature(&current, forward, &nextone)) {
+ current = nextone;
+ continue;
+ }
+ }
+ } else if (forwardtype == disc_node) {
+ /*tex a glyph followed by a disc */
+ halfword pre = disc_pre_break_head(forward);
+ halfword replace = disc_no_break_head(forward);
+ halfword next;
+ /*tex Check on: |a{b?}{?}{?}| and |a+b=>B| : |{B?}{?}{a?}| */
+ /*tex Check on: |a{?}{?}{b?}| and |a+b=>B| : |{a?}{?}{B?}| */
+ if (tex_aux_found_ligature(current, pre) || tex_aux_found_ligature(current, replace)) {
+ /*tex Move |cur| from before disc to skipped part */
+ halfword previous = node_prev(current);
+ tex_uncouple_node(current);
+ tex_couple_nodes(previous, forward);
+ tex_aux_discretionary_prepend(forward, no_break_code, current);
+ tex_aux_discretionary_prepend(forward, pre_break_code, tex_copy_node(current));
+ /*tex As we have removed cur, we need to start again. */
+ current = previous;
+ }
+ /*tex Check on: |a{?}{?}{}b| and |a+b=>B| : |{a?}{?b}{B}|. */
+ next = node_next(forward);
+ if (! replace && tex_aux_found_ligature(current, next)) {
+ /*tex Move |cur| from before |disc| to |no_break| part. */
+ halfword previous = node_prev(current);
+ halfword tail = node_next(next);
+ tex_uncouple_node(current);
+ tex_couple_nodes(previous, forward);
+ tex_aux_discretionary_prepend(forward, pre_break_code, tex_copy_node(current));
+ /*tex Move next from after disc to |no_break| part. */
+ tex_uncouple_node(next);
+ tex_try_couple_nodes(forward, tail);
+ /*tex We {\em know} this works. */
+ tex_couple_nodes(current, next);
+ /*tex Make sure the list is correct. */
+ tex_aux_discretionary_append(forward, post_break_code, tex_copy_node(next));
+ /*tex As we have removed cur, we need to start again. */
+ current = previous;
+ }
+ /*tex We are finished with the |pre_break|. */
+ tex_aux_handle_ligature_list(forward, pre_break_code);
+ } else if (forwardtype == boundary_node) {
+ halfword next = node_next(forward);
+ tex_try_couple_nodes(current, next);
+ tex_flush_node(forward);
+ if (right) {
+ /*tex Shame, didn't need it. */
+ tex_flush_node(right);
+ /*tex No need to reset |right|, we're going to leave the loop anyway. */
+ }
break;
- } else if (tex_aux_try_ligature(&cur, fwd)) {
+ } else if (right) {
+ tex_couple_nodes(current, right);
+ tex_couple_nodes(right, forward);
+ right = null;
continue;
+ } else {
+ break;
}
- } else if (t == disc_node) {
- /*tex a glyph followed by a disc */
- halfword pre = disc_pre_break_head(fwd);
- halfword nob = disc_no_break_head(fwd);
- halfword next, tail;
- /*tex Check on: |a{b?}{?}{?}| and |a+b=>B| : |{B?}{?}{a?}| */
- /*tex Check on: |a{?}{?}{b?}| and |a+b=>B| : |{a?}{?}{B?}| */
- if ((pre && node_type(pre) == glyph_node && tex_aux_found_ligature(cur, pre))
- || (nob && node_type(nob) == glyph_node && tex_aux_found_ligature(cur, nob))) {
- /*tex Move |cur| from before disc to skipped part */
- halfword prev = node_prev(cur);
- tex_uncouple_node(cur);
- tex_couple_nodes(prev, fwd);
- tex_aux_nesting_prepend(disc_no_break(fwd), cur);
- /*tex Now ligature the |pre_break|. */
- tex_aux_nesting_prepend(disc_pre_break(fwd), tex_copy_node(cur));
- /*tex As we have removed cur, we need to start again. */
- cur = prev;
- }
- /*tex Check on: |a{?}{?}{}b| and |a+b=>B| : |{a?}{?b}{B}|. */
- next = node_next(fwd);
- if ((! nob) && next && node_type(next) == glyph_node && tex_aux_found_ligature(cur, next)) {
- /*tex Move |cur| from before |disc| to |no_break| part. */
- halfword prev = node_prev(cur);
- tex_uncouple_node(cur);
- tex_couple_nodes(prev, fwd);
- /*tex We {\em know} it's empty. */
- tex_couple_nodes(disc_no_break(fwd), cur);
- /*tex Now copy |cur| the |pre_break|. */
- tex_aux_nesting_prepend(disc_pre_break(fwd), tex_copy_node(cur));
- /*tex Move next from after disc to |no_break| part. */
- tail = node_next(next);
- tex_uncouple_node(next);
- tex_try_couple_nodes(fwd, tail);
- /*tex We {\em know} this works. */
- tex_couple_nodes(cur, next);
- /*tex Make sure the list is correct. */
- disc_no_break_tail(fwd) = next;
- /*tex Now copy next to the |post_break|. */
- tex_aux_nesting_append(disc_post_break(fwd), tex_copy_node(next));
- /*tex As we have removed cur, we need to start again. */
- cur = prev;
- }
- /*tex We are finished with the |pre_break|. */
- tex_aux_handle_ligature_nesting(disc_pre_break(fwd), disc_pre_break_head(fwd));
- } else if (t == boundary_node) {
- halfword next = node_next(fwd);
- tex_try_couple_nodes(cur, next);
- tex_flush_node(fwd);
+ } else {
+ /*tex The last character of a paragraph. */
if (right) {
- /*tex Shame, didn't need it. */
- tex_flush_node(right);
- /*tex No need to reset |right|, we're going to leave the loop anyway. */
+ /*tex |par| prohibits the use of |couple_nodes| here. */
+ tex_try_couple_nodes(current, right);
+ right = null;
+ continue;
+ } else {
+ break;
}
- break;
- } else if (right) {
- tex_couple_nodes(cur, right);
- tex_couple_nodes(right, fwd);
- right = null;
- continue;
- } else {
- break;
- }
- } else {
- /*tex The last character of a paragraph. */
- if (right) {
- /*tex |par| prohibits the use of |couple_nodes| here. */
- tex_try_couple_nodes(cur, right);
- right = null;
- continue;
- } else {
- break;
}
+ /*tex A discretionary followed by \unknown */
}
- /*tex A discretionary followed by \unknown */
- } else if (t == disc_node) {
+ } else if (currenttype == disc_node) {
/*tex If |{?}{x}{?}| or |{?}{?}{y}| then: */
- if (disc_no_break_head(cur) || disc_post_break_head(cur)) {
- halfword fwd;
- if (disc_post_break_head(cur)) {
- tex_aux_handle_ligature_nesting(disc_post_break(cur), disc_post_break_head(cur));
+ if (disc_no_break_head(current) || disc_post_break_head(current)) {
+ /*tex Is this nesting okay (and needed)? */
+ halfword forward;
+ if (disc_post_break_head(current)) {
+ tex_aux_handle_ligature_list(current, post_break_code);
}
- if (disc_no_break_head(cur)) {
- tex_aux_handle_ligature_nesting(disc_no_break(cur), disc_no_break_head(cur));
+ if (disc_no_break_head(current)) {
+ tex_aux_handle_ligature_list(current, no_break_code);
}
- fwd = node_next(cur);
- while (fwd) {
- if (node_type(fwd) == glyph_node) {
- halfword nob = disc_no_break_tail(cur);
- halfword pst = disc_post_break_tail(cur);
- if ((! nob || ! tex_aux_found_ligature(nob, fwd)) && (! pst || ! tex_aux_found_ligature(pst, fwd))) {
- break;
- } else {
- halfword next = node_next(fwd);
- tex_aux_nesting_append(disc_no_break(cur), tex_copy_node(fwd));
- tex_aux_handle_ligature_nesting(disc_no_break(cur), nob);
- tex_uncouple_node(fwd);
- tex_try_couple_nodes(cur, next);
- tex_aux_nesting_append(disc_post_break(cur), fwd);
- tex_aux_handle_ligature_nesting(disc_post_break(cur), pst);
- fwd = node_next(cur);
- }
+ forward = node_next(current);
+ while (forward && node_type(forward) == glyph_node && tex_aux_apply_base_ligaturing(forward)) {
+ halfword replace = disc_no_break_tail(current);
+ halfword post = disc_post_break_tail(current);
+ if (tex_aux_found_ligature(replace, forward) || tex_aux_found_ligature(post, forward)) {
+ tex_try_couple_nodes(current, node_next(forward));
+ tex_uncouple_node(forward);
+ tex_aux_discretionary_append(current, no_break_code, tex_copy_node(forward));
+ tex_aux_handle_ligature_pair(current, no_break_code);
+ tex_aux_handle_ligature_pair(current, post_break_code);
+ forward = node_next(current);
} else {
break;
}
}
- if (fwd && node_type(fwd) == disc_node) {
+ if (forward && node_type(forward) == disc_node) {
/*tex This only deals with simple pre-only discretionaries and a following glyph. */
- halfword next = node_next(fwd);
+ halfword next = node_next(forward);
if (next
- && ! disc_no_break_head(fwd)
- && ! disc_post_break_head(fwd)
+ && ! disc_no_break_head(forward)
+ && ! disc_post_break_head(forward)
&& node_type(next) == glyph_node
- && ((disc_post_break_tail(cur) && tex_aux_found_ligature(disc_post_break_tail(cur), next)) ||
- (disc_no_break_tail (cur) && tex_aux_found_ligature(disc_no_break_tail (cur), next)))) {
+ && tex_aux_apply_base_ligaturing(next)
+ && ((disc_post_break_tail(current) && tex_aux_found_ligature(disc_post_break_tail(current), next)) ||
+ (disc_no_break_tail (current) && tex_aux_found_ligature(disc_no_break_tail (current), next)))) {
halfword last = node_next(next);
tex_uncouple_node(next);
- tex_try_couple_nodes(fwd, last);
+ tex_try_couple_nodes(forward, last);
/*tex Just a hidden flag, used for (base mode) experiments. */
if (hyphenation_permitted(hyphenation_mode_par, lazy_ligatures_hyphenation_mode)) {
/*tex f-f-i -> f-fi */
- halfword tail = disc_no_break_tail(cur);
- tex_aux_nesting_append(disc_no_break(cur), tex_copy_node(next));
- tex_aux_handle_ligature_nesting(disc_no_break(cur), tail);
- tail = disc_post_break_tail(cur);
- tex_aux_nesting_append(disc_post_break(cur), next);
- tex_aux_handle_ligature_nesting(disc_post_break(cur), tail);
- tex_try_couple_nodes(node_prev(fwd), node_next(fwd));
- tex_flush_node(fwd);
+ tex_aux_discretionary_append(current, no_break_code, tex_copy_node(next));
+ tex_aux_handle_ligature_pair(current,no_break_code);
+ tex_aux_discretionary_append(current, post_break_code, next);
+ tex_aux_handle_ligature_pair(current,post_break_code);
+ tex_try_couple_nodes(node_prev(forward), node_next(forward));
+ tex_flush_node(forward);
} else {
/*tex f-f-i -> ff-i : |{a-}{b}{AB} {-}{c}{}| => |{AB-}{c}{ABc}| */
- tex_aux_nesting_append(disc_post_break(fwd), tex_copy_node(next));
- if (disc_no_break_head(cur)) {
- halfword tail;
- tex_aux_nesting_prepend_list(disc_no_break(fwd), tex_copy_node_list(disc_no_break_head(cur), null));
- tail = disc_no_break_tail(fwd);
- tex_aux_nesting_append(disc_no_break(fwd), next);
- tex_aux_handle_ligature_nesting(disc_no_break(fwd), tail);
- tex_aux_nesting_prepend_list(disc_pre_break(fwd), tex_copy_node_list(disc_no_break_head(cur), null));
+ tex_aux_discretionary_append(forward, post_break_code, tex_copy_node(next));
+ if (disc_no_break_head(current)) {
+ tex_aux_nesting_prepend_list(forward, no_break_code, disc_no_break_head(current));
+ tex_aux_discretionary_append(forward, no_break_code, next);
+ tex_aux_handle_ligature_pair(forward, no_break_code);
+ tex_aux_nesting_prepend_list(forward, pre_break_code, disc_no_break_head(current));
}
- tex_try_couple_nodes(node_prev(cur), node_next(cur));
- tex_flush_node(cur);
- cur = fwd;
+ tex_try_couple_nodes(node_prev(current), node_next(current));
+ tex_flush_node(current);
+ current = forward;
}
}
}
}
} else {
/*tex We have glyph nor disc. */
- return cur;
+ return last;
}
/*tex Goto the next node, where |\par| allows |node_next(cur)| to be NULL. */
- cur = node_next(cur);
+ last = current;
+ current = node_next(current);
}
- return cur;
+ return current;
}
/*tex The return value is the new tail, head should be a dummy: */
@@ -1293,27 +1374,35 @@ halfword tex_handle_ligaturing(halfword head, halfword tail)
if (node_next(head)) {
/*tex A trick to allow explicit |node == null| tests. */
halfword save_tail = null;
- halfword cur, prev;
+ halfword current, previous;
if (tail) {
save_tail = node_next(tail);
node_next(tail) = null;
}
- prev = head;
- cur = node_next(prev);
- while (cur) {
- if (node_type(cur) == glyph_node || node_type(cur) == boundary_node) {
- cur = tex_aux_handle_ligature_word(cur);
+ previous = head;
+ current = node_next(previous);
+ while (current) {
+ switch(node_type(current)) {
+ case glyph_node:
+ if (tex_aux_apply_base_ligaturing(current)) {
+ current = tex_aux_handle_ligature_word(current);
+ }
+ break;
+ case disc_node:
+ case boundary_node:
+ current = tex_aux_handle_ligature_word(current);
+ break;
+ }
+ previous = current;
+ if (current) {
+ current = node_next(current);
}
- prev = cur;
- cur = node_next(cur);
}
- if (! prev) {
- prev = tail;
+ if (! previous) {
+ previous = tex_tail_of_node_list(head);
}
- tex_try_couple_nodes(prev, save_tail);
- // if (tail) {
- // }
- return prev;
+ tex_try_couple_nodes(previous, save_tail);
+ return previous;
} else {
return tail;
}
@@ -1321,13 +1410,9 @@ halfword tex_handle_ligaturing(halfword head, halfword tail)
/*tex Kerning starts here: */
-static void tex_aux_add_kern_before(halfword left, halfword right)
+static halfword tex_aux_add_kern_before(halfword left, halfword right)
{
- if (
- glyph_font(left) == glyph_font(right) &&
- glyph_scale(left) == glyph_scale(right) &&
- glyph_x_scale(left) == glyph_x_scale(right) &&
- glyph_y_scale(left) == glyph_y_scale(right) &&
+ if (tex_aux_same_font_properties(left, right) &&
! tex_has_glyph_option(left, glyph_option_no_right_kern) &&
! tex_has_glyph_option(right, glyph_option_no_left_kern) &&
tex_has_kern(glyph_font(left), glyph_character(left))
@@ -1335,21 +1420,19 @@ static void tex_aux_add_kern_before(halfword left, halfword right)
scaled k = tex_raw_get_kern(glyph_font(left), glyph_character(left), glyph_character(right));
if (k) {
scaled kern = tex_new_kern_node(k, font_kern_subtype);
- halfword prev = node_prev(right);
- tex_couple_nodes(prev, kern);
+ halfword previous = node_prev(right);
+ tex_couple_nodes(previous, kern);
tex_couple_nodes(kern, right);
tex_attach_attribute_list_copy(kern, left);
+ return kern;
}
}
+ return null;
}
-static void tex_aux_add_kern_after(halfword left, halfword right, halfword aft)
+static halfword tex_aux_add_kern_after(halfword left, halfword right, halfword after)
{
- if (
- glyph_font(left) == glyph_font(right) &&
- glyph_scale(left) == glyph_scale(right) &&
- glyph_x_scale(left) == glyph_x_scale(right) &&
- glyph_y_scale(left) == glyph_y_scale(right) &&
+ if (tex_aux_same_font_properties(left, right) &&
! tex_has_glyph_option(left, glyph_option_no_right_kern) &&
! tex_has_glyph_option(right, glyph_option_no_left_kern) &&
tex_has_kern(glyph_font(left), glyph_character(left))
@@ -1357,78 +1440,96 @@ static void tex_aux_add_kern_after(halfword left, halfword right, halfword aft)
scaled k = tex_raw_get_kern(glyph_font(left), glyph_character(left), glyph_character(right));
if (k) {
scaled kern = tex_new_kern_node(k, font_kern_subtype);
- halfword next = node_next(aft);
- tex_couple_nodes(aft, kern);
+ halfword next = node_next(after);
+ tex_couple_nodes(after, kern);
tex_try_couple_nodes(kern, next);
- tex_attach_attribute_list_copy(kern, aft);
+ tex_attach_attribute_list_copy(kern, after);
+ return kern;
}
}
+ return null;
}
-static void tex_aux_do_handle_kerning(halfword root, halfword init_left, halfword init_right)
+static halfword tex_aux_do_handle_kerning(halfword root, halfword init_left, halfword init_right);
+
+static void tex_aux_handle_discretionary_kerning(halfword target, int location, halfword left, halfword right)
{
- halfword cur = node_next(root);
- if (cur) {
+ halfword node = tex_aux_discretionary_node(target, location);
+ if (node_head(node)) {
+ halfword kern = tex_aux_do_handle_kerning(node_head(node), left, right);
+ if (kern) {
+ node_head(node) = kern;
+ node_tail(node) = tex_tail_of_node_list(node_head(node));
+ }
+ }
+}
+
+static halfword tex_aux_do_handle_kerning(halfword root, halfword init_left, halfword init_right)
+{
+ // halfword head = node_next(root); // todo: get rid of this one
+ halfword head = root; // todo: get rid of this one
+ halfword current = head;
+ halfword initial = null;
+ if (current) {
halfword left = null;
- if (node_type(cur) == glyph_node) {
+ if (node_type(current) == glyph_node && tex_aux_apply_base_kerning(current)) {
if (init_left) {
- tex_aux_add_kern_before(init_left, cur);
+ halfword kern = tex_aux_add_kern_before(init_left, current);
+ if (current == head) {
+ initial = kern;
+ }
}
- left = cur;
+ left = current;
}
- cur = node_next(cur);
- while (cur) {
- halfword t = node_type(cur);
- if (t == glyph_node) {
- if (left) {
- tex_aux_add_kern_before(left, cur);
- if (glyph_character(left) < 0) {
- halfword prev = node_prev(left);
- tex_couple_nodes(prev, cur);
- tex_flush_node(left);
+ current = node_next(current);
+ while (current) {
+ halfword currenttype = node_type(current);
+ if (currenttype == glyph_node) {
+ if (tex_aux_apply_base_kerning(current)) {
+ if (left) {
+ tex_aux_add_kern_before(left, current);
+ if (glyph_character(left) < 0) {
+ halfword previous = node_prev(left);
+ tex_couple_nodes(previous, current);
+ tex_flush_node(left);
+ }
}
+ left = current;
+ } else {
+ left = null;
}
- left = cur;
} else {
- if (t == disc_node) {
- halfword right = node_type(node_next(cur)) == glyph_node ? node_next(cur) : null;
- tex_aux_do_handle_kerning(disc_pre_break(cur), left, null);
- if (disc_pre_break_head(cur)) {
- disc_pre_break_tail(cur) = tex_tail_of_node_list(disc_pre_break_head(cur));
- }
- tex_aux_do_handle_kerning(disc_post_break(cur), null, right);
- if (disc_post_break_head(cur)) {
- disc_post_break_tail(cur) = tex_tail_of_node_list(disc_post_break_head(cur));
- }
- tex_aux_do_handle_kerning(disc_no_break(cur), left, right);
- if (disc_no_break_head(cur)) {
- disc_no_break_tail(cur) = tex_tail_of_node_list(disc_no_break_head(cur));
- }
+ if (currenttype == disc_node) {
+ halfword next = node_next(current);
+ halfword right = node_type(next) == glyph_node && tex_aux_apply_base_kerning(next) ? next : null;
+ tex_aux_handle_discretionary_kerning(current, pre_break_code, left, null);
+ tex_aux_handle_discretionary_kerning(current, post_break_code, null, right);
+ tex_aux_handle_discretionary_kerning(current, no_break_code, left, right);
}
if (left) {
- if (glyph_character(left) < 0) {
- halfword prev = node_prev(left);
- tex_couple_nodes(prev, cur);
+ if (glyph_character(left) < 0) { /* boundary ? */
+ halfword previous = node_prev(left);
+ tex_couple_nodes(previous, current);
tex_flush_node(left);
}
left = null;
}
}
- cur = node_next(cur);
+ current = node_next(current);
}
if (left) {
if (init_right) {
tex_aux_add_kern_after(left, init_right, left);
}
if (glyph_character(left) < 0) {
- halfword prev = node_prev(left);
+ halfword previous = node_prev(left);
halfword next = node_next(left);
if (next) {
- tex_couple_nodes(prev, next);
+ tex_couple_nodes(previous, next);
node_tail(root) = next;
- } else if (prev != root) {
- node_next(prev) = null;
- node_tail(root) = prev;
+ } else if (previous != root) {
+ node_next(previous) = null;
+ node_tail(root) = previous;
} else {
node_next(root) = null;
node_tail(root) = null;
@@ -1440,6 +1541,7 @@ static void tex_aux_do_handle_kerning(halfword root, halfword init_left, halfwor
tex_aux_add_kern_after(init_left, init_right, root);
node_tail(root) = node_next(root);
}
+ return initial;
}
halfword tex_handle_kerning(halfword head, halfword tail)
@@ -1449,7 +1551,7 @@ halfword tex_handle_kerning(halfword head, halfword tail)
save_link = node_next(tail);
node_next(tail) = null;
node_tail(head) = tail;
- tex_aux_do_handle_kerning(head, null, null);
+ tex_aux_do_handle_kerning(node_next(head), null, null); /*tex There is no need to check initial here. */
tail = node_tail(head);
if (tex_valid_node(save_link)) {
/* no need for check */
@@ -1457,7 +1559,7 @@ halfword tex_handle_kerning(halfword head, halfword tail)
}
} else {
node_tail(head) = null;
- tex_aux_do_handle_kerning(head, null, null);
+ tex_aux_do_handle_kerning(node_next(head), null, null); /*tex There is no need to check initial here. */
}
return tail;
}
@@ -1494,19 +1596,17 @@ halfword tex_handle_glyphrun(halfword head, halfword group, halfword direction)
if (callback_id) {
head = tex_aux_run_lua_ligkern_callback(lmt_lua_state.lua_instance, head, group, direction, callback_id);
} else {
+ // what if disc at start
tex_handle_ligaturing(head, null);
}
callback_id = lmt_callback_defined(kerning_callback);
if (callback_id) {
head = tex_aux_run_lua_ligkern_callback(lmt_lua_state.lua_instance, head, group, direction, callback_id);
} else {
- halfword nest = tex_new_node(nesting_node, unset_nesting_code);
- tex_couple_nodes(nest, head);
- tex_aux_do_handle_kerning(nest, null, null);
- head = node_next(nest);
- node_prev(head) = null;
- node_next(nest) = null;
- tex_flush_node(nest);
+ halfword kern = tex_aux_do_handle_kerning(head, null, null);
+ if (kern) {
+ head = kern;
+ }
}
}
}
@@ -1534,10 +1634,8 @@ void tex_set_cur_font(halfword g, halfword f)
}
/*tex
-
Because we do fonts in \LUA\ we can decide to drop this one and assume a definition using the
token scanner. It also avoids the filename (split) mess.
-
*/
int tex_tex_def_font(int a)
@@ -1555,7 +1653,7 @@ int tex_tex_def_font(int a)
/*tex Stated 'at' size, or negative of scaled magnification. */
scaled s = -1000;
char *fn;
- /*tex Here |a| detemines if we define global or not. */
+ /*tex Here |a| determines if we define global or not. */
if (is_global(a)) {
update_tex_font_global(u, null_font);
} else {
@@ -1603,11 +1701,9 @@ int tex_tex_def_font(int a)
}
/*tex
-
When \TEX\ wants to typeset a character that doesn't exist, the character node is not created;
thus the output routine can assume that characters exist when it sees them. The following
procedure prints a warning message unless the user has suppressed it.
-
*/
void tex_char_warning(halfword f, int c)
diff --git a/source/luametatex/source/tex/texfont.h b/source/luametatex/source/tex/texfont.h
index 994cdd894..947cdf446 100644
--- a/source/luametatex/source/tex/texfont.h
+++ b/source/luametatex/source/tex/texfont.h
@@ -324,6 +324,9 @@ extern font_state_info lmt_font_state;
typedef enum text_control_codes {
text_control_collapse_hyphens = 0x00001,
+ text_control_base_ligaturing = 0x00002,
+ text_control_base_kerning = 0x00004,
+ text_control_none_protected = 0x00008,
} text_control_codes;
# define has_font_text_control(f,c) ((font_textcontrol(f) & c) == c)
diff --git a/source/luametatex/source/tex/texinputstack.h b/source/luametatex/source/tex/texinputstack.h
index 7ae677d56..51ff2ef56 100644
--- a/source/luametatex/source/tex/texinputstack.h
+++ b/source/luametatex/source/tex/texinputstack.h
@@ -68,12 +68,12 @@ typedef struct input_file_state_info {
extern input_file_state_info input_file_state;
-static inline int input_file_value(void)
+inline static int input_file_value(void)
{
return input_file_state.forced_file ? input_file_state.forced_file : lmt_input_state.cur_input.state_file;
}
-static inline int input_line_value(void)
+inline static int input_line_value(void)
{
return input_file_state.forced_line ? input_file_state.forced_line : (input_file_state.line ? input_file_state.line : lmt_input_state.input_line);
}
diff --git a/source/luametatex/source/tex/texinserts.c b/source/luametatex/source/tex/texinserts.c
index dbd164926..3d634dd39 100644
--- a/source/luametatex/source/tex/texinserts.c
+++ b/source/luametatex/source/tex/texinserts.c
@@ -155,7 +155,7 @@ halfword tex_get_insert_distance(halfword i)
}
}
-static inline halfword tex_aux_insert_box(halfword i)
+inline static halfword tex_aux_insert_box(halfword i)
{
if (tex_valid_insert_id(i)) {
return lmt_insert_state.mode == index_insert_mode ? insert_content(i) : lmt_insert_state.inserts[i].content;
diff --git a/source/luametatex/source/tex/texlinebreak.c b/source/luametatex/source/tex/texlinebreak.c
index 2e0c945a7..7c9e6b768 100644
--- a/source/luametatex/source/tex/texlinebreak.c
+++ b/source/luametatex/source/tex/texlinebreak.c
@@ -1372,7 +1372,7 @@ halfword tex_badness(scaled t, scaled s)
}
}
-static inline void tex_split_line_break_criterium(halfword criterium, halfword *semi_tight, halfword *decent, halfword *semi_loose, halfword *loose) {
+inline static void tex_split_line_break_criterium(halfword criterium, halfword *semi_tight, halfword *decent, halfword *semi_loose, halfword *loose) {
*semi_tight = (criterium >> 24) & 0x7F;
*decent = (criterium >> 16) & 0x7F;
*semi_loose = (criterium >> 8) & 0x7F;
@@ -1391,7 +1391,7 @@ static inline void tex_split_line_break_criterium(halfword criterium, halfword *
}
}
-static inline halfword tex_normalized_loose_badness(halfword b, halfword loose, halfword semi_loose, halfword decent)
+inline static halfword tex_normalized_loose_badness(halfword b, halfword loose, halfword semi_loose, halfword decent)
{
// if (b > loose_criterium) {
// return very_loose_fit;
@@ -1411,7 +1411,7 @@ static inline halfword tex_normalized_loose_badness(halfword b, halfword loose,
}
}
-static inline halfword tex_normalized_tight_badness(halfword b, halfword decent, halfword semi_tight)
+inline static halfword tex_normalized_tight_badness(halfword b, halfword decent, halfword semi_tight)
{
// if (b > decent_criterium) {
// return tight_fit;
diff --git a/source/luametatex/source/tex/texmaincontrol.c b/source/luametatex/source/tex/texmaincontrol.c
index b0a9d2a4b..6de36d7ee 100644
--- a/source/luametatex/source/tex/texmaincontrol.c
+++ b/source/luametatex/source/tex/texmaincontrol.c
@@ -68,7 +68,7 @@ main_control_state_info lmt_main_control_state = {
A few helpers:
*/
-inline scaled tex_aux_checked_dimen1(scaled v)
+inline static scaled tex_aux_checked_dimen1(scaled v)
{
if (v > max_dimen) {
return max_dimen;
@@ -79,7 +79,7 @@ inline scaled tex_aux_checked_dimen1(scaled v)
}
}
-inline scaled tex_aux_checked_dimen2(scaled v)
+inline static scaled tex_aux_checked_dimen2(scaled v)
{
if (v > max_dimen) {
return max_dimen;
@@ -475,6 +475,25 @@ static void tex_aux_run_relax(void) {
return;
}
+static void tex_aux_run_active(void) {
+// if (lmt_input_state.scanner_status == scanner_is_tolerant || lmt_input_state.scanner_status == scanner_is_matching) {
+// cur_cs = tex_active_to_cs(cur_chr, ! lmt_hash_state.no_new_cs);
+// cur_cmd = eq_type(cur_cs);
+// cur_chr = eq_value(cur_cs);
+// tex_x_token();
+// } else
+ if ((cur_mode == mmode || lmt_nest_state.math_mode) && tex_check_active_math_char(cur_chr)) {
+ /*tex We have an intercept. */
+ tex_back_input(cur_tok);
+ } else {
+ cur_cs = tex_active_to_cs(cur_chr, ! lmt_hash_state.no_new_cs);
+ cur_cmd = eq_type(cur_cs);
+ cur_chr = eq_value(cur_cs);
+ tex_x_token();
+ tex_back_input(cur_tok);
+ }
+}
+
/*tex
|ignore_spaces| is a special case: after it has acted, |get_x_token| has already fetched the
@@ -1664,7 +1683,7 @@ void tex_local_control(int obeymode)
tex_unsave_full_scanner_status(saved_full_status);
}
-inline int tex_aux_is_iterator_value(halfword tokeninfo)
+inline static int tex_aux_is_iterator_value(halfword tokeninfo)
{
if (tokeninfo >= cs_token_flag) {
halfword cs = tokeninfo - cs_token_flag;
@@ -3543,7 +3562,7 @@ inline static void tex_aux_update_register(int a, int level, halfword index, hal
if ((register_attribute_number(index)) > lmt_node_memory_state.max_used_attribute) {
lmt_node_memory_state.max_used_attribute = register_attribute_number(index);
}
- change_attribute_register(a, index, value);
+ tex_change_attribute_register(a, index, value);
tex_word_define(a, index, value);
break;
case dimen_val_level:
@@ -4497,9 +4516,9 @@ static void tex_aux_set_let(int a, int force)
case let_charcode_code:
/*tex |\letcharcode| (todo: protection) */
{
- halfword v = tex_scan_int(0, NULL);
- if (v > 0) {
- p = tex_active_to_cs(v, 1);
+ halfword character = tex_scan_int(0, NULL);
+ if (character > 0) {
+ p = tex_active_to_cs(character, 1);
do {
tex_get_token();
} while (cur_cmd == spacer_cmd);
@@ -4773,6 +4792,13 @@ static void tex_aux_set_define_char_code(int a) /* maybe make |a| already a bool
tex_set_hm_code(chr, val, global_or_local(a));
}
break;
+ case amcode_charcode:
+ {
+ halfword chr = tex_scan_char_number(0);
+ halfword val = tex_scan_category_code(1);
+ tex_set_am_code(chr, val, global_or_local(a));
+ }
+ break;
case mathcode_charcode:
tex_scan_extdef_math_code((is_global(a)) ? level_one: cur_level, tex_mathcode);
break;
@@ -5181,7 +5207,7 @@ static void tex_aux_set_internal_attr(int a)
if (internal_attribute_number(p) > lmt_node_memory_state.max_used_attribute) {
lmt_node_memory_state.max_used_attribute = internal_attribute_number(p);
}
- change_attribute_register(a, p, v);
+ tex_change_attribute_register(a, p, v);
tex_word_define(a, p, v);
}
@@ -5192,7 +5218,7 @@ static void tex_aux_set_register_attr(int a)
if (register_attribute_number(p) > lmt_node_memory_state.max_used_attribute) {
lmt_node_memory_state.max_used_attribute = register_attribute_number(p);
}
- change_attribute_register(a, p, v);
+ tex_change_attribute_register(a, p, v);
tex_word_define(a, p, v);
}
@@ -5488,6 +5514,15 @@ void tex_get_r_token(void)
tex_get_token();
} while (cur_tok == space_token);
if (eqtb_invalid_cs(cur_cs)) {
+ if (cur_cmd == active_char_cmd) {
+ cur_cs = tex_active_to_cs(cur_chr, 1);
+ cur_cmd = eq_type(cur_cs);
+ cur_chr = eq_value(cur_cs);
+ // tex_x_token();
+ // if (! eqtb_invalid_cs(cur_cs)) {
+ return;
+ // }
+ }
if (cur_cs == 0) {
tex_back_input(cur_tok);
}
@@ -5777,7 +5812,7 @@ void tex_assign_internal_attribute_value(int a, halfword p, int val)
if (register_attribute_number(p) > lmt_node_memory_state.max_used_attribute) {
lmt_node_memory_state.max_used_attribute = register_attribute_number(p);
}
- change_attribute_register(a, p, val);
+ tex_change_attribute_register(a, p, val);
tex_word_define(a, p, val);
}
@@ -6349,6 +6384,8 @@ inline static void tex_aux_big_switch(int mode, int cmd)
register_runner(ignore_cmd, tex_aux_run_relax, tex_aux_run_relax, tex_aux_run_relax);
+ register_runner(active_char_cmd, tex_aux_run_active, tex_aux_run_active, tex_aux_run_active);
+
/*tex The next is unlikely to happen but compilers like the check. */
# if (main_control_mode == 0)
diff --git a/source/luametatex/source/tex/texmath.c b/source/luametatex/source/tex/texmath.c
index f650704cd..1424e5e03 100644
--- a/source/luametatex/source/tex/texmath.c
+++ b/source/luametatex/source/tex/texmath.c
@@ -138,7 +138,7 @@ static void tex_aux_math_math_component (halfword n, int append);
inline static mathdictval tex_fake_math_dict(halfword chr)
{
- mathdictval d = { 0, 0, 0 };
+ mathdictval d = tex_no_dict_code();
if (math_dict_properties_par || math_dict_group_par) {
d.properties = (unsigned short) math_dict_properties_par;
d.group = (unsigned short) math_dict_group_par;
@@ -957,7 +957,7 @@ int tex_show_math_node(halfword n, int threshold, int max)
return 1;
}
-inline halfword tex_aux_valid_delimiter(halfword d)
+inline static halfword tex_aux_valid_delimiter(halfword d)
{
return (d && (delimiter_small_family(d) || delimiter_small_character(d) || delimiter_large_family(d) || delimiter_large_character(d))) ? d : null;
}
@@ -1040,6 +1040,9 @@ static void tex_aux_display_radical_noad(halfword n, int threshold, int max)
if (radical_depth(n)) {
tex_print_format(", depth %D", radical_depth(n), pt_unit);
}
+ if (radical_size(n)) {
+ tex_print_format(", size %i", radical_size(n));
+ }
if (noad_source(n) != 0) {
tex_print_format(", source %i", noad_source(n));
}
@@ -1246,7 +1249,9 @@ void tex_run_math_initialize(void)
switch(cur_cmd) {
case math_shift_cmd:
/*tex |get_x_token| would fail on |\ifmmode|! */
+ lmt_nest_state.math_mode = 1;
tex_get_token();
+ lmt_nest_state.math_mode = 0;
if (cur_cmd == math_shift_cmd && cur_list.mode > nomode) {
tex_aux_enter_display_math(math_shift_cmd);
} else {
@@ -1513,7 +1518,7 @@ void tex_scan_extdef_del_code(int level, int extcode)
mathdictval tex_scan_mathdict(void)
{
- mathdictval d = { 0, 0, 0 }; /* use this one directly */
+ mathdictval d = tex_no_dict_code(); /* use this one directly */
d.properties = (unsigned short) tex_scan_math_properties_number();
d.group = (unsigned short) tex_scan_math_group_number();
d.index = (unsigned int) tex_scan_math_index_number();
@@ -1522,7 +1527,7 @@ mathdictval tex_scan_mathdict(void)
mathcodeval tex_scan_mathchar(int extcode)
{
- mathcodeval d = { 0, 0, 0 }; /* use this one directly */
+ mathcodeval d = tex_no_math_code(); /* use this one directly */
switch (extcode) {
case tex_mathcode:
/*tex |"<4bits><4bits><8bits>| */
@@ -1600,7 +1605,7 @@ halfword tex_new_math_dict_spec(mathdictval d, mathcodeval m, quarterword code)
mathcodeval tex_get_math_spec(halfword s)
{
- mathcodeval m = { 0, 0, 0 };
+ mathcodeval m = tex_no_math_code();
if (s) {
m.class_value = math_spec_class(s);
m.family_value = math_spec_family(s);
@@ -1611,7 +1616,7 @@ mathcodeval tex_get_math_spec(halfword s)
mathdictval tex_get_math_dict(halfword s)
{
- mathdictval d = { 0, 0, 0 };
+ mathdictval d = tex_no_dict_code();
if (s) {
d.properties = math_spec_properties(s);
d.group = math_spec_group(s);
@@ -1666,19 +1671,114 @@ mathcodeval tex_scan_delimiter_as_mathchar(int extcode)
For some reason |$\char44$| gives an undefined |$| when we made that character active in math.
*/
-static void tex_aux_scan_active_math_char(void)
+static void tex_aux_report_active(int where, const char *what, int code, int character)
+{
+ tex_begin_diagnostic();
+ tex_print_format("[active: location %i, %s, code %i, char %i]",where, what, code, character);
+ tex_end_diagnostic();
+}
+
+static void tex_aux_append_math_char(mathcodeval mval, mathdictval dval, int automatic);
+
+int tex_check_active_math_char(int character)
+{
+ halfword code = tex_get_am_code(character);
+ if (code) {
+ switch (code) {
+ case alignment_tab_cmd:
+ case superscript_cmd:
+ case subscript_cmd:
+ cur_cmd = code;
+ cur_chr = character;
+ cur_tok = token_val(cur_cmd, cur_chr);
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(4, "control", code, character);
+ }
+ return 1;
+ case letter_cmd:
+ case other_char_cmd:
+ cur_cmd = code;
+ cur_chr = character;
+ cur_tok = token_val(cur_cmd, cur_chr);
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(4, "inject", code, character);
+ }
+ return 1;
+ default:
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(4, "ignore", code, character);
+ }
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+}
+
+int tex_pass_active_math_char(int character)
{
- cur_cs = tex_active_to_cs(cur_chr, 1);
- cur_cmd = eq_type(cur_cs);
- cur_chr = eq_value(cur_cs);
- tex_x_token();
- tex_back_input(cur_tok);
+ halfword code = tex_get_am_code(character);
+ if (code) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int tex_aux_scan_active_math_char(mathcodeval *mval, int where)
+{
+ halfword character = mval->character_value;
+ halfword code = tex_get_am_code(character);
+ if (code) {
+ switch (code) {
+ case alignment_tab_cmd:
+ case superscript_cmd:
+ case subscript_cmd:
+ cur_cmd = code;
+ cur_chr = character;
+ cur_tok = token_val(cur_cmd, cur_chr);
+ tex_back_input(cur_tok);
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(where, "control", code, character);
+ }
+ return 1;
+ case letter_cmd:
+ case other_char_cmd:
+ cur_cmd = code;
+ cur_chr = character;
+ cur_tok = token_val(cur_cmd, cur_chr);
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(where, "inject", code, character);
+ }
+ return 0;
+ default:
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(where, "ignore", code, character);
+ }
+ return 1;
+ }
+ } else if (mval->class_value == active_math_class_value) {
+ cur_cs = tex_active_to_cs(cur_chr, 1);
+ cur_cmd = eq_type(cur_cs);
+ cur_chr = eq_value(cur_cs);
+ tex_x_token();
+ tex_back_input(cur_tok);
+ if (tracing_commands_par >= 4) {
+ tex_aux_report_active(where, "active", code, character);
+ }
+ return 1;
+ } else {
+ // if (tracing_commands_par >= 4) {
+ // tex_aux_report_active(where, "keep", code, mval->character_value);
+ // }
+ return 0;
+ }
}
static int tex_aux_scan_math(halfword target, halfword style, int usetextfont, halfword toks, halfword toks_text, int nocomponent, halfword cls, halfword all)
{
- mathcodeval mval = { 0, 0, 0 };
- mathdictval dval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
+ mathdictval dval = tex_no_dict_code();
lmt_math_state.last_atom = cls;
RESTART:
do {
@@ -1694,13 +1794,12 @@ static int tex_aux_scan_math(halfword target, halfword style, int usetextfont, h
case other_char_cmd:
case char_given_cmd:
mval = tex_get_math_code(cur_chr);
- if (mval.class_value == active_math_class_value) {
- /*tex An active character is allowed here. */
- tex_aux_scan_active_math_char();
- goto RESTART;
+ if (tex_aux_scan_active_math_char(&mval, 1)) {
+ goto RESTART; /* rescan pushed back token */
+ } else {
+ dval = tex_fake_math_dict(mval.character_value);
+ break;
}
- dval = tex_fake_math_dict(mval.character_value);
- break;
// case char_number_cmd:
// /* The |\glyph| variant is accepted but no keywords here. */
// cur_chr = tex_scan_char_number();
@@ -1875,18 +1974,16 @@ static void tex_aux_append_math_fence_val(mathcodeval mval, mathdictval dval, qu
/* todo : share the next three with the regular fences */
noad_options(fence) |= noad_option_no_check;
if (class == middle_noad_subtype && cur_group != math_fence_group) {
- tex_aux_append_math_fence_val((mathcodeval) { 0, 0, 0 }, (mathdictval) { 0, 0, 0 }, open_noad_subtype);
+ tex_aux_append_math_fence_val(tex_no_math_code(), tex_no_dict_code(), open_noad_subtype);
}
tex_aux_append_math_fence(fence, class);
}
static void tex_aux_append_math_char(mathcodeval mval, mathdictval dval, int automatic)
{
- if (mval.class_value == active_math_class_value) {
- /*tex An active character is allowed here */
- tex_aux_scan_active_math_char();
- return;
- } else {
+ if (tex_aux_scan_active_math_char(&mval, 2)) {
+ return; /* rescan pushed back token */
+ } else {
if (automatic && tex_math_has_class_option(mval.class_value, auto_inject_class_option)) {
switch (mval.class_value) {
case accent_noad_subtype:
@@ -1923,10 +2020,9 @@ static void tex_aux_append_math_char(mathcodeval mval, mathdictval dval, int aut
static void tex_aux_append_math_char_in_text(mathcodeval mval, mathdictval dval)
{
(void) dval;
- if (mval.class_value == active_math_class_value) {
- /*tex An active character is allowed here. But why in text mode too. */
- tex_aux_scan_active_math_char();
- } else {
+ if (tex_aux_scan_active_math_char(&mval, 3)) {
+ return; /* rescan pushed back token */
+ } else {
halfword p = tex_new_char_node(glyph_character_subtype, tex_fam_fnt(mval.family_value, text_size), mval.character_value, 1); /* todo: data */
tex_tail_append(p);
}
@@ -1942,8 +2038,8 @@ void tex_run_math_char_number(void) {
Both |\char| and |\glyph| get the same treatment. Scanning can change |cur_chr| so we do
that first. We no longer check for active here!
*/
- mathcodeval mval = { 0, 0, 0 };
- mathdictval dval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
+ mathdictval dval = tex_no_dict_code();
cur_chr = tex_scan_char_number(0);
mval.character_value = cur_chr;
mval.family_value = (short) cur_fam_par;
@@ -2057,16 +2153,16 @@ int tex_scan_math_code_val(halfword code, mathcodeval *mval, mathdictval *dval)
}
void tex_run_text_math_char_number(void) {
- mathcodeval mval = { 0, 0, 0 };
- mathdictval dval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
+ mathdictval dval = tex_no_dict_code();
if (tex_scan_math_code_val(cur_chr, &mval, &dval)) {
tex_aux_append_math_char_in_text(mval, dval);
}
}
void tex_run_math_math_char_number(void) {
- mathcodeval mval = { 0, 0, 0 };
- mathdictval dval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
+ mathdictval dval = tex_no_dict_code();
if (tex_scan_math_code_val(cur_chr, &mval, &dval)) {
tex_aux_append_math_char(mval, dval, 1);
}
@@ -2075,10 +2171,10 @@ void tex_run_math_math_char_number(void) {
void tex_run_math_delimiter_number(void) {
switch (cur_chr) {
case math_delimiter_code:
- tex_aux_append_math_char(tex_scan_delimiter_as_mathchar(tex_mathcode), (mathdictval) { 0, 0, 0 }, 0);
+ tex_aux_append_math_char(tex_scan_delimiter_as_mathchar(tex_mathcode), tex_no_dict_code(), 0);
break;
case math_udelimiter_code:
- tex_aux_append_math_char(tex_scan_delimiter_as_mathchar(umath_mathcode), (mathdictval) { 0, 0, 0 }, 0);
+ tex_aux_append_math_char(tex_scan_delimiter_as_mathchar(umath_mathcode), tex_no_dict_code(), 0);
break;
}
}
@@ -2532,7 +2628,7 @@ void tex_run_math_radical(void)
}
break;
case 's': case 'S':
- switch (tex_scan_character("toTO", 0, 0, 0)) {
+ switch (tex_scan_character("itoITO", 0, 0, 0)) {
case 't': case 'T':
if (tex_scan_mandate_keyword("style", 2)) {
switch (code) {
@@ -2554,6 +2650,11 @@ void tex_run_math_radical(void)
noad_source(radical) = tex_scan_int(0, NULL);
}
break;
+ case 'i': case 'I':
+ if (tex_scan_mandate_keyword("size", 2)) {
+ radical_size(radical) = tex_scan_int(0, NULL);
+ }
+ break;
default:
tex_aux_show_keyword_error("style|source");
goto DONE;
@@ -3931,7 +4032,7 @@ void tex_run_math_fence(void)
break;
default:
if (cur_group != math_fence_group) {
- tex_aux_append_math_fence_val((mathcodeval) { 0, 0, 0 }, (mathdictval) { 0, 0, 0 }, open_noad_subtype);
+ tex_aux_append_math_fence_val(tex_no_math_code(), tex_no_dict_code(), open_noad_subtype);
}
switch (cur_group) {
case math_fence_group:
@@ -5578,7 +5679,7 @@ halfword tex_to_math_rules_parameter(halfword left, halfword right)
void tex_set_default_math_codes(void)
{
- mathcodeval mval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
/*tex This will remap old font families at runtime. */
mval.class_value = math_use_current_family_code;
/*tex Upright math digts come from family 0. */
diff --git a/source/luametatex/source/tex/texmath.h b/source/luametatex/source/tex/texmath.h
index a522008f3..79f40c13b 100644
--- a/source/luametatex/source/tex/texmath.h
+++ b/source/luametatex/source/tex/texmath.h
@@ -282,7 +282,7 @@ typedef enum math_atom_font_options {
math_atom_math_font_option = 2,
} math_atom_font_options;
-inline int math_parameter_value_type(int n)
+inline static int math_parameter_value_type(int n)
{
if (n < last_math_parameter) {
return lmt_interface.math_parameter_values[n].type;
@@ -563,7 +563,7 @@ extern scaled tex_get_math_x_parameter_default (int style, int param, scaled d
extern scaled tex_get_math_y_parameter (int style, int param);
extern scaled tex_get_math_y_parameter_checked (int style, int param);
-extern scaled tex_get_math_y_parameter_default (int style, int paramm, scaled dflt);
+extern scaled tex_get_math_y_parameter_default (int style, int param, scaled dflt);
extern scaled tex_get_font_math_parameter (int font, int size, int param);
extern scaled tex_get_font_math_x_parameter (int font, int size, int param);
@@ -624,6 +624,9 @@ extern void tex_run_text_math_spec (void);
extern void tex_set_default_math_codes (void);
+extern int tex_check_active_math_char (int character);
+extern int tex_pass_active_math_char (int character);
+
/*tex The runners in maincontrol: */
extern void tex_run_math_left_brace (void);
diff --git a/source/luametatex/source/tex/texmathcodes.c b/source/luametatex/source/tex/texmathcodes.c
index f19cde91c..33aac71ee 100644
--- a/source/luametatex/source/tex/texmathcodes.c
+++ b/source/luametatex/source/tex/texmathcodes.c
@@ -82,7 +82,7 @@ mathcodeval tex_mathchar_from_integer(int value, int extcode)
mathcodeval tex_mathchar_from_spec(int value)
{
- mathcodeval mval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
if (value) {
mval.class_value = math_spec_class(value);
mval.family_value = math_spec_family(value);
@@ -165,7 +165,7 @@ void tex_set_math_code(int n, mathcodeval v, int level)
mathcodeval tex_get_math_code(int n)
{
sa_tree_item item;
- mathcodeval m = { 0, 0, 0 };
+ mathcodeval m = tex_no_math_code();
sa_get_item_4(lmt_mathcode_state.mathcode_head, n, &item);
if (item.uint_value == MATHCODEDEFAULT) {
m.character_value = n;
@@ -282,6 +282,14 @@ delcodeval tex_get_del_code(int n)
return d;
}
+/*tex */
+
+mathdictval tex_no_dict_code(void)
+{
+ return (mathdictval) { 0, 0, 0 };
+}
+
+
/*tex This really only works for old-style delcodes! */
int tex_get_del_code_number(int n)
diff --git a/source/luametatex/source/tex/texmathcodes.h b/source/luametatex/source/tex/texmathcodes.h
index a45132171..8017c2c65 100644
--- a/source/luametatex/source/tex/texmathcodes.h
+++ b/source/luametatex/source/tex/texmathcodes.h
@@ -74,4 +74,6 @@ extern void tex_undump_math_codes (dumpstream f);
extern void tex_free_math_codes (void);
+extern mathdictval tex_no_dict_code (void);
+
# endif
diff --git a/source/luametatex/source/tex/texmlist.c b/source/luametatex/source/tex/texmlist.c
index 0ea1f82e8..b5412872a 100644
--- a/source/luametatex/source/tex/texmlist.c
+++ b/source/luametatex/source/tex/texmlist.c
@@ -222,7 +222,7 @@ typedef enum limits_modes {
limits_horizontal_mode, // no limits
} limits_modes;
-inline void tex_math_wipe_kerns(kernset *kerns) {
+inline static void tex_math_wipe_kerns(kernset *kerns) {
if (kerns) {
kerns->topright = 0;
kerns->topleft = 0;
@@ -239,7 +239,7 @@ inline void tex_math_wipe_kerns(kernset *kerns) {
}
}
-inline void tex_math_copy_kerns(kernset *kerns, kernset *parent) {
+inline static void tex_math_copy_kerns(kernset *kerns, kernset *parent) {
if (kerns && parent) {
kerns->topright = parent->topright;
kerns->topleft = parent->topleft;
@@ -511,7 +511,7 @@ static int tex_aux_math_followed_by_italic_kern(halfword current, const char *tr
return 0;
}
-static inline int tex_aux_checked_left_kern_fnt_chr(halfword fnt, halfword chr, halfword state, halfword subtype)
+inline static int tex_aux_checked_left_kern_fnt_chr(halfword fnt, halfword chr, halfword state, halfword subtype)
{
halfword top = 0;
halfword bot = 0;
@@ -532,7 +532,7 @@ static inline int tex_aux_checked_left_kern_fnt_chr(halfword fnt, halfword chr,
}
}
-static inline int tex_aux_checked_left_kern(halfword list, halfword state, halfword subtype)
+inline static int tex_aux_checked_left_kern(halfword list, halfword state, halfword subtype)
{
if (list && node_type(list) == glyph_node) {
return tex_aux_checked_left_kern_fnt_chr(glyph_font(list), glyph_character(list), state, subtype);
@@ -541,7 +541,7 @@ static inline int tex_aux_checked_left_kern(halfword list, halfword state, halfw
}
}
-static inline int tex_aux_checked_right_kern_fnt_chr(halfword fnt, halfword chr, halfword state, halfword subtype)
+inline static int tex_aux_checked_right_kern_fnt_chr(halfword fnt, halfword chr, halfword state, halfword subtype)
{
halfword top = 0;
halfword bot = 0;
@@ -562,7 +562,7 @@ static inline int tex_aux_checked_right_kern_fnt_chr(halfword fnt, halfword chr,
}
}
-static inline int tex_aux_checked_right_kern(halfword list, halfword state, halfword subtype)
+inline static int tex_aux_checked_right_kern(halfword list, halfword state, halfword subtype)
{
if (list && node_type(list) == glyph_node) {
return tex_aux_checked_right_kern_fnt_chr(glyph_font(list), glyph_character(list), state, subtype);
@@ -2472,6 +2472,12 @@ static void tex_aux_make_delimited_radical(halfword target, int style, int size,
halfword total = height + depth;
delimiterextremes extremes = { .tfont = null_font, .tchar = 0, .bfont = null_font, .bchar = 0, .height = 0, .depth = 0 };
noad_new_hlist(target) = null;
+ size += radical_size(target);
+ if (size < text_size) {
+ size = text_size;
+ } else if (size > script_script_size) {
+ size = script_script_size;
+ }
delimiter = tex_aux_make_delimiter(target, delimiter, size, total, 0, style, 2, NULL, NULL, 0, has_noad_option_nooverflow(target), &extremes, depth);
if (companion) {
/*tex For now we assume symmetry and same height and depth! */
@@ -4771,7 +4777,7 @@ inline static scaled tex_aux_insert_italic_now(halfword target, halfword kernel,
return italic;
}
-static inline int tex_aux_raise_prime_composed(halfword target)
+inline static int tex_aux_raise_prime_composed(halfword target)
{
int mainclass = -1 ;
/* maybe also mainclass */
@@ -4891,12 +4897,14 @@ static void tex_aux_make_scripts(halfword target, halfword kernel, scaled italic
primedata.node = tex_aux_analyze_script(noad_prime(target), &primedata);
maxleftkern = tex_aux_math_left_kern(glyph_font(kernel), glyph_character(kernel));
// maxrightkern = tex_aux_math_right_kern(glyph_font(kernel), glyph_character(kernel));
- prime_up = tex_get_math_y_parameter_default(style, math_parameter_prime_shift_drop, 0);
- shift_up = tex_get_math_y_parameter_checked(style, math_parameter_superscript_shift_drop);
- shift_down = tex_get_math_y_parameter_checked(style, math_parameter_subscript_shift_drop);
- break; // fallthrough
+ prime_up = 0;
+ shift_up = 0;
+ shift_down = 0;
+ break;
default:
- kernelsize.ht -= supdrop; /* new */
+ /*tex Used for optimizing accents. */
+ kernelsize.ht -= supdrop;
+ /*tex These parameters are only applied in an assembly (and often some 0.5 .. 1.5 pt on 12pt). */
prime_up = kernelsize.ht - tex_get_math_y_parameter_default(style, math_parameter_prime_shift_drop, 0);
shift_up = kernelsize.ht - tex_get_math_y_parameter_checked(style, math_parameter_superscript_shift_drop);
shift_down = kernelsize.dp + tex_get_math_y_parameter_checked(style, math_parameter_subscript_shift_drop);
@@ -5372,7 +5380,7 @@ static void tex_aux_make_scripts(halfword target, halfword kernel, scaled italic
*/
-// static inline int tex_aux_is_extensible(halfword result)
+// inline static int tex_aux_is_extensible(halfword result)
// {
// if (result) {
// switch (node_type(result)) {
@@ -6119,7 +6127,7 @@ static halfword tex_aux_unroll_noad(halfword tail, halfword l, quarterword s)
while (l) {
halfword n = node_next(l);
node_next(l) = null;
- if (node_type(l) == hlist_node && (node_subtype(l) == s) && ! box_source_anchor(l)) {
+ if (node_type(l) == hlist_node && node_subtype(l) == s && ! box_source_anchor(l)) {
if (box_list(l)) {
tex_couple_nodes(tail, box_list(l));
tail = tex_tail_of_node_list(tail);
@@ -7052,6 +7060,9 @@ static void tex_mlist_to_hlist_finalize_list(mliststate *state)
} else {
tex_couple_nodes(p, l);
}
+ } else if ((current_subtype == open_noad_subtype || current_subtype == fenced_noad_subtype) && tex_math_has_class_option(fenced_noad_subtype, unpack_class_option)) {
+ /*tex tricky as we have an open subtype for spacing now. */
+ p = tex_aux_unroll_noad(p, l, math_fence_list);
} else if (has_noad_option_unpacklist(current) || tex_math_has_class_option(current_subtype, unpack_class_option)) {
/*tex So here we only unpack a math list. */
p = tex_aux_unroll_noad(p, l, math_list_list);
diff --git a/source/luametatex/source/tex/texnesting.c b/source/luametatex/source/tex/texnesting.c
index d699d58fc..f281eee2e 100644
--- a/source/luametatex/source/tex/texnesting.c
+++ b/source/luametatex/source/tex/texnesting.c
@@ -182,7 +182,7 @@ nest_state_info lmt_nest_state = {
.offset = 0,
},
.shown_mode = 0,
- .padding = 0,
+ .math_mode = 0,
};
/*tex
@@ -239,7 +239,8 @@ void tex_initialize_nesting(void)
{
lmt_nest_state.nest_data.ptr = 0;
lmt_nest_state.nest_data.top = 0;
- lmt_nest_state.shown_mode = 0;
+ // lmt_nest_state.shown_mode = 0;
+ // lmt_nest_state.math_mode = 0;
cur_list.mode = vmode;
cur_list.head = contribute_head;
cur_list.tail = contribute_head;
@@ -290,6 +291,8 @@ void tex_push_nest(void)
{
list_state_record *top = &lmt_nest_state.nest[lmt_nest_state.nest_data.ptr];
lmt_nest_state.nest_data.ptr += 1;
+ // lmt_nest_state.shown_mode = 0; // needs checking
+ lmt_nest_state.math_mode = 0;
if (tex_aux_room_on_nest_stack()) {
cur_list.mode = top->mode;
cur_list.head = tex_new_temp_node();
diff --git a/source/luametatex/source/tex/texnesting.h b/source/luametatex/source/tex/texnesting.h
index f940094a0..91251eee0 100644
--- a/source/luametatex/source/tex/texnesting.h
+++ b/source/luametatex/source/tex/texnesting.h
@@ -30,7 +30,7 @@ typedef struct nest_state_info {
list_state_record *nest;
memory_data nest_data;
int shown_mode;
- int padding;
+ int math_mode;
} nest_state_info;
extern nest_state_info lmt_nest_state;
diff --git a/source/luametatex/source/tex/texnodes.c b/source/luametatex/source/tex/texnodes.c
index 0134eb419..ab2601a43 100644
--- a/source/luametatex/source/tex/texnodes.c
+++ b/source/luametatex/source/tex/texnodes.c
@@ -1800,6 +1800,24 @@ halfword tex_list_node_mem_usage(void)
(actually for each node tyep I guess).
*/
+extern void tex_change_attribute_register(halfword a, halfword id, halfword value)
+{
+ if (eq_value(id) != value) {
+ if (is_global(a)) {
+ int i;
+ for (i = (lmt_save_state.save_stack_data.ptr - 1); i >= 0; i--) {
+ if (save_type(i) == attribute_list_save_type) {
+ delete_attribute_reference(save_value(i));
+ save_value(i) = attribute_cache_disabled;
+ }
+ }
+ } else {
+ delete_attribute_reference(current_attribute_state);
+ }
+ set_current_attribute_state(attribute_cache_disabled);
+ }
+}
+
inline static halfword tex_aux_new_attribute_list_node(halfword count)
{
halfword r = tex_get_node(attribute_node_size);
diff --git a/source/luametatex/source/tex/texnodes.h b/source/luametatex/source/tex/texnodes.h
index 9e24ada27..50dbeaa97 100644
--- a/source/luametatex/source/tex/texnodes.h
+++ b/source/luametatex/source/tex/texnodes.h
@@ -130,8 +130,9 @@ typedef enum node_types {
align_stack_node,
noad_state_node,
if_node,
- unhyphenated_node, /*tex These are both active nodes. */
- hyphenated_node, /*tex These are both active nodes. */
+ /*tex These two are active nodes. */
+ unhyphenated_node,
+ hyphenated_node,
delta_node,
passive_node,
} node_types;
@@ -988,17 +989,17 @@ typedef enum rule_codes {
# define first_rule_code normal_rule_code
# define last_rule_code strut_rule_code
-# define rule_node_size 7
-# define rule_width(a) vlink(a,2)
-# define rule_x_offset(a) vinfo(a,2)
-# define rule_depth(a) vlink(a,3)
-# define rule_y_offset(a) vinfo(a,3)
-# define rule_height(a) vlink(a,4)
-# define rule_data(a) vinfo(a,4)
-# define rule_left(a) vinfo(a,5)
-# define rule_right(a) vlink(a,5)
-# define rule_font(a) vinfo(a,6)
-# define rule_character(a) vlink(a,6)
+# define rule_node_size 7
+# define rule_width(a) vlink(a,2)
+# define rule_x_offset(a) vinfo(a,2)
+# define rule_depth(a) vlink(a,3)
+# define rule_y_offset(a) vinfo(a,3)
+# define rule_height(a) vlink(a,4)
+# define rule_data(a) vinfo(a,4)
+# define rule_left(a) vinfo(a,5)
+# define rule_right(a) vlink(a,5)
+# define rule_font(a) vinfo(a,6)
+# define rule_character(a) vlink(a,6)
# define rule_total(a) (rule_height(a) + rule_depth(a))
@@ -1057,36 +1058,36 @@ typedef enum rule_codes {
*/
-//define glyph_node_size 12
-# define glyph_node_size 13
-# define glyph_character(a) vinfo(a,2)
-# define glyph_font(a) vlink(a,2)
-# define glyph_data(a) vinfo(a,3) /*tex We had that unused, so now it's like an attribute. */
-# define glyph_state(a) vlink(a,3) /*tex A user field (can be handy in \LUA). */
-# define glyph_language(a) vinfo(a,4)
-# define glyph_script(a) vlink(a,4)
-# define glyph_options(a) vinfo(a,5)
-# define glyph_hyphenate(a) vlink(a,5)
-# define glyph_protected(a) vinfo00(a,6)
-# define glyph_lhmin(a) vinfo01(a,6)
-# define glyph_rhmin(a) vinfo02(a,6)
-# define glyph_discpart(a) vinfo03(a,6)
-# define glyph_expansion(a) vlink(a,6)
-# define glyph_x_scale(a) vinfo(a,7)
-# define glyph_y_scale(a) vlink(a,7)
-# define glyph_scale(a) vinfo(a,8)
-# define glyph_raise(a) vlink(a,8)
-# define glyph_left(a) vinfo(a,9)
-# define glyph_right(a) vlink(a,9)
-# define glyph_x_offset(a) vinfo(a,10)
-# define glyph_y_offset(a) vlink(a,10)
-//define glyph_input_file(a) vinfo(a,11) /* aka glyph_synctex_tag */
-//define glyph_input_line(a) vlink(a,11) /* aka glyph_synctex_line */
-# define glyph_properties(a) vinfo0(a,11)
-# define glyph_group(a) vinfo1(a,11)
-# define glyph_index(a) vlink(a,11)
-# define glyph_input_file(a) vinfo(a,12)
-# define glyph_input_line(a) vlink(a,12)
+//define glyph_node_size 12
+# define glyph_node_size 13
+# define glyph_character(a) vinfo(a,2)
+# define glyph_font(a) vlink(a,2)
+# define glyph_data(a) vinfo(a,3) /*tex We had that unused, so now it's like an attribute. */
+# define glyph_state(a) vlink(a,3) /*tex A user field (can be handy in \LUA). */
+# define glyph_language(a) vinfo(a,4)
+# define glyph_script(a) vlink(a,4)
+# define glyph_options(a) vinfo(a,5)
+# define glyph_hyphenate(a) vlink(a,5)
+# define glyph_protected(a) vinfo00(a,6)
+# define glyph_lhmin(a) vinfo01(a,6)
+# define glyph_rhmin(a) vinfo02(a,6)
+# define glyph_discpart(a) vinfo03(a,6)
+# define glyph_expansion(a) vlink(a,6)
+# define glyph_x_scale(a) vinfo(a,7)
+# define glyph_y_scale(a) vlink(a,7)
+# define glyph_scale(a) vinfo(a,8)
+# define glyph_raise(a) vlink(a,8)
+# define glyph_left(a) vinfo(a,9)
+# define glyph_right(a) vlink(a,9)
+# define glyph_x_offset(a) vinfo(a,10)
+# define glyph_y_offset(a) vlink(a,10)
+//define glyph_input_file(a) vinfo(a,11) /* aka glyph_synctex_tag */
+//define glyph_input_line(a) vlink(a,11) /* aka glyph_synctex_line */
+# define glyph_properties(a) vinfo0(a,11)
+# define glyph_group(a) vinfo1(a,11)
+# define glyph_index(a) vlink(a,11)
+# define glyph_input_file(a) vinfo(a,12)
+# define glyph_input_line(a) vlink(a,12)
# define get_glyph_data(a) ((halfword) glyph_data(a))
# define get_glyph_state(a) ((halfword) glyph_state(a))
@@ -1477,6 +1478,10 @@ typedef enum specification_options {
# define specification_n(a,n) (specification_repeat(a) ? ((n - 1) % specification_count(a) + 1) : (n > specification_count(a) ? specification_count(a) : n))
+/* interesting: 1Kb smaller bin: */
+
+// inline static halfword specification_n(halfword a, halfword n) { return specification_repeat(a) ? ((n - 1) % specification_count(a) + 1) : (n > specification_count(a) ? specification_count(a) : n); }
+
extern void tex_null_specification_list (halfword a);
extern void tex_new_specification_list (halfword a, halfword n, halfword o);
extern void tex_dispose_specification_list (halfword a);
@@ -1596,15 +1601,15 @@ typedef enum simple_choice_subtypes {
*/
-# define noad_state_node_size 6
-# define noad_state_topright(a) vlink(a,2)
-# define noad_state_bottomright(a) vinfo(a,2)
-# define noad_state_topleft(a) vlink(a,3)
-# define noad_state_bottomleft(a) vinfo(a,3)
-# define noad_state_height(a) vlink(a,4)
-# define noad_state_depth(a) vinfo(a,4)
-# define noad_state_toptotal(a) vlink(a,5)
-# define noad_state_bottomtotal(a) vinfo(a,5)
+# define noad_state_node_size 6
+# define noad_state_topright(a) vlink(a,2)
+# define noad_state_bottomright(a) vinfo(a,2)
+# define noad_state_topleft(a) vlink(a,3)
+# define noad_state_bottomleft(a) vinfo(a,3)
+# define noad_state_height(a) vlink(a,4)
+# define noad_state_depth(a) vinfo(a,4)
+# define noad_state_toptotal(a) vlink(a,5)
+# define noad_state_bottomtotal(a) vinfo(a,5)
# define noad_size 14
# define noad_new_hlist(a) vlink(a,2) /*tex the translation of an mlist; a bit confusing name */
@@ -1754,7 +1759,7 @@ inline static void tex_add_noad_option (halfword a, halfword r) { noad_option
inline static void tex_remove_noad_option (halfword a, halfword r) { noad_options(a) &= ~(r | noad_options(a)); }
inline static int tex_has_noad_option (halfword a, halfword r) { return (noad_options(a) & r) == r; }
-inline int has_noad_no_script_option(halfword n, halfword option)
+inline static int has_noad_no_script_option(halfword n, halfword option)
{
switch (node_type(n)) {
case simple_noad:
@@ -1880,13 +1885,13 @@ typedef enum math_modifier_types {
/*tex accent noads: todo, left and right offsets and options */
-# define accent_noad_size noad_size
-# define accent_top_character noad_extra_1 /*tex the |top_accent_chr| field of an accent noad */
-# define accent_bottom_character noad_extra_2 /*tex the |bot_accent_chr| field of an accent noad */
-# define accent_middle_character noad_extra_3 /*tex the |overlay_accent_chr| field of an accent noad */
-# define accent_fraction noad_extra_4
-# define accent_top_overshoot noad_extra_5
-# define accent_bot_overshoot noad_extra_6
+# define accent_noad_size noad_size
+# define accent_top_character noad_extra_1 /*tex the |top_accent_chr| field of an accent noad */
+# define accent_bottom_character noad_extra_2 /*tex the |bot_accent_chr| field of an accent noad */
+# define accent_middle_character noad_extra_3 /*tex the |overlay_accent_chr| field of an accent noad */
+# define accent_fraction noad_extra_4
+# define accent_top_overshoot noad_extra_5
+# define accent_bot_overshoot noad_extra_6
typedef enum math_accent_subtypes {
bothflexible_accent_subtype,
@@ -1965,6 +1970,7 @@ typedef enum fraction_subtypes {
# define radical_degree noad_extra_1
# define radical_left_delimiter noad_extra_2
# define radical_right_delimiter noad_extra_3
+# define radical_size noad_extra_4
# define radical_height noad_extra_5
# define radical_depth noad_extra_6
@@ -2513,9 +2519,10 @@ inline static void tex_attach_attribute_list_attribute(halfword target, halfword
# define attach_current_attribute_list tex_build_attribute_list /* (target) */
# define set_current_attribute_state(v) do { \
- current_attribute_state = v; \
+ current_attribute_state = v; \
} while (0)
+/*
# define change_attribute_register(a,id,value) do { \
if (eq_value(id) != value) { \
if (is_global(a)) { \
@@ -2532,6 +2539,9 @@ inline static void tex_attach_attribute_list_attribute(halfword target, halfword
set_current_attribute_state(attribute_cache_disabled); \
} \
} while (0)
+*/
+
+extern void tex_change_attribute_register(halfword a, halfword id, halfword value);
# define save_attribute_state_before() do { \
halfword c = current_attribute_state; \
@@ -2621,8 +2631,8 @@ typedef enum glue_signs {
# define normal_glue_multiplier 0.0
-inline halfword tex_checked_glue_sign (halfword sign) { return ((sign < min_glue_sign ) || (sign > max_glue_sign )) ? normal_glue_sign : sign ; }
-inline halfword tex_checked_glue_order (halfword order) { return ((order < min_glue_order) || (order > max_glue_order)) ? normal_glue_order : order; }
+inline static halfword tex_checked_glue_sign (halfword sign) { return ((sign < min_glue_sign ) || (sign > max_glue_sign )) ? normal_glue_sign : sign ; }
+inline static halfword tex_checked_glue_order (halfword order) { return ((order < min_glue_order) || (order > max_glue_order)) ? normal_glue_order : order; }
/*tex
These are reserved nodes that sit at the start of main memory. We could actually just allocate
diff --git a/source/luametatex/source/tex/texprimitive.c b/source/luametatex/source/tex/texprimitive.c
index d5f2b0927..9875e06dd 100644
--- a/source/luametatex/source/tex/texprimitive.c
+++ b/source/luametatex/source/tex/texprimitive.c
@@ -743,8 +743,10 @@ void tex_print_cmd_chr(singleword cmd, halfword chr)
case other_char_cmd:
tex_aux_print_chr_cmd("the", cmd, chr);
break;
- /*
case active_char_cmd:
+ tex_aux_print_chr_cmd("active", cmd, chr);
+ break;
+ /*
case comment_cmd:
case invalid_char_cmd:
break;
diff --git a/source/luametatex/source/tex/texprinting.h b/source/luametatex/source/tex/texprinting.h
index b323b1ae5..5e311a0bb 100644
--- a/source/luametatex/source/tex/texprinting.h
+++ b/source/luametatex/source/tex/texprinting.h
@@ -105,12 +105,11 @@ inline static int tex_single_letter(strnumber s)
inline static int tex_is_active_cs(strnumber s)
{
if (s && str_length(s) > 3) {
- const unsigned char *ss = str_string(s);
- return (ss[0] == 0xEF) && (ss[1] == 0xBF) && (ss[2] == 0xBF);
+ const unsigned char *ss = str_string(s); // or signed and active_character ...
+ return (ss[0] == active_first) && (ss[1] == active_second) && (ss[2] == active_third);
} else {
return 0;
}
}
-# define active_cs_value(A) aux_str2uni((str_string((A))+3))
# endif
diff --git a/source/luametatex/source/tex/texscanning.c b/source/luametatex/source/tex/texscanning.c
index 5480910dc..3c9859de9 100644
--- a/source/luametatex/source/tex/texscanning.c
+++ b/source/luametatex/source/tex/texscanning.c
@@ -11,7 +11,7 @@ static void tex_aux_scan_expression (int level);
A helper.
*/
-inline void tex_push_back(halfword tok, halfword cmd, halfword chr)
+inline static void tex_push_back(halfword tok, halfword cmd, halfword chr)
{
if (cmd != spacer_cmd && tok != deep_frozen_relax_token && ! (cmd == relax_cmd && chr == no_relax_code)) {
tex_back_input(tok);
@@ -670,7 +670,7 @@ static int tex_aux_set_cur_val_by_some_cmd(int code)
case math_char_slot_code:
/* we actually need two commands or we need to look ahead */
{
- mathcodeval mval = { 0, 0, 0 };
+ mathcodeval mval = tex_no_math_code();
mathdictval dval = { 0, 0, 0 };
if (tex_scan_math_cmd_val(&mval, &dval)) {
switch (code) {
@@ -1059,6 +1059,9 @@ static void tex_aux_set_cur_val_by_define_char_cmd(int chr)
case hmcode_charcode:
chr = tex_get_hm_code(index);
break;
+ case amcode_charcode:
+ chr = tex_get_am_code(index);
+ break;
case mathcode_charcode:
case extmathcode_charcode:
chr = tex_get_math_code_number(index);
@@ -1820,7 +1823,7 @@ halfword tex_scan_math_index_number (void) { return tex_
halfword tex_scan_math_discretionary_number (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_math_discretionary, "Math discretionary"); }
singleword tex_scan_box_index (void) { return (singleword) tex_aux_scan_limited_int(0, 0, max_box_index, "Box index"); }
singleword tex_scan_box_axis (void) { return (singleword) tex_aux_scan_limited_int(0, 0, max_box_axis, "Box axis"); }
-halfword tex_scan_category_code (void) { return tex_aux_scan_limited_int(0, 0, max_category_code,"Category code"); }
+halfword tex_scan_category_code (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_category_code,"Category code"); }
halfword tex_scan_function_reference (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_function_reference, "Function reference"); }
halfword tex_scan_bytecode_reference (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, 0, max_bytecode_index, "Bytecode reference"); }
halfword tex_scan_limited_scale (int optional_equal) { return tex_aux_scan_limited_int(optional_equal, -max_limited_scale, max_limited_scale, "Limited scale"); }
diff --git a/source/luametatex/source/tex/texscanning.h b/source/luametatex/source/tex/texscanning.h
index 90897bf54..303143587 100644
--- a/source/luametatex/source/tex/texscanning.h
+++ b/source/luametatex/source/tex/texscanning.h
@@ -120,7 +120,7 @@ extern halfword tex_scan_math_properties_number (void);
extern halfword tex_scan_math_group_number (void);
extern halfword tex_scan_math_index_number (void);
extern halfword tex_scan_math_discretionary_number (int optional_equal);
-extern halfword tex_scan_category_code (void);
+extern halfword tex_scan_category_code (int optional_equal);
extern singleword tex_scan_box_index (void); /*tex For local boxes: small for now! */
extern singleword tex_scan_box_axis (void);
extern halfword tex_scan_function_reference (int optional_equal);
diff --git a/source/luametatex/source/tex/texstringpool.c b/source/luametatex/source/tex/texstringpool.c
index fd93758b5..ffe4177bf 100644
--- a/source/luametatex/source/tex/texstringpool.c
+++ b/source/luametatex/source/tex/texstringpool.c
@@ -82,7 +82,7 @@ string_pool_info lmt_string_pool_state = {
# define initial_temp_string_slots 256
# define reserved_temp_string_slots 2
-static inline void tex_aux_increment_pool_string(int n)
+inline static void tex_aux_increment_pool_string(int n)
{
lmt_string_pool_state.string_body_data.allocated += n;
if (lmt_string_pool_state.string_body_data.allocated > lmt_string_pool_state.string_body_data.size) {
@@ -90,7 +90,7 @@ static inline void tex_aux_increment_pool_string(int n)
}
}
-static inline void tex_aux_decrement_pool_string(int n)
+inline static void tex_aux_decrement_pool_string(int n)
{
lmt_string_pool_state.string_body_data.allocated -= n;
}
diff --git a/source/luametatex/source/tex/texstringpool.h b/source/luametatex/source/tex/texstringpool.h
index 7302e7fb4..a15b9fad5 100644
--- a/source/luametatex/source/tex/texstringpool.h
+++ b/source/luametatex/source/tex/texstringpool.h
@@ -76,37 +76,37 @@ extern string_pool_info lmt_string_pool_state;
/*tex Forget the last character in the pool. */
-inline void tex_flush_char(void) { --lmt_string_pool_state.string_temp_top; }
-
-extern strnumber tex_make_string (void);
-extern strnumber tex_push_string (const unsigned char *s, int l);
-extern char *tex_take_string (int *len);
-extern int tex_str_eq_buf (strnumber s, int k, int n);
-extern int tex_str_eq_str (strnumber s, strnumber t);
-extern int tex_str_eq_cstr (strnumber s, const char *, size_t);
-extern int tex_get_strings_started (void);
-extern void tex_reset_cur_string (void);
-/* strnumber tex_search_string (strnumber search); */
-/* int tex_used_strings (void); */
-extern strnumber tex_maketexstring (const char *s);
-extern strnumber tex_maketexlstring (const char *s, size_t);
-extern void tex_append_char (unsigned char c);
-extern void tex_append_string (const unsigned char *s, unsigned l);
-extern char *tex_makecstring (int s, int *allocated);
-extern char *tex_makeclstring (int s, size_t *len);
-extern void tex_dump_string_pool (dumpstream f);
-extern void tex_undump_string_pool (dumpstream f);
-extern void tex_initialize_string_pool (void);
-extern void tex_initialize_string_mem (void);
-extern void tex_flush_str (strnumber s);
-extern strnumber tex_save_cur_string (void);
-extern void tex_restore_cur_string (strnumber u);
-
-/* void tex_increment_pool_string (int n); */
-/* void tex_decrement_pool_string (int n); */
-
-extern void tex_compact_string_pool (void);
-
-inline char *tex_to_cstring (int s) { return str_length(s) > 0 ? (char *) str_string(s) : ""; }
+inline static void tex_flush_char(void) { --lmt_string_pool_state.string_temp_top; }
+
+extern strnumber tex_make_string (void);
+extern strnumber tex_push_string (const unsigned char *s, int l);
+extern char *tex_take_string (int *len);
+extern int tex_str_eq_buf (strnumber s, int k, int n);
+extern int tex_str_eq_str (strnumber s, strnumber t);
+extern int tex_str_eq_cstr (strnumber s, const char *, size_t);
+extern int tex_get_strings_started (void);
+extern void tex_reset_cur_string (void);
+/* strnumber tex_search_string (strnumber search); */
+/* int tex_used_strings (void); */
+extern strnumber tex_maketexstring (const char *s);
+extern strnumber tex_maketexlstring (const char *s, size_t);
+extern void tex_append_char (unsigned char c);
+extern void tex_append_string (const unsigned char *s, unsigned l);
+extern char *tex_makecstring (int s, int *allocated);
+extern char *tex_makeclstring (int s, size_t *len);
+extern void tex_dump_string_pool (dumpstream f);
+extern void tex_undump_string_pool (dumpstream f);
+extern void tex_initialize_string_pool (void);
+extern void tex_initialize_string_mem (void);
+extern void tex_flush_str (strnumber s);
+extern strnumber tex_save_cur_string (void);
+extern void tex_restore_cur_string (strnumber u);
+
+/* void tex_increment_pool_string (int n); */
+/* void tex_decrement_pool_string (int n); */
+
+extern void tex_compact_string_pool (void);
+
+inline static char *tex_to_cstring (int s) { return str_length(s) > 0 ? (char *) str_string(s) : ""; }
# endif
diff --git a/source/luametatex/source/tex/textextcodes.c b/source/luametatex/source/tex/textextcodes.c
index 39fc258c7..2fef9857f 100644
--- a/source/luametatex/source/tex/textextcodes.c
+++ b/source/luametatex/source/tex/textextcodes.c
@@ -218,12 +218,16 @@ static void tex_aux_free_catcodes(void)
# define HMCODESTACK 8
# define HMCODEDEFAULT 0
+# define AMCODESTACK 8
+# define AMCODEDEFAULT 0
+
typedef struct luscode_state_info {
sa_tree uccode_head;
sa_tree lccode_head;
sa_tree sfcode_head;
sa_tree hccode_head;
sa_tree hmcode_head;
+ sa_tree amcode_head;
} luscode_state_info;
static luscode_state_info lmt_luscode_state = {
@@ -231,7 +235,8 @@ static luscode_state_info lmt_luscode_state = {
.lccode_head = NULL,
.sfcode_head = NULL,
.hccode_head = NULL,
- .hmcode_head = NULL
+ .hmcode_head = NULL,
+ .amcode_head = NULL
};
void tex_set_lc_code(int n, halfword v, int gl)
@@ -445,6 +450,45 @@ static void tex_aux_free_hmcodes(void)
sa_destroy_tree(lmt_luscode_state.hmcode_head);
}
+/*tex Experiment. */
+
+
+void tex_set_am_code(int n, halfword v, int gl)
+{
+ sa_set_item_1(lmt_luscode_state.amcode_head, n, v, gl);
+}
+
+halfword tex_get_am_code(int n)
+{
+ return sa_return_item_1(lmt_luscode_state.amcode_head, n);
+}
+
+static void tex_aux_unsave_amcodes(int gl)
+{
+ sa_restore_stack(lmt_luscode_state.amcode_head, gl);
+}
+
+static void tex_aux_initialize_amcodes(void)
+{
+ sa_tree_item item = { .int_value = AMCODEDEFAULT };
+ lmt_luscode_state.amcode_head = sa_new_tree(AMCODESTACK, 1, item);
+}
+
+static void tex_aux_dump_amcodes(dumpstream f)
+{
+ sa_dump_tree(f, lmt_luscode_state.amcode_head);
+}
+
+static void tex_aux_undump_amcodes(dumpstream f)
+{
+ lmt_luscode_state.amcode_head = sa_undump_tree(f);
+}
+
+static void tex_aux_free_amcodes(void)
+{
+ sa_destroy_tree(lmt_luscode_state.amcode_head);
+}
+
/*tex
The hyphenation codes are indeed stored in a tree and are used instead of lowercase codes when
@@ -544,6 +588,7 @@ void tex_unsave_text_codes(int grouplevel)
tex_aux_unsave_sfcodes(grouplevel);
tex_aux_unsave_hccodes(grouplevel);
tex_aux_unsave_hmcodes(grouplevel);
+ tex_aux_unsave_amcodes(grouplevel);
}
void tex_initialize_text_codes(void)
@@ -554,6 +599,7 @@ void tex_initialize_text_codes(void)
tex_aux_initialize_sfcodes();
tex_aux_initialize_hccodes();
tex_aux_initialize_hmcodes();
+ tex_aux_initialize_amcodes();
/* initializehjcodes(); */
}
@@ -565,6 +611,7 @@ void tex_free_text_codes(void)
tex_aux_free_sfcodes();
tex_aux_free_hccodes();
tex_aux_free_hmcodes();
+ tex_aux_free_amcodes();
/* freehjcodes(); */
}
@@ -576,6 +623,7 @@ void tex_dump_text_codes(dumpstream f)
tex_aux_dump_sfcodes(f);
tex_aux_dump_hccodes(f);
tex_aux_dump_hmcodes(f);
+ tex_aux_dump_amcodes(f);
/* dumphjcodes(f); */
}
@@ -587,6 +635,7 @@ void tex_undump_text_codes(dumpstream f)
tex_aux_undump_sfcodes(f);
tex_aux_undump_hccodes(f);
tex_aux_undump_hmcodes(f);
+ tex_aux_undump_amcodes(f);
/* undumphjcodes(f); */
}
diff --git a/source/luametatex/source/tex/textextcodes.h b/source/luametatex/source/tex/textextcodes.h
index 476f0f03e..d9fd7fbe4 100644
--- a/source/luametatex/source/tex/textextcodes.h
+++ b/source/luametatex/source/tex/textextcodes.h
@@ -29,6 +29,8 @@ extern void tex_set_hc_code (int n, halfword v, int gl);
extern halfword tex_get_hc_code (int n);
extern void tex_set_hm_code (int n, halfword v, int gl);
extern halfword tex_get_hm_code (int n);
+extern void tex_set_am_code (int n, halfword v, int gl);
+extern halfword tex_get_am_code (int n);
extern void tex_set_hj_code (int l, int n, halfword v, int gl);
extern halfword tex_get_hj_code (int l, int n);
extern void tex_initialize_xx_codes (void);
diff --git a/source/luametatex/source/tex/textoken.c b/source/luametatex/source/tex/textoken.c
index 7dd9c888b..ba457491a 100644
--- a/source/luametatex/source/tex/textoken.c
+++ b/source/luametatex/source/tex/textoken.c
@@ -573,7 +573,7 @@ static const char *tex_aux_special_cmd_string(halfword cmd, halfword chr, const
case begin_local_cmd : return "[[special cmd: begin local call]]";
case end_local_cmd : return "[[special cmd: end local call]]";
// case prefix_cmd : return "[[special cmd: enforced]]";
- case prefix_cmd : return "\\always";
+ case prefix_cmd : return "\\always ";
default : printf("[[unknown cmd: (%i,%i)]\n", cmd, chr); return unknown;
}
}
@@ -625,6 +625,7 @@ halfword tex_show_token_list(halfword p, halfword q, int l, int asis)
case spacer_cmd:
case letter_cmd:
case other_char_cmd:
+ case active_char_cmd: /* new */
case ignore_cmd: /* new */
tex_print_tex_str(chr);
break;
@@ -691,7 +692,7 @@ halfword tex_show_token_list(halfword p, halfword q, int l, int asis)
} while (0)
*/
-inline halfword get_unichar_from_buffer(int *b)
+inline static halfword get_unichar_from_buffer(int *b)
{
halfword a = (halfword) ((const unsigned char) *(lmt_fileio_state.io_buffer + *b));
if (a <= 0x80) {
@@ -1032,14 +1033,13 @@ int tex_scan_keyword_case_sensitive(const char *s)
halfword tex_active_to_cs(int c, int force)
{
halfword cs = -1;
- if (c > 0) {
- /*tex This is not that efficient: we can make a helper that doesn't use an alloc. */
- char utfbytes[8] = { '\xEF', '\xBF', '\xBF', 0 };
+ if (c >= 0 && c <= max_character_code) {
+ char utfbytes[8] = { active_character_first, active_character_second, active_character_third, 0 };
aux_uni2string((char *) &utfbytes[3], c);
cs = tex_string_locate(utfbytes, (size_t) utf8_size(c) + 3, force);
}
if (cs < 0) {
- cs = tex_string_locate("\xEF\xBF\xBF", 4, force); /*tex Including the zero sentinel. */
+ cs = tex_string_locate(active_character_unknown, 4, force); /*tex Including the zero sentinel. */
}
return cs;
}
@@ -1195,10 +1195,18 @@ static int tex_aux_get_next_file(void)
case mid_line_state + active_char_cmd:
case new_line_state + active_char_cmd:
case skip_blanks_state + active_char_cmd:
- /*tex Process an active-character. */
- cur_cs = tex_active_to_cs(cur_chr, ! lmt_hash_state.no_new_cs);
- cur_cmd = eq_type(cur_cs);
- cur_chr = eq_value(cur_cs);
+ /*tex Process an active-character. */
+ if ((lmt_input_state.scanner_status == scanner_is_tolerant || lmt_input_state.scanner_status == scanner_is_matching) && tex_pass_active_math_char(cur_chr)) {
+ /*tex We need to intercept a delimiter in arguments. */
+ } else if ((lmt_input_state.scanner_status == scanner_is_defining || lmt_input_state.scanner_status == scanner_is_absorbing) && tex_pass_active_math_char(cur_chr)) {
+ /*tex We are storing stuff in a token list or macro body. */
+ } else if ((cur_mode == mmode || lmt_nest_state.math_mode) && tex_check_active_math_char(cur_chr)) {
+ /*tex We have an intercept. */
+ } else {
+ cur_cs = tex_active_to_cs(cur_chr, ! lmt_hash_state.no_new_cs);
+ cur_cmd = eq_type(cur_cs);
+ cur_chr = eq_value(cur_cs);
+ }
lmt_input_state.cur_input.state = mid_line_state;
break;
case mid_line_state + superscript_cmd:
@@ -2730,6 +2738,7 @@ void tex_run_convert_tokens(halfword code)
break;
}
case cs_string_code:
+ case cs_active_code:
{
int saved_selector;
int saved_scanner_status = lmt_input_state.scanner_status;
@@ -2737,7 +2746,18 @@ void tex_run_convert_tokens(halfword code)
tex_get_token();
lmt_input_state.scanner_status = saved_scanner_status;
push_selector;
- if (cur_cs) {
+ if (code == cs_active_code) {
+ // tex_print_char(active_first);
+ // tex_print_char(active_second);
+ // tex_print_char(active_third);
+ tex_print_str(active_character_namespace);
+ if (cur_cmd == active_char_cmd) {
+ tex_print_char(cur_chr);
+ } else {
+ /*tex So anything else will just inject the hash (abstraction, saves a command). */
+ tex_back_input(cur_tok);
+ }
+ } else if (cur_cs) {
tex_print_cs_name(cur_cs);
} else {
tex_print_tex_str(cur_chr);
@@ -3122,6 +3142,7 @@ char *tex_tokenlist_to_tstring(int pp, int inhibit_par, int *siz, int skippreamb
case spacer_cmd:
case letter_cmd:
case other_char_cmd:
+ case active_char_cmd:
if (! skip) {
tex_aux_append_uchar_to_buffer(chr);
}
@@ -3335,7 +3356,7 @@ void tex_set_tex_attribute_register(int j, halfword v, int flags, int internal)
if (j > lmt_node_memory_state.max_used_attribute) {
lmt_node_memory_state.max_used_attribute = j;
}
- change_attribute_register(flags, register_attribute_location(j), v);
+ tex_change_attribute_register(flags, register_attribute_location(j), v);
tex_word_define(flags, internal ? internal_attribute_location(j) : register_attribute_location(j), v);
}
diff --git a/source/luametatex/source/tex/textoken.h b/source/luametatex/source/tex/textoken.h
index ad67dfcb5..843304405 100644
--- a/source/luametatex/source/tex/textoken.h
+++ b/source/luametatex/source/tex/textoken.h
@@ -390,6 +390,43 @@ extern halfword tex_copy_token_list (halfword h, halfword *t);
extern halfword tex_parse_str_to_tok (halfword head, halfword *tail, halfword ct, const char *str, size_t lstr, int option);
-inline int tex_valid_token (int t) { return ((t >= 0) && (t <= (int) lmt_token_memory_state.tokens_data.top)); }
+inline static int tex_valid_token (int t) { return ((t >= 0) && (t <= (int) lmt_token_memory_state.tokens_data.top)); }
+
+/*tex
+
+ This is also a sort of documentation. Active characters are stored in the hash using a prefix
+ which assumes that users don't use that one. So far we've seen no clashes which is due to the
+ fact that the namespace prefix U+FFFF is an invalid \UNICODE\ character and it's kind of hard
+ to get that one into the input anyway.
+
+ The replacement character U+FFFD is a kind of fallback when we run into some troubles or when
+ a control sequence is expected (and undefined is unacceptable).
+
+ U+FFFD REPLACEMENT CHARACTER
+ U+FFFE NOT A CHARACTER
+ U+FFFF NOT A CHARACTER
+
+ I experimented with a namespace character (catcodtable id) as fourth character but there are
+ some unwanted side effects, for instance in testing an active character as separator (in
+ arguments) so that code waa eventually removed. I might come back to this one day (active
+ characters in the catcode regime namespace).
+
+*/
+
+# define utf_fffd_string "\xEF\xBF\xBD" /* U+FFFD : 65533 */
+
+# define active_character_namespace "\xEF\xBF\xBF" /* U+FFFF : 65535 */
+
+# define active_character_first '\xEF'
+# define active_character_second '\xBF'
+# define active_character_third '\xBF'
+
+# define active_first 0xEF
+# define active_second 0xBF
+# define active_third 0xBF
+
+# define active_character_unknown "\xEF\xBF\xBD" /* utf_fffd_string */
+
+# define active_cs_value(A) aux_str2uni(str_string(A)+3)
# endif