diff src/buffer.h @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents fdefd0186b75
children e38acbeb1cae
line wrap: on
line diff
--- a/src/buffer.h	Fri Mar 08 13:33:14 2002 +0000
+++ b/src/buffer.h	Wed Mar 13 08:54:06 2002 +0000
@@ -2,6 +2,7 @@
    Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995
    Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
+   Copyright (C) 2001, 2002 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -32,10 +33,6 @@
 #ifndef INCLUDED_buffer_h_
 #define INCLUDED_buffer_h_
 
-#ifdef MULE
-#include "mule-charset.h"
-#endif
-
 #include "casetab.h"
 #include "chartab.h"
 
@@ -93,8 +90,10 @@
 			   time buffer visited or saved a file.  */
 
 #ifdef MULE
-  /* We keep track of a "known" region for very fast access.
-     This information is text-only so it goes here. */
+  /* We keep track of a "known" region for very fast access.  This
+     information is text-only so it goes here.  We update this at each
+     change to the buffer, so if it's entirely ASCII, these will always
+     contain the minimum and maximum positions of the buffer. */
   Charbpos mule_bufmin, mule_bufmax;
   Bytebpos mule_bytmin, mule_bytmax;
   int mule_shifter, mule_three_p;
@@ -103,6 +102,8 @@
      positions. */
   Charbpos mule_charbpos_cache[16];
   Bytebpos mule_bytebpos_cache[16];
+
+  int entirely_ascii_p;
 #endif
 
   /* Similar to the above, we keep track of positions for which line
@@ -111,7 +112,6 @@
 
   /* Change data that goes with the text. */
   struct buffer_text_change_data *changes;
-
 };
 
 struct buffer
@@ -262,333 +262,6 @@
      )
 
 
