Mercurial > hg > xemacs-beta
diff src/casetab.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 859a2309aef8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/casetab.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,291 @@ +/* XEmacs routines to deal with case tables. + Copyright (C) 1987, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1995 Sun Microsystems, Inc. + +This file is part of XEmacs. + +XEmacs 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, or (at your option) any +later version. + +XEmacs 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 General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: FSF 19.28. Between FSF 19.28 and 19.30, casetab.c + was rewritten to use junky RMS char tables. Meanwhile I rewrote it + to use more logical char tables. RMS also discards the "list of four + tables" format and instead stuffs the other tables as "extra slots" + in the downcase table. I've kept the four-lists format for now. */ + +/* Written by Howard Gayle. See some mythical and not-in-the-Emacs- + distribution file chartab.c for details. */ + +/* Modified for Mule by Ben Wing. */ + +/* #### We do not currently deal properly with translating non-ASCII + (including Latin-1!) characters under Mule. Getting this right is + *hard*, way fucking hard. So we at least preserve consistency by + sanitizing all the case tables to remove translations that would + get us into trouble and possibly result in inconsistent internal + text, which would likely lead to crashes. */ + +#include <config.h> +#include "lisp.h" +#include "buffer.h" +#include "opaque.h" + +Lisp_Object Qcase_table_p; +Lisp_Object Vascii_downcase_table, Vascii_upcase_table; +Lisp_Object Vascii_canon_table, Vascii_eqv_table; +Lisp_Object Qtranslate_table; + +static void compute_trt_inverse (Lisp_Object trt, Lisp_Object inverse); + +#define STRING256_P(obj) \ + (STRINGP (obj) && string_char_length (XSTRING (obj)) == 256) + +DEFUN ("case-table-p", Fcase_table_p, Scase_table_p, 1, 1, 0 /* +Return t iff ARG is a case table. +See `set-case-table' for more information on these data structures. +*/ ) + (table) + Lisp_Object table; +{ + Lisp_Object down, up, canon, eqv; + down = Fcar_safe (table); + up = Fcar_safe (Fcdr_safe (table)); + canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table))); + eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table)))); + + return (STRING256_P (down) + && (NILP (up) || STRING256_P (up)) + && ((NILP (canon) && NILP (eqv)) + || (STRING256_P (canon) + && (NILP (eqv) || STRING256_P (eqv)))) + ? Qt : Qnil); +} + +static Lisp_Object +check_case_table (Lisp_Object obj) +{ + REGISTER Lisp_Object tem; + + while (tem = Fcase_table_p (obj), NILP (tem)) + obj = wrong_type_argument (Qcase_table_p, obj); + return (obj); +} + +DEFUN ("current-case-table", Fcurrent_case_table, Scurrent_case_table, + 0, 1, 0 /* +Return the case table of BUFFER, which defaults to the current buffer. +*/ ) + (buffer) + Lisp_Object buffer; +{ + Lisp_Object down, up, canon, eqv; + struct buffer *buf = decode_buffer (buffer, 0); + + down = buf->downcase_table; + up = buf->upcase_table; + canon = buf->case_canon_table; + eqv = buf->case_eqv_table; + + return Fcons (down, Fcons (up, Fcons (canon, Fcons (eqv, Qnil)))); +} + +DEFUN ("standard-case-table", Fstandard_case_table, + Sstandard_case_table, 0, 0, 0 /* +Return the standard case table. +This is the one used for new buffers. +*/ ) + () +{ + return Fcons (Vascii_downcase_table, + Fcons (Vascii_upcase_table, + Fcons (Vascii_canon_table, + Fcons (Vascii_eqv_table, + Qnil)))); +} + +static Lisp_Object set_case_table (Lisp_Object table, int standard); + + +DEFUN ("set-case-table", Fset_case_table, Sset_case_table, 1, 1, 0 /* +Select a new case table for the current buffer. +A case table is a list (DOWNCASE UPCASE CANONICALIZE EQUIVALENCES) + where each element is either nil or a string of length 256. +DOWNCASE maps each character to its lower-case equivalent. +UPCASE maps each character to its upper-case equivalent; + if lower and upper case characters are in 1-1 correspondence, + you may use nil and the upcase table will be deduced from DOWNCASE. +CANONICALIZE maps each character to a canonical equivalent; + any two characters that are related by case-conversion have the same + canonical equivalent character; it may be nil, in which case it is + deduced from DOWNCASE and UPCASE. +EQUIVALENCES is a map that cyclicly permutes each equivalence class + (of characters with the same canonical equivalent); it may be nil, + in which case it is deduced from CANONICALIZE. +*/ ) + (table) + Lisp_Object table; +{ + return set_case_table (table, 0); +} + +DEFUN ("set-standard-case-table", + Fset_standard_case_table, Sset_standard_case_table, 1, 1, 0 /* +Select a new standard case table for new buffers. +See `set-case-table' for more info on case tables. +*/ ) + (table) + Lisp_Object table; +{ + return set_case_table (table, 1); +} + +static Lisp_Object +set_case_table (Lisp_Object table, int standard) +{ + Lisp_Object down, up, canon, eqv; + struct buffer *buf = current_buffer; + + check_case_table (table); + + down = Fcar_safe (table); + up = Fcar_safe (Fcdr_safe (table)); + canon = Fcar_safe (Fcdr_safe (Fcdr_safe (table))); + eqv = Fcar_safe (Fcdr_safe (Fcdr_safe (Fcdr_safe (table)))); + + if (NILP (up)) + { + up = MAKE_TRT_TABLE (); + compute_trt_inverse (down, up); + } + + if (NILP (canon)) + { + REGISTER Charcount i; + + canon = MAKE_TRT_TABLE (); + + /* Set up the CANON vector; for each character, + this sequence of upcasing and downcasing ought to + get the "preferred" lowercase equivalent. */ + for (i = 0; i < 256; i++) + SET_TRT_TABLE_CHAR_1 (canon, i, + TRT_TABLE_CHAR_1 + (down, + TRT_TABLE_CHAR_1 + (up, + TRT_TABLE_CHAR_1 (down, i)))); + } + + if (NILP (eqv)) + { + eqv = MAKE_TRT_TABLE (); + + compute_trt_inverse (canon, eqv); + } + + if (standard) + { + Vascii_downcase_table = down; + Vascii_upcase_table = up; + Vascii_canon_table = canon; + Vascii_eqv_table = eqv; + } + else + { + buf->downcase_table = down; + buf->upcase_table = up; + buf->case_canon_table = canon; + buf->case_eqv_table = eqv; + } + return table; +} + +/* Given a translate table TRT, store the inverse mapping into INVERSE. + Since TRT is not one-to-one, INVERSE is not a simple mapping. + Instead, it divides the space of characters into equivalence classes. + All characters in a given class form one circular list, chained through + the elements of INVERSE. */ + +static void +compute_trt_inverse (Lisp_Object trt, Lisp_Object inverse) +{ + Charcount i = 0400; + Emchar c, q; + + while (--i) + SET_TRT_TABLE_CHAR_1 (inverse, i, (Emchar) i); + i = 0400; + while (--i) + { + if ((q = TRT_TABLE_CHAR_1 (trt, i)) != (Emchar) i) + { + c = TRT_TABLE_CHAR_1 (inverse, q); + SET_TRT_TABLE_CHAR_1 (inverse, q, (Emchar) i); + SET_TRT_TABLE_CHAR_1 (inverse, i, c); + } + } +} + + +void +syms_of_casetab (void) +{ + defsymbol (&Qcase_table_p, "case-table-p"); + defsymbol (&Qtranslate_table, "translate-table"); + + defsubr (&Scase_table_p); + defsubr (&Scurrent_case_table); + defsubr (&Sstandard_case_table); + defsubr (&Sset_case_table); + defsubr (&Sset_standard_case_table); +} + +void +complex_vars_of_casetab (void) +{ + REGISTER Emchar i; + Lisp_Object tem; + + staticpro (&Vascii_downcase_table); + staticpro (&Vascii_upcase_table); + staticpro (&Vascii_canon_table); + staticpro (&Vascii_eqv_table); + + tem = MAKE_TRT_TABLE (); + Vascii_downcase_table = tem; + Vascii_canon_table = tem; + + /* Under Mule, can't do set_string_char() until Vcharset_control_1 + and Vcharset_ascii are initialized. */ + for (i = 0; i < 256; i++) + { + unsigned char lowered = tolower (i); + + SET_TRT_TABLE_CHAR_1 (tem, i, lowered); + } + + tem = MAKE_TRT_TABLE (); + Vascii_upcase_table = tem; + Vascii_eqv_table = tem; + + for (i = 0; i < 256; i++) + { + unsigned char flipped = (isupper (i) ? tolower (i) + : (islower (i) ? toupper (i) : i)); + + SET_TRT_TABLE_CHAR_1 (tem, i, flipped); + } + +}