diff src/casetab.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children abe6d1db359e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/casetab.c	Mon Aug 13 11:28:15 2007 +0200
@@ -0,0 +1,354 @@
+/* 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 FSF 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_tablep;
+Lisp_Object Vascii_downcase_table, Vascii_upcase_table;
+Lisp_Object Vascii_canon_table, Vascii_eqv_table;
+#ifdef MULE
+Lisp_Object Vmirror_ascii_downcase_table, Vmirror_ascii_upcase_table;
+Lisp_Object Vmirror_ascii_canon_table, Vmirror_ascii_eqv_table;
+#endif
+
+static void compute_trt_inverse (Lisp_Object trt, Lisp_Object inverse);
+
+#define STRING256_P(obj) (STRINGP (obj) && XSTRING_CHAR_LENGTH (obj) == 256)
+
+DEFUN ("case-table-p", Fcase_table_p, 1, 1, 0, /*
+Return t if ARG is a case table.
+See `set-case-table' for more information on these data structures.
+*/
+       (table))
+{
+  Lisp_Object down, up, canon, eqv;
+  if (!CONSP (table)) return Qnil; down  = XCAR (table); table = XCDR (table);
+  if (!CONSP (table)) return Qnil; up    = XCAR (table); table = XCDR (table);
+  if (!CONSP (table)) return Qnil; canon = XCAR (table); table = XCDR (table);
+  if (!CONSP (table)) return Qnil; eqv   = XCAR (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_tablep, obj);
+  return (obj);
+}
+
+DEFUN ("current-case-table", Fcurrent_case_table, 0, 1, 0, /*
+Return the case table of BUFFER, which defaults to the current buffer.
+*/
+       (buffer))
+{
+  struct buffer *buf = decode_buffer (buffer, 0);
+
+  return list4 (buf->downcase_table,
+		buf->upcase_table,
+		buf->case_canon_table,
+		buf->case_eqv_table);
+}
+
+DEFUN ("standard-case-table", Fstandard_case_table, 0, 0, 0, /*
+Return the standard case table.
+This is the one used for new buffers.
+*/
+       ())
+{
+  return list4 (Vascii_downcase_table,
+		Vascii_upcase_table,
+		Vascii_canon_table,
+		Vascii_eqv_table);
+}
+
+static Lisp_Object set_case_table (Lisp_Object table, int standard);
+
+
+DEFUN ("set-case-table", Fset_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.
+
+BUG: Under XEmacs/Mule, translations to or from non-ASCII characters
+ (this includes chars in the range 128 - 255) are ignored by
+ the string/buffer-searching routines.  Thus, `case-fold-search'
+ will not correctly conflate a-umlaut and A-umlaut even if the
+ case tables call for this.
+*/
+       (table))
+{
+  return set_case_table (table, 0);
+}
+
+DEFUN ("set-standard-case-table", Fset_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))
+{
+  return set_case_table (table, 1);
+}
+
+#ifdef MULE
+
+static Lisp_Object
+make_mirror_trt_table (Lisp_Object table)
+{
+  Lisp_Object new_table;
+
+  if (!STRING256_P (table))
+    {
+#ifdef DEBUG_XEMACS
+      /* This should be caught farther up. */
+      abort ();
+#else
+      signal_simple_error ("Invalid translate table", table);
+#endif
+    }
+
+  new_table = MAKE_MIRROR_TRT_TABLE ();
+  {
+    int i;
+
+    for (i = 0; i < 256; i++)
+      {
+	Emchar newval = string_char (XSTRING (table), i);
+	if ((i >= 128 && newval != i)
+	    || (i < 128 && newval >= 128))
+	  {
+	    newval = (Emchar) i;
+	  }
+	SET_MIRROR_TRT_TABLE_CHAR_1 (new_table, i, newval);
+      }
+  }
+  return new_table;
+}
+
+#endif /* MULE */
+
+static Lisp_Object
+set_case_table (Lisp_Object table, int standard)
+{
+  Lisp_Object down, up, canon, eqv, tail = table;
+  struct buffer *buf = current_buffer;
+
+  check_case_table (table);
+
+  down  = XCAR (tail); tail = XCDR (tail);
+  up    = XCAR (tail); tail = XCDR (tail);
+  canon = XCAR (tail); tail = XCDR (tail);
+  eqv   = XCAR (tail);
+
+  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;
+#ifdef MULE
+      Vmirror_ascii_downcase_table = make_mirror_trt_table (down);
+      Vmirror_ascii_upcase_table = make_mirror_trt_table (up);
+      Vmirror_ascii_canon_table = make_mirror_trt_table (canon);
+      Vmirror_ascii_eqv_table = make_mirror_trt_table (eqv);
+#endif
+    }
+  else
+    {
+      buf->downcase_table = down;
+      buf->upcase_table = up;
+      buf->case_canon_table = canon;
+      buf->case_eqv_table = eqv;
+#ifdef MULE
+      buf->mirror_downcase_table = make_mirror_trt_table (down);
+      buf->mirror_upcase_table = make_mirror_trt_table (up);
+      buf->mirror_case_canon_table = make_mirror_trt_table (canon);
+      buf->mirror_case_eqv_table = make_mirror_trt_table (eqv);
+#endif
+    }
+  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_tablep, "case-table-p");
+
+  DEFSUBR (Fcase_table_p);
+  DEFSUBR (Fcurrent_case_table);
+  DEFSUBR (Fstandard_case_table);
+  DEFSUBR (Fset_case_table);
+  DEFSUBR (Fset_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);
+
+#ifdef MULE
+  staticpro (&Vmirror_ascii_downcase_table);
+  staticpro (&Vmirror_ascii_upcase_table);
+  staticpro (&Vmirror_ascii_canon_table);
+  staticpro (&Vmirror_ascii_eqv_table);
+#endif
+
+  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);
+    }
+
+#ifdef MULE
+  tem = make_mirror_trt_table (tem);
+  Vmirror_ascii_downcase_table = tem;
+  Vmirror_ascii_canon_table = tem;
+#endif
+
+  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);
+    }
+
+#ifdef MULE
+  tem = make_mirror_trt_table (tem);
+  Vmirror_ascii_upcase_table = tem;
+  Vmirror_ascii_eqv_table = tem;
+#endif
+}