-
-/************************************************************************/
-/*									*/
-/*		   working with raw internal-format data		*/
-/*									*/
-/************************************************************************/
-
-/* NOTE: In all the following macros, we follow these rules concerning
-   multiple evaluation of the arguments:
-
-   1) Anything that's an lvalue can be evaluated more than once.
-   2) Anything that's a Lisp Object can be evaluated more than once.
-      This should probably be changed, but this follows the way
-      that all the macros in lisp.h do things.
-   3) 'struct buffer *' arguments can be evaluated more than once.
-   4) Nothing else can be evaluated more than once.  Use inline
-      functions, if necessary, to prevent multiple evaluation.
-   5) An exception to (4) is that there are some macros below that
-      may evaluate their arguments more than once.  They are all
-      denoted with the word "unsafe" in their name and are generally
-      meant to be called only by other macros that have already
-      stored the calling values in temporary variables.
-
-
-   Use the following functions/macros on contiguous strings of data.
-   If the text you're operating on is known to come from a buffer, use
-   the buffer-level functions below -- they know about the gap and may
-   be more efficient.
-
-
-  (A) For working with charptr's (pointers to internally-formatted text):
-  -----------------------------------------------------------------------
-
-   VALID_CHARPTR_P (ptr):
-	Given a charptr, does it point to the beginning of a character?
-
-   ASSERT_VALID_CHARPTR (ptr):
-	If error-checking is enabled, assert that the given charptr
-	points to the beginning of a character.	 Otherwise, do nothing.
-
-   INC_CHARPTR (ptr):
-	Given a charptr (assumed to point at the beginning of a character),
-	modify that pointer so it points to the beginning of the next
-	character.
-
-   DEC_CHARPTR (ptr):
-	Given a charptr (assumed to point at the beginning of a
-	character or at the very end of the text), modify that pointer
-	so it points to the beginning of the previous character.
-
-   VALIDATE_CHARPTR_BACKWARD (ptr):
-	Make sure that PTR is pointing to the beginning of a character.
-	If not, back up until this is the case.	  Note that there are not
-	too many places where it is legitimate to do this sort of thing.
-	It's an error if you're passed an "invalid" char * pointer.
-	NOTE: PTR *must* be pointing to a valid part of the string (i.e.
-	not the very end, unless the string is zero-terminated or
-	something) in order for this function to not cause crashes.
-
-   VALIDATE_CHARPTR_FORWARD (ptr):
-	Make sure that PTR is pointing to the beginning of a character.
-	If not, move forward until this is the case.  Note that there
-	are not too many places where it is legitimate to do this sort
-	of thing.  It's an error if you're passed an "invalid" char *
-	pointer.
-
-
-   (B) For working with the length (in bytes and characters) of a
-       section of internally-formatted text:
-   --------------------------------------------------------------
-
-   bytecount_to_charcount (ptr, nbi):
-	Given a pointer to a text string and a length in bytes,
-	return the equivalent length in characters.
-
-   charcount_to_bytecount (ptr, nch):
-	Given a pointer to a text string and a length in characters,
-	return the equivalent length in bytes.
-
-   charptr_n_addr (ptr, n):
-	Return a pointer to the beginning of the character offset N
-	(in characters) from PTR.
-
-
-   (C) For retrieving or changing the character pointed to by a charptr:
-   ---------------------------------------------------------------------
-
-   charptr_emchar (ptr):
-	Retrieve the character pointed to by PTR as an Emchar.
-
-   charptr_emchar_n (ptr, n):
-	Retrieve the character at offset N (in characters) from PTR,
-	as an Emchar.
-
-   set_charptr_emchar (ptr, ch):
-	Store the character CH (an Emchar) as internally-formatted
-	text starting at PTR.  Return the number of bytes stored.
-
-   charptr_copy_char (ptr, ptr2):
-	Retrieve the character pointed to by PTR and store it as
-	internally-formatted text in PTR2.
-
-
-   (D) For working with Emchars:
-   -----------------------------
-
-   [Note that there are other functions/macros for working with Emchars
-    in mule-charset.h, for retrieving the charset of an Emchar
-    and such.  These are only valid when MULE is defined.]
-
-   valid_char_p (ch):
-	Return whether the given Emchar is valid.
-
-   CHARP (ch):
-	Return whether the given Lisp_Object is a character.
-
-   CHECK_CHAR_COERCE_INT (ch):
-	Signal an error if CH is not a valid character or integer Lisp_Object.
-	If CH is an integer Lisp_Object, convert it to a character Lisp_Object,
-	but merely by repackaging, without performing tests for char validity.
-
-   MAX_EMCHAR_LEN:
-	Maximum number of buffer bytes per Emacs character.
-
-*/
-
-
-/* ---------------------------------------------------------------------- */
-/* (A) For working with charptr's (pointers to internally-formatted text) */
-/* ---------------------------------------------------------------------- */
-
-#ifdef MULE
-# define VALID_CHARPTR_P(ptr) INTBYTE_FIRST_BYTE_P (* (unsigned char *) ptr)
-#else
-# define VALID_CHARPTR_P(ptr) 1
-#endif
-
-#ifdef ERROR_CHECK_CHARBPOS
-# define ASSERT_VALID_CHARPTR(ptr) assert (VALID_CHARPTR_P (ptr))
-#else
-# define ASSERT_VALID_CHARPTR(ptr)
-#endif
-
-/* Note that INC_CHARPTR() and DEC_CHARPTR() have to be written in
-   completely separate ways.  INC_CHARPTR() cannot use the DEC_CHARPTR()
-   trick of looking for a valid first byte because it might run off
-   the end of the string.  DEC_CHARPTR() can't use the INC_CHARPTR()
-   method because it doesn't have easy access to the first byte of
-   the character it's moving over. */
-
-#define REAL_INC_CHARPTR(ptr) \
-  ((void) ((ptr) += REP_BYTES_BY_FIRST_BYTE (* (unsigned char *) (ptr))))
-
-#define REAL_INC_CHARBYTEBPOS(ptr, pos) \
-  (pos += REP_BYTES_BY_FIRST_BYTE (* (unsigned char *) (ptr)))
-
-#define REAL_DEC_CHARPTR(ptr) do {	\
-  (ptr)--;				\
-} while (!VALID_CHARPTR_P (ptr))
-
-#ifdef ERROR_CHECK_CHARBPOS
-#define INC_CHARPTR(ptr) do {		\
-  ASSERT_VALID_CHARPTR (ptr);		\
-  REAL_INC_CHARPTR (ptr);		\
-} while (0)
-
-#define INC_CHARBYTEBPOS(ptr, pos) do {		\
-  ASSERT_VALID_CHARPTR (ptr);			\
-  REAL_INC_CHARBYTEBPOS (ptr, pos);		\
-} while (0)
-
-#define DEC_CHARPTR(ptr) do {			\
-  const Intbyte *dc_ptr1 = (ptr);		\
-  const Intbyte *dc_ptr2 = dc_ptr1;		\
-  REAL_DEC_CHARPTR (dc_ptr2);			\
-  assert (dc_ptr1 - dc_ptr2 ==			\
-	  REP_BYTES_BY_FIRST_BYTE (*dc_ptr2));	\
-  (ptr) = (Intbyte *) dc_ptr2;			\
-} while (0)
-
-#else /* ! ERROR_CHECK_CHARBPOS */
-#define INC_CHARBYTEBPOS(ptr, pos) REAL_INC_CHARBYTEBPOS (ptr, pos)
-#define INC_CHARPTR(ptr) REAL_INC_CHARPTR (ptr)
-#define DEC_CHARPTR(ptr) REAL_DEC_CHARPTR (ptr)
-#endif /* ! ERROR_CHECK_CHARBPOS */
-
-#ifdef MULE
-
-#define VALIDATE_CHARPTR_BACKWARD(ptr) do {	\
-  while (!VALID_CHARPTR_P (ptr)) ptr--;		\
-} while (0)
-
-/* This needs to be trickier to avoid the possibility of running off
-   the end of the string. */
-
-#define VALIDATE_CHARPTR_FORWARD(ptr) do {	\
-  Intbyte *vcf_ptr = (ptr);			\
-  VALIDATE_CHARPTR_BACKWARD (vcf_ptr);		\
-  if (vcf_ptr != (ptr))				\
-    {						\
-      (ptr) = vcf_ptr;				\
-      INC_CHARPTR (ptr);			\
-    }						\
-} while (0)
-
-#else /* not MULE */
-#define VALIDATE_CHARPTR_BACKWARD(ptr)
-#define VALIDATE_CHARPTR_FORWARD(ptr)
-#endif /* not MULE */
-
-/* -------------------------------------------------------------- */
-/* (B) For working with the length (in bytes and characters) of a */
-/*     section of internally-formatted text 			  */
-/* -------------------------------------------------------------- */
-
-INLINE_HEADER const Intbyte *
-charptr_n_addr (const Intbyte *ptr, Charcount offset);
-INLINE_HEADER const Intbyte *
-charptr_n_addr (const Intbyte *ptr, Charcount offset)
-{
-  return ptr + charcount_to_bytecount (ptr, offset);
-}
-
-/* -------------------------------------------------------------------- */
-/* (C) For retrieving or changing the character pointed to by a charptr */
-/* -------------------------------------------------------------------- */
-
-#define simple_charptr_emchar(ptr)		((Emchar) (ptr)[0])
-#define simple_set_charptr_emchar(ptr, x)	((ptr)[0] = (Intbyte) (x), 1)
-#define simple_charptr_copy_char(ptr, ptr2)	((ptr2)[0] = *(ptr), 1)
-
-#ifdef MULE
-
-Emchar non_ascii_charptr_emchar (const Intbyte *ptr);
-Bytecount non_ascii_set_charptr_emchar (Intbyte *ptr, Emchar c);
-Bytecount non_ascii_charptr_copy_char (const Intbyte *src, Intbyte *dst);
-
-INLINE_HEADER Emchar charptr_emchar (const Intbyte *ptr);
-INLINE_HEADER Emchar
-charptr_emchar (const Intbyte *ptr)
-{
-  return BYTE_ASCII_P (*ptr) ?
-    simple_charptr_emchar (ptr) :
-    non_ascii_charptr_emchar (ptr);
-}
-
-INLINE_HEADER Bytecount set_charptr_emchar (Intbyte *ptr, Emchar x);
-INLINE_HEADER Bytecount
-set_charptr_emchar (Intbyte *ptr, Emchar x)
-{
-  return !CHAR_MULTIBYTE_P (x) ?
-    simple_set_charptr_emchar (ptr, x) :
-    non_ascii_set_charptr_emchar (ptr, x);
-}
-
-/* Copy the character pointed to by SRC into DST.
-   Return the number of bytes copied.  */
-INLINE_HEADER Bytecount
-charptr_copy_char (const Intbyte *src, Intbyte *dst);
-INLINE_HEADER Bytecount
-charptr_copy_char (const Intbyte *src, Intbyte *dst)
-{
-  return BYTE_ASCII_P (*src) ?
-    simple_charptr_copy_char (src, dst) :
-    non_ascii_charptr_copy_char (src, dst);
-}
-
-#else /* not MULE */
-
-# define charptr_emchar(ptr)		simple_charptr_emchar (ptr)
-# define set_charptr_emchar(ptr, x)	simple_set_charptr_emchar (ptr, x)
-# define charptr_copy_char(ptr, ptr2)	simple_charptr_copy_char (ptr, ptr2)
-
-#endif /* not MULE */
-
-#define charptr_emchar_n(ptr, offset) \
-  charptr_emchar (charptr_n_addr (ptr, offset))
-
-
-/* ---------------------------- */
-/* (D) For working with Emchars */
-/* ---------------------------- */
-
-#ifdef MULE
-
-int non_ascii_valid_char_p (Emchar ch);
-
-INLINE_HEADER int valid_char_p (Emchar ch);
-INLINE_HEADER int
-valid_char_p (Emchar ch)
-{
-  return (! (ch & ~0xFF)) || non_ascii_valid_char_p (ch);
-}
-
-#else /* not MULE */
-
-#define valid_char_p(ch) (! (ch & ~0xFF))
-
-#endif /* not MULE */
-
-#define CHAR_INTP(x) (INTP (x) && valid_char_p (XINT (x)))
-
-#define CHAR_OR_CHAR_INTP(x) (CHARP (x) || CHAR_INTP (x))
-
-INLINE_HEADER Emchar XCHAR_OR_CHAR_INT (Lisp_Object obj);
-INLINE_HEADER Emchar
-XCHAR_OR_CHAR_INT (Lisp_Object obj)
-{
-  return CHARP (obj) ? XCHAR (obj) : XINT (obj);
-}
-
-#define CHECK_CHAR_COERCE_INT(x) do {		\
-  if (CHARP (x))				\
-     ;						\
-  else if (CHAR_INTP (x))			\
-    x = make_char (XINT (x));			\
-  else						\
-    x = wrong_type_argument (Qcharacterp, x);	\
-} while (0)
-
-#ifdef MULE
-# define MAX_EMCHAR_LEN 4
-#else
-# define MAX_EMCHAR_LEN 1
-#endif
-
-
 /*----------------------------------------------------------------------*/
 /*	    Accessor macros for important positions in a buffer		*/
 /*----------------------------------------------------------------------*/
