diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex/textcodes.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/tex/textcodes.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/textcodes.c b/Build/source/texk/web2c/luatexdir/tex/textcodes.c new file mode 100644 index 00000000000..a6a0b3a55e3 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/tex/textcodes.c @@ -0,0 +1,530 @@ +/* + +textcodes.w + +Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> + +This file is part of LuaTeX. + +LuaTeX is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. + +LuaTeX is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU General Public License along +with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "ptexlib.h" + +/*tex + +Contrary to traditional \TEX\ we have catcode tables so that we can switch +catcode regimes very fast. We can have many such regimes and they're stored in +trees. + +*/ + +#define CATCODESTACK 8 +#define CATCODEDEFAULT 12 +#define CATCODE_MAX 32767 + +static sa_tree *catcode_heads = NULL; +static int catcode_max = 0; +static unsigned char *catcode_valid = NULL; + +void set_cat_code(int h, int n, halfword v, quarterword gl) +{ + sa_tree_item sa_value = { 0 }; + sa_tree s = catcode_heads[h]; + if (h > catcode_max) + catcode_max = h; + if (s == NULL) { + sa_value.int_value = CATCODEDEFAULT; + s = new_sa_tree(CATCODESTACK, 1, sa_value); + catcode_heads[h] = s; + } + sa_value.int_value = (int) v; + set_sa_item(s, n, sa_value, gl); +} + +halfword get_cat_code(int h, int n) +{ + sa_tree_item sa_value = { 0 }; + sa_tree s = catcode_heads[h]; + if (h > catcode_max) + catcode_max = h; + if (s == NULL) { + sa_value.int_value = CATCODEDEFAULT; + s = new_sa_tree(CATCODESTACK, 1, sa_value); + catcode_heads[h] = s; + } + return (halfword) get_sa_item(s, n).int_value; +} + +void unsave_cat_codes(int h, quarterword gl) +{ + int k; + if (h > catcode_max) + catcode_max = h; + for (k = 0; k <= catcode_max; k++) { + if (catcode_heads[k] != NULL) + restore_sa_stack(catcode_heads[k], gl); + } +} + +static void initializecatcodes(void) +{ + sa_tree_item sa_value = { 0 }; + catcode_max = 0; + catcode_heads = Mxmalloc_array(sa_tree, (CATCODE_MAX + 1)); + catcode_valid = Mxmalloc_array(unsigned char, (CATCODE_MAX + 1)); + memset(catcode_heads, 0, sizeof(sa_tree) * (CATCODE_MAX + 1)); + memset(catcode_valid, 0, sizeof(unsigned char) * (CATCODE_MAX + 1)); + catcode_valid[0] = 1; + sa_value.int_value = CATCODEDEFAULT; + catcode_heads[0] = new_sa_tree(CATCODESTACK, 1, sa_value); +} + +static void dumpcatcodes(void) +{ + int total = 0; + int k; + for (k = 0; k <= catcode_max; k++) { + if (catcode_valid[k]) { + total++; + } + } + dump_int(catcode_max); + dump_int(total); + for (k = 0; k <= catcode_max; k++) { + if (catcode_valid[k]) { + dump_int(k); + dump_sa_tree(catcode_heads[k],"catcodes"); + } + } +} + +static void undumpcatcodes(void) +{ + int total, k, x; + xfree(catcode_heads); + xfree(catcode_valid); + catcode_heads = Mxmalloc_array(sa_tree, (CATCODE_MAX + 1)); + catcode_valid = Mxmalloc_array(unsigned char, (CATCODE_MAX + 1)); + memset(catcode_heads, 0, sizeof(sa_tree) * (CATCODE_MAX + 1)); + memset(catcode_valid, 0, sizeof(unsigned char) * (CATCODE_MAX + 1)); + undump_int(catcode_max); + undump_int(total); + for (k = 0; k < total; k++) { + undump_int(x); + catcode_heads[x] = undump_sa_tree("catcodes"); + catcode_valid[x] = 1; + } +} + +int valid_catcode_table(int h) +{ + if (h <= CATCODE_MAX && h >= 0 && catcode_valid[h]) { + return 1; + } + return 0; +} + +void copy_cat_codes(int from, int to) +{ + if (from < 0 || from > CATCODE_MAX || catcode_valid[from] == 0) { + uexit(1); + } + if (to > catcode_max) + catcode_max = to; + destroy_sa_tree(catcode_heads[to]); + catcode_heads[to] = copy_sa_tree(catcode_heads[from]); + catcode_valid[to] = 1; +} + +void initex_cat_codes(int h) +{ + int k; + if (h > catcode_max) + catcode_max = h; + destroy_sa_tree(catcode_heads[h]); + catcode_heads[h] = NULL; + set_cat_code(h, '\r', car_ret_cmd, 1); + set_cat_code(h, ' ', spacer_cmd, 1); + set_cat_code(h, '\\', escape_cmd, 1); + set_cat_code(h, '%', comment_cmd, 1); + set_cat_code(h, 127, invalid_char_cmd, 1); + set_cat_code(h, 0, ignore_cmd, 1); + set_cat_code(h, 0xFEFF, ignore_cmd, 1); + for (k = 'A'; k <= 'Z'; k++) { + set_cat_code(h, k, letter_cmd, 1); + set_cat_code(h, k + 'a' - 'A', letter_cmd, 1); + } + catcode_valid[h] = 1; +} + +static void freecatcodes(void) +{ + int k; + for (k = 0; k <= catcode_max; k++) { + if (catcode_valid[k]) { + destroy_sa_tree(catcode_heads[k]); + } + } + xfree(catcode_heads); + xfree(catcode_valid); +} + +/*tex + +The lowercase mapping codes are also stored in a tree. + +*/ + +#define LCCODESTACK 8 +#define LCCODEDEFAULT 0 + +static sa_tree lccode_head = NULL; + +void set_lc_code(int n, halfword v, quarterword gl) +{ + sa_tree_item sa_value = { 0 }; + sa_value.int_value = (int) v; + set_sa_item(lccode_head, n, sa_value, gl); +} + +halfword get_lc_code(int n) +{ + return (halfword) get_sa_item(lccode_head, n).int_value; +} + +static void unsavelccodes(quarterword gl) +{ + restore_sa_stack(lccode_head, gl); +} + +static void initializelccodes(void) +{ + sa_tree_item sa_value = { 0 }; + sa_value.int_value = LCCODEDEFAULT; + lccode_head = new_sa_tree(LCCODESTACK, 1, sa_value); +} + +static void dumplccodes(void) +{ + dump_sa_tree(lccode_head,"lccodes"); +} + +static void undumplccodes(void) +{ + lccode_head = undump_sa_tree("lccodes"); +} + +static void freelccodes(void) +{ + destroy_sa_tree(lccode_head); +} + +/*tex + +And the uppercase mapping codes are again stored in a tree. + +*/ + +#define UCCODESTACK 8 +#define UCCODEDEFAULT 0 + +static sa_tree uccode_head = NULL; + +void set_uc_code(int n, halfword v, quarterword gl) +{ + sa_tree_item sa_value = { 0 }; + sa_value.int_value = (int) v; + set_sa_item(uccode_head, n, sa_value, gl); +} + +halfword get_uc_code(int n) +{ + return (halfword) get_sa_item(uccode_head, n).int_value; +} + +static void unsaveuccodes(quarterword gl) +{ + restore_sa_stack(uccode_head, gl); +} + +static void initializeuccodes(void) +{ + sa_tree_item sa_value = { 0 }; + sa_value.int_value = UCCODEDEFAULT; + uccode_head = new_sa_tree(UCCODESTACK, 1, sa_value); +} + +static void dumpuccodes(void) +{ + dump_sa_tree(uccode_head,"uccodes"); +} + +static void undumpuccodes(void) +{ + uccode_head = undump_sa_tree("uccodes"); +} + +static void freeuccodes(void) +{ + destroy_sa_tree(uccode_head); +} + +/*tex + +By now it will be no surprise that the space factors get stored in a tree. + +*/ + +#define SFCODESTACK 8 +#define SFCODEDEFAULT 1000 + +static sa_tree sfcode_head = NULL; + +void set_sf_code(int n, halfword v, quarterword gl) +{ + sa_tree_item sa_value = { 0 }; + sa_value.int_value = (int) v; + set_sa_item(sfcode_head, n, sa_value, gl); +} + +halfword get_sf_code(int n) +{ + return (halfword) get_sa_item(sfcode_head, n).int_value; +} + +static void unsavesfcodes(quarterword gl) +{ + restore_sa_stack(sfcode_head, gl); +} + +static void initializesfcodes(void) +{ + sa_tree_item sa_value = { 0 }; + sa_value.int_value = SFCODEDEFAULT; + sfcode_head = new_sa_tree(SFCODESTACK, 1, sa_value); +} + +static void dumpsfcodes(void) +{ + dump_sa_tree(sfcode_head,"sfcodes"); +} + +static void undumpsfcodes(void) +{ + sfcode_head = undump_sa_tree("sfcodes"); +} + +static void freesfcodes(void) +{ + destroy_sa_tree(sfcode_head); +} + +/*tex + +The hyphenation codes are indeed stored in a tree and are used instead of +lowercase codes when deciding what characters to take into acccount when +hyphenating. They are bound to upto |HJCODE_MAX| languages. + +*/ + +#define HJCODESTACK 8 +#define HJCODEDEFAULT 0 +#define HJCODE_MAX 16383 + +static sa_tree *hjcode_heads = NULL; +static int hjcode_max = 0; +static unsigned char *hjcode_valid = NULL; + +/*tex + +Here we set codes but we don't initialize from lccodes. + +*/ + +void set_hj_code(int h, int n, halfword v, quarterword gl) +{ + sa_tree_item sa_value = { 0 }; + sa_tree s = hjcode_heads[h]; + if (h > hjcode_max) + hjcode_max = h; + if (s == NULL) { + sa_value.int_value = HJCODEDEFAULT; + s = new_sa_tree(HJCODESTACK, 1, sa_value); + hjcode_heads[h] = s; + } + sa_value.int_value = (int) v; + set_sa_item(s, n, sa_value, gl); +} + +/*tex + +We just return the lccodes when nothing is set. + +*/ + +halfword get_hj_code(int h, int n) +{ + sa_tree s = hjcode_heads[h]; + if (s == NULL) { + s = lccode_head; + } + return (halfword) get_sa_item(s, n).int_value; +} + +/*tex + +We don't restore as we can have more languages in a paragraph and hyphenation +takes place at a later stage so we would get weird grouping side effects .. so, +one can overload settings but management is then upto the used, so no: + +*/ + +/* + static void unsavehjcodes(quarterword gl) { } +*/ + +static void initializehjcodes(void) +{ + /* + sa_tree_item sa_value = { 0 }; + */ + hjcode_max = 0; + hjcode_heads = Mxmalloc_array(sa_tree, (HJCODE_MAX + 1)); + hjcode_valid = Mxmalloc_array(unsigned char, (HJCODE_MAX + 1)); + memset(hjcode_heads, 0, sizeof(sa_tree) * (HJCODE_MAX + 1)); + memset(hjcode_valid, 0, sizeof(unsigned char) * (HJCODE_MAX + 1)); + /* + hjcode_valid[0] = 1; + sa_value.int_value = HJCODEDEFAULT; + hjcode_heads[0] = new_sa_tree(HJCODESTACK, 1, sa_value); + */ +} + +void hj_codes_from_lc_codes(int h) +{ + sa_tree_item sa_value = { 0 }; + sa_tree s = hjcode_heads[h]; + if (s != NULL) { + destroy_sa_tree(s); + } else if (h > hjcode_max) { + hjcode_max = h; + } + if (s == NULL) { + sa_value.int_value = HJCODEDEFAULT; + s = new_sa_tree(HJCODESTACK, 1, sa_value); + hjcode_heads[h] = s; + } + hjcode_heads[h] = copy_sa_tree(lccode_head); + hjcode_valid[h] = 1; +} + +static void dumphjcodes(void) +{ + int total = 0; + int k; + for (k = 0; k <= hjcode_max; k++) { + if (hjcode_valid[k]) { + total++; + } + } + dump_int(hjcode_max); + dump_int(total); + for (k = 0; k <= hjcode_max; k++) { + if (hjcode_valid[k]) { + dump_int(k); + dump_sa_tree(hjcode_heads[k],"hjcodes"); + } + } +} + +static void undumphjcodes(void) +{ + int total, k, x; + xfree(hjcode_heads); + xfree(hjcode_valid); + hjcode_heads = Mxmalloc_array(sa_tree, (HJCODE_MAX + 1)); + hjcode_valid = Mxmalloc_array(unsigned char, (HJCODE_MAX + 1)); + memset(hjcode_heads, 0, sizeof(sa_tree) * (HJCODE_MAX + 1)); + memset(hjcode_valid, 0, sizeof(unsigned char) * (HJCODE_MAX + 1)); + undump_int(hjcode_max); + undump_int(total); + for (k = 0; k < total; k++) { + undump_int(x); + hjcode_heads[x] = undump_sa_tree("hjcodes"); + hjcode_valid[x] = 1; + } +} + +static void freehjcodes(void) +{ + int k; + for (k = 0; k <= hjcode_max; k++) { + if (hjcode_valid[k]) { + destroy_sa_tree(hjcode_heads[k]); + } + } + xfree(hjcode_heads); + xfree(hjcode_valid); +} + +/*tex + +The public management functions. + +*/ + +void unsave_text_codes(quarterword grouplevel) +{ + unsavelccodes(grouplevel); + unsaveuccodes(grouplevel); + unsavesfcodes(grouplevel); +} + +void initialize_text_codes(void) +{ + initializecatcodes(); + initializelccodes(); + initializeuccodes(); + initializesfcodes(); + initializehjcodes(); +} + +void free_text_codes(void) +{ + freecatcodes(); + freelccodes(); + freeuccodes(); + freesfcodes(); + freehjcodes(); +} + +void dump_text_codes(void) +{ + dumpcatcodes(); + dumplccodes(); + dumpuccodes(); + dumpsfcodes(); + dumphjcodes(); +} + +void undump_text_codes(void) +{ + undumpcatcodes(); + undumplccodes(); + undumpuccodes(); + undumpsfcodes(); + undumphjcodes(); +} |