@@ -718,21 +391,21 @@
 
 #define buffer_or_string_charbpos_to_bytebpos(obj, pos)		\
   (BUFFERP (obj) ? charbpos_to_bytebpos (XBUFFER (obj), pos) :	\
-   (Bytebpos) charcount_to_bytecount (XSTRING_DATA (obj), pos))
+   (Bytebpos) XSTRING_INDEX_CHAR_TO_BYTE (obj, pos))
 
 #define buffer_or_string_bytebpos_to_charbpos(obj, ind)		\
   (BUFFERP (obj) ? bytebpos_to_charbpos (XBUFFER (obj), ind) :	\
-   (Charbpos) bytecount_to_charcount (XSTRING_DATA (obj), ind))
+   (Charbpos) XSTRING_INDEX_BYTE_TO_CHAR (obj, ind))
 
 /* Similar for Charbpos's and Membposs. */
 
 #define buffer_or_string_charbpos_to_membpos(obj, pos)		\
   (BUFFERP (obj) ? charbpos_to_membpos (XBUFFER (obj), pos) :	\
-   (Membpos) charcount_to_bytecount (XSTRING_DATA (obj), pos))
+   (Membpos) XSTRING_INDEX_CHAR_TO_BYTE (obj, pos))
 
 #define buffer_or_string_membpos_to_charbpos(obj, ind)		\
   (BUFFERP (obj) ? membpos_to_charbpos (XBUFFER (obj), ind) :	\
-   (Charbpos) bytecount_to_charcount (XSTRING_DATA (obj), ind))
+   (Charbpos) XSTRING_INDEX_BYTE_TO_CHAR (obj, ind))
 
 /************************************************************************/
 /*                                                                      */
@@ -895,7 +568,7 @@
 
 #define DEC_BYTEBPOS(buf, x) do				\
 {							\
-  ASSERT_VALID_BYTEBPOS_BACKWARD_UNSAFE (buf, x);		\
+  ASSERT_VALID_BYTEBPOS_BACKWARD_UNSAFE (buf, x);	\
   /* Note that we do the decrement first to		\
      make sure that the pointer in			\
      VALIDATE_BYTEBPOS_BACKWARD() ends up on		\
@@ -932,53 +605,75 @@
 Charbpos bytebpos_to_charbpos_func (struct buffer *buf, Bytebpos x);
 
 /* The basic algorithm we use is to keep track of a known region of
-   characters in each buffer, all of which are of the same width.  We
-   keep track of the boundaries of the region in both Charbpos and
-   Bytebpos coordinates and also keep track of the char width, which
-   is 1 - 4 bytes.  If the position we're translating is not in
-   the known region, then we invoke a function to update the known
-   region to surround the position in question.  This assumes
-   locality of reference, which is usually the case.
+   characters in each buffer, all of which are of the same width.  We keep
+   track of the boundaries of the region in both Charbpos and Bytebpos
+   coordinates and also keep track of the char width, which is 1 - 4 bytes.
+   If the position we're translating is not in the known region, then we
+   invoke a function to update the known region to surround the position in
+   question.  This assumes locality of reference, which is usually the
+   case.
+
+   Note that the function to update the known region can be simple or
+   complicated depending on how much information we cache.  In addition to
+   the known region, we always cache the correct conversions for point,
+   BEGV, and ZV, and in addition to this we cache 16 positions where the
+   conversion is known.  We only look in the cache or update it when we
+   need to move the known region more than a certain amount (currently 50
+   chars), and then we throw away a "random" value and replace it with the
+   newly calculated value.
+
+   Finally, we maintain an extra flag that tracks whether the buffer is
+   entirely ASCII, to speed up the conversions even more.  This flag is
+   actually of dubious value because in an entirely-ASCII buffer the known
+   region will always span the entire buffer (in fact, we update the flag
+   based on this fact), and so all we're saving is a few machine cycles.
 
-   Note that the function to update the known region can be simple
-   or complicated depending on how much information we cache.
-   For the moment, we don't cache any information, and just move
-   linearly forward or back from the known region, with a few
-   shortcuts to catch all-ASCII buffers. (Note that this will
-   thrash with bad locality of reference.) A smarter method would
-   be to keep some sort of pseudo-extent layer over the buffer;
-   maybe keep track of the charbpos/bytebpos correspondence at the
-   beginning of each line, which would allow us to do a binary
-   search over the pseudo-extents to narrow things down to the
-   correct line, at which point you could use a linear movement
-   method.  This would also mesh well with efficiently
-   implementing a line-numbering scheme.
+   A potentially smarter method than what we do with known regions and
+   cached positions would be to keep some sort of pseudo-extent layer over
+   the buffer; maybe keep track of the charbpos/bytebpos correspondence at the
+   beginning of each line, which would allow us to do a binary search over
+   the pseudo-extents to narrow things down to the correct line, at which
+   point you could use a linear movement method.  This would also mesh well
+   with efficiently implementing a line-numbering scheme.  However, you
+   have to weigh the amount of time spent updating the cache vs. the
+   savings that result from it.  In reality, we modify the buffer far less
+   often than we access it, so a cache of this sort that provides
+   guaranteed LOG (N) performance (or perhaps N * LOG (N), if we set a
+   maximum on the cache size) would indeed be a win, particularly in very
+   large buffers.  If we ever implement this, we should probably set a
+   reasonably high minimum below which we use the old method, because the
+   time spent updating the fancy cache would likely become dominant when
+   making buffer modifications in smaller buffers.
 
-   Note also that we have to multiply or divide by the char width
-   in order to convert the positions.  We do some tricks to avoid
-   ever actually having to do a multiply or divide, because that
-   is typically an expensive operation (esp. divide).  Multiplying
-   or dividing by 1, 2, or 4 can be implemented simply as a
-   shift left or shift right, and we keep track of a shifter value
-   (0, 1, or 2) indicating how much to shift.  Multiplying by 3
-   can be implemented by doubling and then adding the original
-   value.  Dividing by 3, alas, cannot be implemented in any
-   simple shift/subtract method, as far as I know; so we just
-   do a table lookup.  For simplicity, we use a table of size
-   128K, which indexes the "divide-by-3" values for the first
-   64K non-negative numbers. (Note that we can increase the
-   size up to 384K, i.e. indexing the first 192K non-negative
-   numbers, while still using shorts in the array.) This also
-   means that the size of the known region can be at most
-   64K for width-three characters.
+   Note also that we have to multiply or divide by the char width in order
+   to convert the positions.  We do some tricks to avoid ever actually
+   having to do a multiply or divide, because that is typically an
+   expensive operation (esp. divide).  Multiplying or dividing by 1, 2, or
+   4 can be implemented simply as a shift left or shift right, and we keep
+   track of a shifter value (0, 1, or 2) indicating how much to shift.
+   Multiplying by 3 can be implemented by doubling and then adding the
+   original value.  Dividing by 3, alas, cannot be implemented in any
+   simple shift/subtract method, as far as I know; so we just do a table
+   lookup.  For simplicity, we use a table of size 128K, which indexes the
+   "divide-by-3" values for the first 64K non-negative numbers. (Note that
+   we can increase the size up to 384K, i.e. indexing the first 192K
+   non-negative numbers, while still using shorts in the array.) This also
+   means that the size of the known region can be at most 64K for
+   width-three characters.
+
+   !!#### We should investigate the algorithm in GNU Emacs.  I think it
+   does something similar, but it may differ in some details, and it's
+   worth seeing if anything can be gleaned.
    */
 
 extern short three_to_one_table[];
 
-INLINE_HEADER int real_charbpos_to_bytebpos (struct buffer *buf, Charbpos x);
-INLINE_HEADER int
+INLINE_HEADER Bytebpos real_charbpos_to_bytebpos (struct buffer *buf, Charbpos x);
+INLINE_HEADER Bytebpos
 real_charbpos_to_bytebpos (struct buffer *buf, Charbpos x)
 {
+  if (buf->text->entirely_ascii_p)
+    return (Bytebpos) x;
   if (x >= buf->text->mule_bufmin && x <= buf->text->mule_bufmax)
     return (buf->text->mule_bytmin +
 	    ((x - buf->text->mule_bufmin) << buf->text->mule_shifter) +
@@ -987,10 +682,12 @@
     return charbpos_to_bytebpos_func (buf, x);
 }
 
-INLINE_HEADER int real_bytebpos_to_charbpos (struct buffer *buf, Bytebpos x);
-INLINE_HEADER int
+INLINE_HEADER Charbpos real_bytebpos_to_charbpos (struct buffer *buf, Bytebpos x);
+INLINE_HEADER Charbpos
 real_bytebpos_to_charbpos (struct buffer *buf, Bytebpos x)
 {
+  if (buf->text->entirely_ascii_p)
+    return (Charbpos) x;
   if (x >= buf->text->mule_bytmin && x <= buf->text->mule_bytmax)
     return (buf->text->mule_bufmin +
 	    ((buf->text->mule_three_p
@@ -1043,330 +740,6 @@
 
 /************************************************************************/
 /*                                                                      */
-/*         Converting between internal and external format              */
-/*                                                                      */
-/************************************************************************/
-/*
-  All client code should use only the two macros
-
-  TO_EXTERNAL_FORMAT (source_type, source, sink_type, sink, coding_system)
-  TO_INTERNAL_FORMAT (source_type, source, sink_type, sink, coding_system)
-
-  Typical use is
-
-  TO_EXTERNAL_FORMAT (DATA, (ptr, len),
-                      LISP_BUFFER, buffer,
-		      Qfile_name);
-
-  The source or sink can be specified in one of these ways:
-
-  DATA,   (ptr, len),    // input data is a fixed buffer of size len
-  ALLOCA, (ptr, len),    // output data is in a alloca()ed buffer of size len
-  MALLOC, (ptr, len),    // output data is in a malloc()ed buffer of size len
-  C_STRING_ALLOCA, ptr,  // equivalent to ALLOCA (ptr, len_ignored) on output
-  C_STRING_MALLOC, ptr,  // equivalent to MALLOC (ptr, len_ignored) on output
-  C_STRING,     ptr,     // equivalent to DATA, (ptr, strlen (ptr) + 1) on input
-  LISP_STRING,  string,  // input or output is a Lisp_Object of type string
-  LISP_BUFFER,  buffer,  // output is written to (point) in lisp buffer
-  LISP_LSTREAM, lstream, // input or output is a Lisp_Object of type lstream
-  LISP_OPAQUE,  object,  // input or output is a Lisp_Object of type opaque
-
-  When specifying the sink, use lvalues, since the macro will assign to them,
-  except when the sink is an lstream or a lisp buffer.
-
-  The macros accept the kinds of sources and sinks appropriate for
-  internal and external data representation.  See the type_checking_assert
-  macros below for the actual allowed types.
-
-  Since some sources and sinks use one argument (a Lisp_Object) to
-  specify them, while others take a (pointer, length) pair, we use
-  some C preprocessor trickery to allow pair arguments to be specified
-  by parenthesizing them, as in the examples above.
-
-  Anything prefixed by dfc_ (`data format conversion') is private.
-  They are only used to implement these macros.
-
-  Using C_STRING* is appropriate for using with external APIs that take
-  null-terminated strings.  For internal data, we should try to be
-  '\0'-clean - i.e. allow arbitrary data to contain embedded '\0'.
-
-  Sometime in the future we might allow output to C_STRING_ALLOCA or
-  C_STRING_MALLOC _only_ with TO_EXTERNAL_FORMAT(), not
-  TO_INTERNAL_FORMAT().  */
-
-#define TO_EXTERNAL_FORMAT(source_type, source, sink_type, sink, coding_system)	\
-do {										\
-  dfc_conversion_type dfc_simplified_source_type;				\
-  dfc_conversion_type dfc_simplified_sink_type;					\
-  dfc_conversion_data dfc_source;						\
-  dfc_conversion_data dfc_sink;							\
-										\
-  type_checking_assert								\
-    ((DFC_TYPE_##source_type == DFC_TYPE_DATA ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_C_STRING ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_LISP_STRING ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_LISP_OPAQUE ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_LISP_LSTREAM)				\
-    &&										\
-     (DFC_TYPE_##sink_type == DFC_TYPE_ALLOCA ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_MALLOC ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_C_STRING_ALLOCA ||			\
-      DFC_TYPE_##sink_type == DFC_TYPE_C_STRING_MALLOC ||			\
-      DFC_TYPE_##sink_type == DFC_TYPE_LISP_LSTREAM ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_LISP_OPAQUE));				\
-										\
-  DFC_SOURCE_##source_type##_TO_ARGS (source);					\
-  DFC_SINK_##sink_type##_TO_ARGS     (sink);					\
-										\
-  DFC_CONVERT_TO_EXTERNAL_FORMAT (dfc_simplified_source_type, &dfc_source,	\
-				  coding_system,				\
-				  dfc_simplified_sink_type,   &dfc_sink);	\
-										\
-  DFC_##sink_type##_USE_CONVERTED_DATA (sink);					\
-} while (0)
-
-#define TO_INTERNAL_FORMAT(source_type, source, sink_type, sink, coding_system)	\
-do {										\
-  dfc_conversion_type dfc_simplified_source_type;				\
-  dfc_conversion_type dfc_simplified_sink_type;					\
-  dfc_conversion_data dfc_source;						\
-  dfc_conversion_data dfc_sink;							\
-										\
-  type_checking_assert								\
-    ((DFC_TYPE_##source_type == DFC_TYPE_DATA ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_C_STRING ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_LISP_OPAQUE ||				\
-      DFC_TYPE_##source_type == DFC_TYPE_LISP_LSTREAM)				\
-     &&										\
-     (DFC_TYPE_##sink_type == DFC_TYPE_ALLOCA ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_MALLOC ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_C_STRING_ALLOCA ||			\
-      DFC_TYPE_##sink_type == DFC_TYPE_C_STRING_MALLOC ||			\
-      DFC_TYPE_##sink_type == DFC_TYPE_LISP_STRING ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_LISP_LSTREAM ||				\
-      DFC_TYPE_##sink_type == DFC_TYPE_LISP_BUFFER));				\
-										\
-  DFC_SOURCE_##source_type##_TO_ARGS (source);					\
-  DFC_SINK_##sink_type##_TO_ARGS     (sink);					\
-										\
-  DFC_CONVERT_TO_INTERNAL_FORMAT (dfc_simplified_source_type, &dfc_source,	\
-				  coding_system,				\
-				  dfc_simplified_sink_type,   &dfc_sink);	\
-										\
-  DFC_##sink_type##_USE_CONVERTED_DATA (sink);					\
-} while (0)
-
-#ifdef FILE_CODING
-#define DFC_CONVERT_TO_EXTERNAL_FORMAT dfc_convert_to_external_format
-#define DFC_CONVERT_TO_INTERNAL_FORMAT dfc_convert_to_internal_format
-#else
-/* ignore coding_system argument */
-#define DFC_CONVERT_TO_EXTERNAL_FORMAT(a, b, coding_system, c, d) \
- dfc_convert_to_external_format (a, b, c, d)
-#define DFC_CONVERT_TO_INTERNAL_FORMAT(a, b, coding_system, c, d) \
- dfc_convert_to_internal_format (a, b, c, d)
-#endif
-
-typedef union
-{
-  struct { const void *ptr; Bytecount len; } data;
-  Lisp_Object lisp_object;
-} dfc_conversion_data;
-
-enum dfc_conversion_type
-{
-  DFC_TYPE_DATA,
-  DFC_TYPE_ALLOCA,
-  DFC_TYPE_MALLOC,
-  DFC_TYPE_C_STRING,
-  DFC_TYPE_C_STRING_ALLOCA,
-  DFC_TYPE_C_STRING_MALLOC,
-  DFC_TYPE_LISP_STRING,
-  DFC_TYPE_LISP_LSTREAM,
-  DFC_TYPE_LISP_OPAQUE,
-  DFC_TYPE_LISP_BUFFER
-};
-typedef enum dfc_conversion_type dfc_conversion_type;
-
-/* WARNING: These use a static buffer.  This can lead to disaster if
-   these functions are not used *very* carefully.  Another reason to only use
-   TO_EXTERNAL_FORMAT() and TO_INTERNAL_FORMAT(). */
-void
-dfc_convert_to_external_format (dfc_conversion_type source_type,
-				dfc_conversion_data *source,
-#ifdef FILE_CODING
-				Lisp_Object coding_system,
-#endif
-				dfc_conversion_type sink_type,
-				dfc_conversion_data *sink);
-void
-dfc_convert_to_internal_format (dfc_conversion_type source_type,
-				dfc_conversion_data *source,
-#ifdef FILE_CODING
-				Lisp_Object coding_system,
-#endif
-				dfc_conversion_type sink_type,
-				dfc_conversion_data *sink);
-/* CPP Trickery */
-#define DFC_CPP_CAR(x,y) (x)
-#define DFC_CPP_CDR(x,y) (y)
-
-/* Convert `source' to args for dfc_convert_to_*_format() */
-#define DFC_SOURCE_DATA_TO_ARGS(val) do {		\
-  dfc_source.data.ptr = DFC_CPP_CAR val;		\
-  dfc_source.data.len = DFC_CPP_CDR val;		\
-  dfc_simplified_source_type = DFC_TYPE_DATA;		\
-} while (0)
-#define DFC_SOURCE_C_STRING_TO_ARGS(val) do {		\
-  dfc_source.data.len =					\
-    strlen ((char *) (dfc_source.data.ptr = (val)));	\
-  dfc_simplified_source_type = DFC_TYPE_DATA;		\
-} while (0)
-#define DFC_SOURCE_LISP_STRING_TO_ARGS(val) do {	\
-  Lisp_Object dfc_slsta = (val);			\
-  type_checking_assert (STRINGP (dfc_slsta));		\
-  dfc_source.lisp_object = dfc_slsta;			\
-  dfc_simplified_source_type = DFC_TYPE_LISP_STRING;	\
-} while (0)
-#define DFC_SOURCE_LISP_LSTREAM_TO_ARGS(val) do {	\
-  Lisp_Object dfc_sllta = (val);			\
-  type_checking_assert (LSTREAMP (dfc_sllta));		\
-  dfc_source.lisp_object = dfc_sllta;			\
-  dfc_simplified_source_type = DFC_TYPE_LISP_LSTREAM;	\
-} while (0)
-#define DFC_SOURCE_LISP_OPAQUE_TO_ARGS(val) do {	\
-  Lisp_Opaque *dfc_slota = XOPAQUE (val);		\
-  dfc_source.data.ptr = OPAQUE_DATA (dfc_slota);	\
-  dfc_source.data.len = OPAQUE_SIZE (dfc_slota);	\
-  dfc_simplified_source_type = DFC_TYPE_DATA;		\
-} while (0)
-
-/* Convert `sink' to args for dfc_convert_to_*_format() */
-#define DFC_SINK_ALLOCA_TO_ARGS(val)		\
-  dfc_simplified_sink_type = DFC_TYPE_DATA
-#define DFC_SINK_C_STRING_ALLOCA_TO_ARGS(val)	\
-  dfc_simplified_sink_type = DFC_TYPE_DATA
-#define DFC_SINK_MALLOC_TO_ARGS(val)		\
-  dfc_simplified_sink_type = DFC_TYPE_DATA
-#define DFC_SINK_C_STRING_MALLOC_TO_ARGS(val)	\
-  dfc_simplified_sink_type = DFC_TYPE_DATA
-#define DFC_SINK_LISP_STRING_TO_ARGS(val)	\
-  dfc_simplified_sink_type = DFC_TYPE_DATA
-#define DFC_SINK_LISP_OPAQUE_TO_ARGS(val)	\
-  dfc_simplified_sink_type = DFC_TYPE_DATA
-#define DFC_SINK_LISP_LSTREAM_TO_ARGS(val) do {		\
-  Lisp_Object dfc_sllta = (val);			\
-  type_checking_assert (LSTREAMP (dfc_sllta));		\
-  dfc_sink.lisp_object = dfc_sllta;			\
-  dfc_simplified_sink_type = DFC_TYPE_LISP_LSTREAM;	\
-} while (0)
-#define DFC_SINK_LISP_BUFFER_TO_ARGS(val) do {		\
-  struct buffer *dfc_slbta = XBUFFER (val);		\
-  dfc_sink.lisp_object =				\
-    make_lisp_buffer_output_stream			\
-    (dfc_slbta, BUF_PT (dfc_slbta), 0);			\
-  dfc_simplified_sink_type = DFC_TYPE_LISP_LSTREAM;	\
-} while (0)
-
-/* Assign to the `sink' lvalue(s) using the converted data. */
-typedef union { char c; void *p; } *dfc_aliasing_voidpp;
-#define DFC_ALLOCA_USE_CONVERTED_DATA(sink) do {			\
-  void * dfc_sink_ret = alloca (dfc_sink.data.len + 1);			\
-  memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 1);	\
-  ((dfc_aliasing_voidpp) &(DFC_CPP_CAR sink))->p = dfc_sink_ret;	\
-  (DFC_CPP_CDR sink) = dfc_sink.data.len;				\
-} while (0)
-#define DFC_MALLOC_USE_CONVERTED_DATA(sink) do {			\
-  void * dfc_sink_ret = xmalloc (dfc_sink.data.len + 1);		\
-  memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 1);	\
-  ((dfc_aliasing_voidpp) &(DFC_CPP_CAR sink))->p = dfc_sink_ret;	\
-  (DFC_CPP_CDR sink) = dfc_sink.data.len;				\
-} while (0)
-#define DFC_C_STRING_ALLOCA_USE_CONVERTED_DATA(sink) do {		\
-  void * dfc_sink_ret = alloca (dfc_sink.data.len + 1);			\
-  memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 1);	\
-  ((dfc_aliasing_voidpp) &(sink))->p = dfc_sink_ret;			\
-} while (0)
-#define DFC_C_STRING_MALLOC_USE_CONVERTED_DATA(sink) do {		\
-  void * dfc_sink_ret = xmalloc (dfc_sink.data.len + 1);		\
-  memcpy (dfc_sink_ret, dfc_sink.data.ptr, dfc_sink.data.len + 1);	\
-  ((dfc_aliasing_voidpp) &(sink))->p = dfc_sink_ret;			\
-} while (0)
-#define DFC_LISP_STRING_USE_CONVERTED_DATA(sink) \
-  sink = make_string ((Intbyte *) dfc_sink.data.ptr, dfc_sink.data.len)
-#define DFC_LISP_OPAQUE_USE_CONVERTED_DATA(sink) \
-  sink = make_opaque (dfc_sink.data.ptr, dfc_sink.data.len)
-#define DFC_LISP_LSTREAM_USE_CONVERTED_DATA(sink) /* data already used */
-#define DFC_LISP_BUFFER_USE_CONVERTED_DATA(sink) \
-  Lstream_delete (XLSTREAM (dfc_sink.lisp_object))
-
-/* Someday we might want to distinguish between Qnative and Qfile_name
-   by using coding-system aliases, but for now it suffices to have
-   these be identical.  Qnative can be used as the coding_system
-   argument to TO_EXTERNAL_FORMAT() and TO_INTERNAL_FORMAT(). */
-#define Qnative Qfile_name
-
-#if defined (WIN32_NATIVE) || defined (CYGWIN)
-/* #### kludge!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-   Remove this as soon as my Mule code is integrated. */
-#define Qmswindows_tstr Qnative
-#endif
-
-/* More stand-ins */
-#define Qcommand_argument_encoding Qnative
-#define Qenvironment_variable_encoding Qnative
-
-/* Convenience macros for extremely common invocations */
-#define C_STRING_TO_EXTERNAL(in, out, coding_system) \
-  TO_EXTERNAL_FORMAT (C_STRING, in, C_STRING_ALLOCA, out, coding_system)
-#define C_STRING_TO_EXTERNAL_MALLOC(in, out, coding_system) \
-  TO_EXTERNAL_FORMAT (C_STRING, in, C_STRING_MALLOC, out, coding_system)
-#define EXTERNAL_TO_C_STRING(in, out, coding_system) \
-  TO_INTERNAL_FORMAT (C_STRING, in, C_STRING_ALLOCA, out, coding_system)
-#define EXTERNAL_TO_C_STRING_MALLOC(in, out, coding_system) \
-  TO_INTERNAL_FORMAT (C_STRING, in, C_STRING_MALLOC, out, coding_system)
-#define LISP_STRING_TO_EXTERNAL(in, out, coding_system) \
-  TO_EXTERNAL_FORMAT (LISP_STRING, in, C_STRING_ALLOCA, out, coding_system)
-#define LISP_STRING_TO_EXTERNAL_MALLOC(in, out, coding_system) \
-  TO_EXTERNAL_FORMAT (LISP_STRING, in, C_STRING_MALLOC, out, coding_system)
-
-
-/************************************************************************/
-/*                                                                      */
-/*                          fake charset functions                      */
-/*                                                                      */
-/************************************************************************/
-
-/* used when MULE is not defined, so that Charset-type stuff can still
-   be done */
-
-#ifndef MULE
-
-#define Vcharset_ascii Qnil
-
-#define CHAR_CHARSET(ch) Vcharset_ascii
-#define CHAR_LEADING_BYTE(ch) LEADING_BYTE_ASCII
-#define LEADING_BYTE_ASCII 0x80
-#define NUM_LEADING_BYTES 1
-#define MIN_LEADING_BYTE 0x80
-#define CHARSETP(cs) 1
-#define CHARSET_BY_LEADING_BYTE(lb) Vcharset_ascii
-#define XCHARSET_LEADING_BYTE(cs) LEADING_BYTE_ASCII
-#define XCHARSET_GRAPHIC(cs) -1
-#define XCHARSET_COLUMNS(cs) 1
-#define XCHARSET_DIMENSION(cs) 1
-#define REP_BYTES_BY_FIRST_BYTE(fb) 1
-#define BREAKUP_CHAR(ch, charset, byte1, byte2) do {	\
-  (charset) = Vcharset_ascii;				\
-  (byte1) = (ch);					\
-  (byte2) = 0;						\
-} while (0)
-#define BYTE_ASCII_P(byte) 1
-
-#endif /* ! MULE */
-
-/************************************************************************/
-/*                                                                      */
 /*                  higher-level buffer-position functions              */
 /*                                                                      */
 /************************************************************************/
@@ -1448,7 +821,7 @@
    OLD_BI_FLOOR_OF(n) = NEW_BI_FLOOR_OF(n + 1)
 
    The definitions were changed because the new definitions are more
-   consistent with the way everything else works in Emacs.
+   consistent with the way everything else works in XEmacs.
  */
 
 /* Properties of CEILING_OF and FLOOR_OF (also apply to BI_ variants):
@@ -1471,7 +844,28 @@
       [BYTE_ADDRESS (FLOOR_OF (n)), BYTE_ADDRESS_BEFORE (n)]
 
       are contiguous.
-   */
+
+  A typical loop using CEILING_OF to process contiguous ranges of text
+  between [from, to) looks like this:
+  
+  {
+    Bytebpos pos = from;
+
+    while (pos < to)
+      {
+	Bytebpos ceil;
+
+	ceil = BI_BUF_CEILING_OF (buf, pos);
+	ceil = min (to, ceil);
+	process_intbyte_string (BI_BUF_BYTE_ADDRESS (buf, pos), ceil - pos);
+	pos = ceil;
+      }
+  }
+
+  Currently there will be at most two iterations in the loop, but it is
+  written in such a way that it will still work if the buffer
+  representation is changed to have multiple gaps in it.
+  */
 
 
 /*  Return the maximum index in the buffer it is safe to scan forwards
@@ -1509,38 +903,6 @@
   bytebpos_to_charbpos							\
    (b, BI_BUF_FLOOR_OF_IGNORE_ACCESSIBLE (b, charbpos_to_bytebpos (b, n)))
 
-
-extern struct buffer *current_buffer;
-
-/* This is the initial (startup) directory, as used for the *scratch* buffer.
-   We're making this a global to make others aware of the startup directory.
-   `initial_directory' is stored in external format.
- */
-extern char initial_directory[];
-extern void init_initial_directory (void);   /* initialize initial_directory */
-
-EXFUN (Fbuffer_disable_undo, 1);
-EXFUN (Fbuffer_modified_p, 1);
-EXFUN (Fbuffer_name, 1);
-EXFUN (Fcurrent_buffer, 0);
-EXFUN (Ferase_buffer, 1);
-EXFUN (Fget_buffer, 1);
-EXFUN (Fget_buffer_create, 1);
-EXFUN (Fget_file_buffer, 1);
-EXFUN (Fkill_buffer, 1);
-EXFUN (Fother_buffer, 3);
-EXFUN (Frecord_buffer, 1);
-EXFUN (Fset_buffer, 1);
-EXFUN (Fset_buffer_modified_p, 2);
-
-extern Lisp_Object QSscratch, Qafter_change_function, Qafter_change_functions;
-extern Lisp_Object Qbefore_change_function, Qbefore_change_functions;
-extern Lisp_Object Qbuffer_or_string_p, Qdefault_directory, Qfirst_change_hook;
-extern Lisp_Object Qpermanent_local, Vafter_change_function;
-extern Lisp_Object Vafter_change_functions, Vbefore_change_function;
-extern Lisp_Object Vbefore_change_functions, Vbuffer_alist, Vbuffer_defaults;
-extern Lisp_Object Vinhibit_read_only, Vtransient_mark_mode;
-
 /* This structure marks which slots in a buffer have corresponding
    default values in Vbuffer_defaults.
    Each such slot has a nonzero value in this structure.
@@ -1584,97 +946,6 @@
 
 #endif /* !REL_ALLOC */
 
-extern Lisp_Object Vbuffer_alist;
-void set_buffer_internal (struct buffer *b);
-struct buffer *decode_buffer (Lisp_Object buffer, int allow_string);
-
-/* from editfns.c */
-void widen_buffer (struct buffer *b, int no_clip);
-int beginning_of_line_p (struct buffer *b, Charbpos pt);
-
-/* from insdel.c */
-void set_buffer_point (struct buffer *buf, Charbpos pos, Bytebpos bipos);
-void find_charsets_in_intbyte_string (unsigned char *charsets,
-				      const Intbyte *str,
-				      Bytecount len);
-void find_charsets_in_emchar_string (unsigned char *charsets,
-				     const Emchar *str,
-				     Charcount len);
-int intbyte_string_displayed_columns (const Intbyte *str, Bytecount len);
-int emchar_string_displayed_columns (const Emchar *str, Charcount len);
-void convert_intbyte_string_into_emchar_dynarr (const Intbyte *str,
-						Bytecount len,
-						Emchar_dynarr *dyn);
-Charcount convert_intbyte_string_into_emchar_string (const Intbyte *str,
-						     Bytecount len,
-						     Emchar *arr);
-void convert_emchar_string_into_intbyte_dynarr (Emchar *arr, int nels,
-						Intbyte_dynarr *dyn);
-Intbyte *convert_emchar_string_into_malloced_string (Emchar *arr, int nels,
-						    Bytecount *len_out);
-/* from marker.c */
-void init_buffer_markers (struct buffer *b);
-void uninit_buffer_markers (struct buffer *b);
-
-/* flags for get_buffer_pos_char(), get_buffer_range_char(), etc. */
-/* At most one of GB_COERCE_RANGE and GB_NO_ERROR_IF_BAD should be
-   specified.  At most one of GB_NEGATIVE_FROM_END and GB_NO_ERROR_IF_BAD
-   should be specified. */
-
-#define GB_ALLOW_PAST_ACCESSIBLE	(1 << 0)
-#define GB_ALLOW_NIL			(1 << 1)
-#define GB_CHECK_ORDER			(1 << 2)
-#define GB_COERCE_RANGE			(1 << 3)
-#define GB_NO_ERROR_IF_BAD		(1 << 4)
-#define GB_NEGATIVE_FROM_END		(1 << 5)
-#define GB_HISTORICAL_STRING_BEHAVIOR	(GB_NEGATIVE_FROM_END | GB_ALLOW_NIL)
-
-Charbpos get_buffer_pos_char (struct buffer *b, Lisp_Object pos,
-			    unsigned int flags);
-Bytebpos get_buffer_pos_byte (struct buffer *b, Lisp_Object pos,
-			    unsigned int flags);
-void get_buffer_range_char (struct buffer *b, Lisp_Object from, Lisp_Object to,
-			    Charbpos *from_out, Charbpos *to_out,
-			    unsigned int flags);
-void get_buffer_range_byte (struct buffer *b, Lisp_Object from, Lisp_Object to,
-			    Bytebpos *from_out, Bytebpos *to_out,
-			    unsigned int flags);
-Charcount get_string_pos_char (Lisp_Object string, Lisp_Object pos,
-			       unsigned int flags);
-Bytecount get_string_pos_byte (Lisp_Object string, Lisp_Object pos,
-			       unsigned int flags);
-void get_string_range_char (Lisp_Object string, Lisp_Object from,
-			    Lisp_Object to, Charcount *from_out,
-			    Charcount *to_out, unsigned int flags);
-void get_string_range_byte (Lisp_Object string, Lisp_Object from,
-			    Lisp_Object to, Bytecount *from_out,
-			    Bytecount *to_out, unsigned int flags);
-Charbpos get_buffer_or_string_pos_char (Lisp_Object object, Lisp_Object pos,
-				      unsigned int flags);
-Bytebpos get_buffer_or_string_pos_byte (Lisp_Object object, Lisp_Object pos,
-				      unsigned int flags);
-void get_buffer_or_string_range_char (Lisp_Object object, Lisp_Object from,
-				      Lisp_Object to, Charbpos *from_out,
-				      Charbpos *to_out, unsigned int flags);
-void get_buffer_or_string_range_byte (Lisp_Object object, Lisp_Object from,
-				      Lisp_Object to, Bytebpos *from_out,
-				      Bytebpos *to_out, unsigned int flags);
-Charbpos buffer_or_string_accessible_begin_char (Lisp_Object object);
-Charbpos buffer_or_string_accessible_end_char (Lisp_Object object);
-Bytebpos buffer_or_string_accessible_begin_byte (Lisp_Object object);
-Bytebpos buffer_or_string_accessible_end_byte (Lisp_Object object);
-Charbpos buffer_or_string_absolute_begin_char (Lisp_Object object);
-Charbpos buffer_or_string_absolute_end_char (Lisp_Object object);
-Bytebpos buffer_or_string_absolute_begin_byte (Lisp_Object object);
-Bytebpos buffer_or_string_absolute_end_byte (Lisp_Object object);
-void record_buffer (Lisp_Object buf);
-Lisp_Object get_buffer (Lisp_Object name,
-			int error_if_deleted_or_does_not_exist);
-int map_over_sharing_buffers (struct buffer *buf,
-			      int (*mapfun) (struct buffer *buf,
-					     void *closure),
-			      void *closure);
-
 
 /************************************************************************/
 /*                         Case conversion                              */
@@ -1715,11 +986,18 @@
   return TRT_TABLE_CHAR_1 (trt, c);
 }
 
+INLINE_HEADER Lisp_Object BUFFER_CASE_TABLE (struct buffer *buf);
+INLINE_HEADER Lisp_Object
+BUFFER_CASE_TABLE (struct buffer *buf)
+{
+  return buf ? buf->case_table : Vstandard_case_table;
+}
+
 /* Macros used below. */
 #define DOWNCASE_TABLE_OF(buf, c)	\
-  TRT_TABLE_OF (XCASE_TABLE_DOWNCASE (buf->case_table), c)
+  TRT_TABLE_OF (XCASE_TABLE_DOWNCASE (BUFFER_CASE_TABLE (buf)), c)
 #define UPCASE_TABLE_OF(buf, c)		\
-  TRT_TABLE_OF (XCASE_TABLE_UPCASE (buf->case_table), c)
+  TRT_TABLE_OF (XCASE_TABLE_UPCASE (BUFFER_CASE_TABLE (buf)), c)
 
 /* 1 if CH is upper case.  */
 
@@ -1766,60 +1044,4 @@
 
 #define DOWNCASE(buf, ch) DOWNCASE_TABLE_OF (buf, ch)
 
-/************************************************************************/
-/*		Lisp string representation convenience functions	*/
-/************************************************************************/
-/* Because the representation of internally formatted data is subject to change,
-   It's bad style to do something like strcmp (XSTRING_DATA (s), "foo")
-   Instead, use the portable: intbyte_strcmp (XSTRING_DATA (s), "foo")
-   or intbyte_memcmp (XSTRING_DATA (s), "foo", 3) */
-
-/* Like strcmp, except first arg points at internally formatted data,
-   while the second points at a string of only ASCII chars. */
-INLINE_HEADER int
-intbyte_strcmp (const Intbyte *bp, const char *ascii_string);
-INLINE_HEADER int
-intbyte_strcmp (const Intbyte *bp, const char *ascii_string)
-{
-#ifdef MULE
-  while (1)
-    {
-      int diff;
-      type_checking_assert (BYTE_ASCII_P (*ascii_string));
-      if ((diff = charptr_emchar (bp) - *(Intbyte *) ascii_string) != 0)
-	return diff;
-      if (*ascii_string == '\0')
-	return 0;
-      ascii_string++;
-      INC_CHARPTR (bp);
-    }
-#else
-  return strcmp ((char *)bp, ascii_string);
-#endif
-}
-
-
-/* Like memcmp, except first arg points at internally formatted data,
-   while the second points at a string of only ASCII chars. */
-INLINE_HEADER int
-intbyte_memcmp (const Intbyte *bp, const char *ascii_string, Bytecount len);
-INLINE_HEADER int
-intbyte_memcmp (const Intbyte *bp, const char *ascii_string, Bytecount len)
-{
-#ifdef MULE
-  while (len--)
-    {
-      int diff = charptr_emchar (bp) - *(Intbyte *) ascii_string;
-      type_checking_assert (BYTE_ASCII_P (*ascii_string));
-      if (diff != 0)
-	return diff;
-      ascii_string++;
-      INC_CHARPTR (bp);
-    }
-  return 0;
-#else
-  return memcmp (bp, ascii_string, len);
-#endif
-}
-
 #endif /* INCLUDED_buffer_h_ */