diff src/buffer.h @ 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 9d177e8d4150
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/buffer.h	Mon Aug 13 11:28:15 2007 +0200
@@ -0,0 +1,1797 @@
+/* Header file for the buffer manipulation primitives.
+   Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995
+   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.30. */
+
+/* Authorship:
+
+   FSF: long ago.
+   JWZ: separated out bufslots.h, early in Lemacs.
+   Ben Wing: almost completely rewritten for Mule, 19.12.
+ */
+
+#ifndef _XEMACS_BUFFER_H_
+#define _XEMACS_BUFFER_H_
+
+#ifdef MULE
+#include "mule-charset.h"
+#endif
+
+/************************************************************************/
+/*                                                                      */
+/*                    definition of Lisp buffer object                  */
+/*                                                                      */
+/************************************************************************/
+
+/* Note: we keep both Bytind and Bufpos versions of some of the
+   important buffer positions because they are accessed so much.
+   If we didn't do this, we would constantly be invalidating the
+   bufpos<->bytind cache under Mule.
+
+   Note that under non-Mule, both versions will always be the
+   same so we don't really need to keep track of them.  But it
+   simplifies the logic to go ahead and do so all the time and
+   the memory loss is insignificant. */
+
+/* Formerly, it didn't much matter what went inside the struct buffer_text
+   and what went outside it.  Now it does, with the advent of "indirect
+   buffers" that share text with another buffer.  An indirect buffer
+   shares the same *text* as another buffer, but has its own buffer-local
+   variables, its own accessible region, and its own markers and extents.
+   (Due to the nature of markers, it doesn't actually matter much whether
+   we stick them inside or out of the struct buffer_text -- the user won't
+   notice any difference -- but we go ahead and put them outside for
+   consistency and overall saneness of algorithm.)
+
+   FSFmacs gets away with not maintaining any "children" pointers from
+   a buffer to the indirect buffers that refer to it by putting the
+   markers inside of the struct buffer_text, using markers to keep track
+   of BEGV and ZV in indirect buffers, and relying on the fact that
+   all intervals (text properties and overlays) use markers for their
+   start and end points.  We don't do this for extents (markers are
+   inefficient anyway and take up space), so we have to maintain
+   children pointers.  This is not terribly hard, though, and the
+   code to maintain this is just like the code already present in
+   extent-parent and extent-children.
+   */
+
+struct buffer_text
+{
+  Bufbyte *beg;		/* Actual address of buffer contents. */
+  Bytind gpt;		/* Index of gap in buffer. */
+  Bytind z;		/* Index of end of buffer. */
+  Bufpos bufz;		/* Equivalent as a Bufpos. */
+  int gap_size;		/* Size of buffer's gap */
+  int end_gap_size;	/* Size of buffer's end gap */
+  long modiff;		/* This counts buffer-modification events
+			   for this buffer.  It is incremented for
+			   each such event, and never otherwise
+			   changed.  */
+  long save_modiff;	/* Previous value of modiff, as of last
+			   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. */
+  Bufpos mule_bufmin, mule_bufmax;
+  Bytind mule_bytmin, mule_bytmax;
+  int mule_shifter, mule_three_p;
+
+  /* And we also cache 16 positions for fairly fast access near those
+     positions. */
+  Bufpos mule_bufpos_cache[16];
+  Bytind mule_bytind_cache[16];
+#endif
+
+  /* Similar to the above, we keep track of positions for which line
+     number has last been calculated.  See line-number.c. */
+  Lisp_Object line_number_cache;
+
+  /* Change data that goes with the text. */
+  struct buffer_text_change_data *changes;
+
+};
+
+struct buffer
+{
+  struct lcrecord_header header;
+
+  /* This structure holds the coordinates of the buffer contents
+     in ordinary buffers.  In indirect buffers, this is not used.  */
+  struct buffer_text own_text;
+
+  /* This points to the `struct buffer_text' that is used for this buffer.
+     In an ordinary buffer, this is the own_text field above.
+     In an indirect buffer, this is the own_text field of another buffer.  */
+  struct buffer_text *text;
+
+  Bytind pt;		/* Position of point in buffer. */
+  Bufpos bufpt;		/* Equivalent as a Bufpos. */
+  Bytind begv;		/* Index of beginning of accessible range. */
+  Bufpos bufbegv;	/* Equivalent as a Bufpos. */
+  Bytind zv;		/* Index of end of accessible range. */
+  Bufpos bufzv;		/* Equivalent as a Bufpos. */
+
+  int face_change;	/* This is set when a change in how the text should
+			   be displayed (e.g., font, color) is made. */
+
+  /* change data indicating what portion of the text has changed
+     since the last time this was reset.  Used by redisplay.
+     Logically we should keep this with the text structure, but
+     redisplay resets it for each buffer individually and we don't
+     want interference between an indirect buffer and its base
+     buffer. */
+  struct each_buffer_change_data *changes;
+
+#ifdef REGION_CACHE_NEEDS_WORK
+  /* If the long line scan cache is enabled (i.e. the buffer-local
+     variable cache-long-line-scans is non-nil), newline_cache
+     points to the newline cache, and width_run_cache points to the
+     width run cache.
+
+     The newline cache records which stretches of the buffer are
+     known *not* to contain newlines, so that they can be skipped
+     quickly when we search for newlines.
+
+     The width run cache records which stretches of the buffer are
+     known to contain characters whose widths are all the same.  If
+     the width run cache maps a character to a value > 0, that value
+     is the character's width; if it maps a character to zero, we
+     don't know what its width is.  This allows compute_motion to
+     process such regions very quickly, using algebra instead of
+     inspecting each character.  See also width_table, below.  */
+  struct region_cache *newline_cache;
+  struct region_cache *width_run_cache;
+#endif /* REGION_CACHE_NEEDS_WORK */
+
+  /* The markers that refer to this buffer.  This is actually a single
+     marker -- successive elements in its marker `chain' are the other
+     markers referring to this buffer */
+  struct Lisp_Marker *markers;
+
+  /* The buffer's extent info.  This is its own type, an extent-info
+     object (done this way for ease in marking / finalizing). */
+  Lisp_Object extent_info;
+
+  /* ----------------------------------------------------------------- */
+  /* All the stuff above this line is the responsibility of insdel.c,
+     with some help from marker.c and extents.c.
+     All the stuff below this line is the responsibility of buffer.c. */
+
+  /* In an indirect buffer, this points to the base buffer.
+     In an ordinary buffer, it is 0.
+     We DO mark through this slot. */
+  struct buffer *base_buffer;
+
+  /* List of indirect buffers whose base is this buffer.
+     If we are an indirect buffer, this will be nil.
+     Do NOT mark through this. */
+  Lisp_Object indirect_children;
+
+  /* Flags saying which DEFVAR_PER_BUFFER variables
+     are local to this buffer.  */
+  int local_var_flags;
+
+  /* Set to the modtime of the visited file when read or written.
+     -1 means visited file was nonexistent.
+     0  means visited file modtime unknown; in no case complain
+     about any mismatch on next save attempt.  */
+  int modtime;
+
+  /* the value of text->modiff at the last auto-save.  */
+  int auto_save_modified;
+
+  /* The time at which we detected a failure to auto-save,
+     Or -1 if we didn't have a failure.  */
+  int auto_save_failure_time;
+
+  /* Position in buffer at which display started
+     the last time this buffer was displayed.  */
+  int last_window_start;
+
+  /* Everything from here down must be a Lisp_Object */
+
+#define MARKED_SLOT(x) Lisp_Object x
+#include "bufslots.h"
+#undef MARKED_SLOT
+};
+
+DECLARE_LRECORD (buffer, struct buffer);
+#define XBUFFER(x) XRECORD (x, buffer, struct buffer)
+#define XSETBUFFER(x, p) XSETRECORD (x, p, buffer)
+#define BUFFERP(x) RECORDP (x, buffer)
+#define CHECK_BUFFER(x) CHECK_RECORD (x, buffer)
+#define CONCHECK_BUFFER(x) CONCHECK_RECORD (x, buffer)
+
+#define BUFFER_LIVE_P(b) (!NILP ((b)->name))
+
+#define CHECK_LIVE_BUFFER(x) do {			\
+  CHECK_BUFFER (x);					\
+  if (!BUFFER_LIVE_P (XBUFFER (x)))			\
+    dead_wrong_type_argument (Qbuffer_live_p, (x));	\
+} while (0)
+
+#define CONCHECK_LIVE_BUFFER(x) do {			\
+  CONCHECK_BUFFER (x);					\
+  if (!BUFFER_LIVE_P (XBUFFER (x)))			\
+    x = wrong_type_argument (Qbuffer_live_p, (x));	\
+} while (0)
+
+
+#define BUFFER_BASE_BUFFER(b) ((b)->base_buffer ? (b)->base_buffer : (b))
+
+/* Map over buffers sharing the same text as MPS_BUF.  MPS_BUFVAR is a
+   variable that gets the buffer values (beginning with the base
+   buffer, then the children), and MPS_BUFCONS should be a temporary
+   Lisp_Object variable.  */
+#define MAP_INDIRECT_BUFFERS(mps_buf, mps_bufvar, mps_bufcons)			\
+for (mps_bufcons = Qunbound,							\
+     mps_bufvar = BUFFER_BASE_BUFFER (mps_buf);					\
+     UNBOUNDP (mps_bufcons) ?							\
+	(mps_bufcons = mps_bufvar->indirect_children,				\
+	1)									\
+       : (!NILP (mps_bufcons)							\
+	  && (mps_bufvar = XBUFFER (XCAR (mps_bufcons)), 1)			\
+	  && (mps_bufcons = XCDR (mps_bufcons), 1));				\
+     )
+
+
+
+/************************************************************************/
+/*									*/
+/*		   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) BUFBYTE_FIRST_BYTE_P (* (unsigned char *) ptr)
+#else
+# define VALID_CHARPTR_P(ptr) 1
+#endif
+
+#ifdef ERROR_CHECK_BUFPOS
+# 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_CHARBYTIND(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_BUFPOS
+#define INC_CHARPTR(ptr) do {		\
+  ASSERT_VALID_CHARPTR (ptr);		\
+  REAL_INC_CHARPTR (ptr);		\
+} while (0)
+
+#define INC_CHARBYTIND(ptr,pos) do {		\
+  ASSERT_VALID_CHARPTR (ptr);		\
+  REAL_INC_CHARBYTIND (ptr,pos);		\
+} while (0)
+
+#define DEC_CHARPTR(ptr) do {			\
+  CONST Bufbyte *dc_ptr1 = (ptr);		\
+  CONST Bufbyte *dc_ptr2 = dc_ptr1;		\
+  REAL_DEC_CHARPTR (dc_ptr2);			\
+  assert (dc_ptr1 - dc_ptr2 ==			\
+	  REP_BYTES_BY_FIRST_BYTE (*dc_ptr2));	\
+  (ptr) = dc_ptr2;				\
+} while (0)
+
+#else /* ! ERROR_CHECK_BUFPOS */
+#define INC_CHARBYTIND(ptr,pos) REAL_INC_CHARBYTIND (ptr,pos)
+#define INC_CHARPTR(ptr) REAL_INC_CHARPTR (ptr)
+#define DEC_CHARPTR(ptr) REAL_DEC_CHARPTR (ptr)
+#endif /* ! ERROR_CHECK_BUFPOS */
+
+#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 {	\
+  Bufbyte *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 CONST Bufbyte *charptr_n_addr (CONST Bufbyte *ptr, Charcount offset);
+INLINE CONST Bufbyte *
+charptr_n_addr (CONST Bufbyte *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] = (Bufbyte) (x), 1)
+#define simple_charptr_copy_char(ptr, ptr2)	((ptr2)[0] = *(ptr), 1)
+
+#ifdef MULE
+
+Emchar non_ascii_charptr_emchar (CONST Bufbyte *ptr);
+Bytecount non_ascii_set_charptr_emchar (Bufbyte *ptr, Emchar c);
+Bytecount non_ascii_charptr_copy_char (CONST Bufbyte *ptr, Bufbyte *ptr2);
+
+INLINE Emchar charptr_emchar (CONST Bufbyte *ptr);
+INLINE Emchar
+charptr_emchar (CONST Bufbyte *ptr)
+{
+  return BYTE_ASCII_P (*ptr) ?
+    simple_charptr_emchar (ptr) :
+    non_ascii_charptr_emchar (ptr);
+}
+
+INLINE Bytecount set_charptr_emchar (Bufbyte *ptr, Emchar x);
+INLINE Bytecount
+set_charptr_emchar (Bufbyte *ptr, Emchar x)
+{
+  return !CHAR_MULTIBYTE_P (x) ?
+    simple_set_charptr_emchar (ptr, x) :
+    non_ascii_set_charptr_emchar (ptr, x);
+}
+
+INLINE Bytecount charptr_copy_char (CONST Bufbyte *ptr, Bufbyte *ptr2);
+INLINE Bytecount
+charptr_copy_char (CONST Bufbyte *ptr, Bufbyte *ptr2)
+{
+  return BYTE_ASCII_P (*ptr) ?
+    simple_charptr_copy_char (ptr, ptr2) :
+    non_ascii_charptr_copy_char (ptr, ptr2);
+}
+
+#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 int valid_char_p (Emchar ch);
+INLINE int
+valid_char_p (Emchar ch)
+{
+  return ((unsigned int) (ch) <= 0xff) || non_ascii_valid_char_p (ch);
+}
+
+#else /* not MULE */
+
+#define valid_char_p(ch) ((unsigned int) (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))
+
+#ifdef ERROR_CHECK_TYPECHECK
+
+INLINE Emchar XCHAR_OR_CHAR_INT (Lisp_Object obj);
+INLINE Emchar
+XCHAR_OR_CHAR_INT (Lisp_Object obj)
+{
+  assert (CHAR_OR_CHAR_INTP (obj));
+  return CHARP (obj) ? XCHAR (obj) : XINT (obj);
+}
+
+#else
+
+#define XCHAR_OR_CHAR_INT(obj) (CHARP (obj) ? XCHAR (obj) : XINT (obj))
+
+#endif
+
+#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		*/
+/*----------------------------------------------------------------------*/
+
+/* We put them here because some stuff below wants them before the
+   place where we would normally put them. */
+
+/* None of these are lvalues.  Use the settor macros below to change
+   the positions. */
+
+/* Beginning of buffer.  */
+#define BI_BUF_BEG(buf) ((Bytind) 1)
+#define BUF_BEG(buf) ((Bufpos) 1)
+
+/* Beginning of accessible range of buffer.  */
+#define BI_BUF_BEGV(buf) ((buf)->begv + 0)
+#define BUF_BEGV(buf) ((buf)->bufbegv + 0)
+
+/* End of accessible range of buffer.  */
+#define BI_BUF_ZV(buf) ((buf)->zv + 0)
+#define BUF_ZV(buf) ((buf)->bufzv + 0)
+
+/* End of buffer.  */
+#define BI_BUF_Z(buf) ((buf)->text->z + 0)
+#define BUF_Z(buf) ((buf)->text->bufz + 0)
+
+/* Point. */
+#define BI_BUF_PT(buf) ((buf)->pt + 0)
+#define BUF_PT(buf) ((buf)->bufpt + 0)
+
+/*----------------------------------------------------------------------*/
+/*		Converting between positions and addresses		*/
+/*----------------------------------------------------------------------*/
+
+/* Convert the address of a byte in the buffer into a position.  */
+INLINE Bytind BI_BUF_PTR_BYTE_POS (struct buffer *buf, Bufbyte *ptr);
+INLINE Bytind
+BI_BUF_PTR_BYTE_POS (struct buffer *buf, Bufbyte *ptr)
+{
+  return (ptr - buf->text->beg + 1
+	  - ((ptr - buf->text->beg + 1) > buf->text->gpt
+	     ? buf->text->gap_size : 0));
+}
+
+#define BUF_PTR_BYTE_POS(buf, ptr) \
+  bytind_to_bufpos (buf, BI_BUF_PTR_BYTE_POS (buf, ptr))
+
+/* Address of byte at position POS in buffer. */
+INLINE Bufbyte * BI_BUF_BYTE_ADDRESS (struct buffer *buf, Bytind pos);
+INLINE Bufbyte *
+BI_BUF_BYTE_ADDRESS (struct buffer *buf, Bytind pos)
+{
+  return (buf->text->beg +
+	  ((pos >= buf->text->gpt ? (pos + buf->text->gap_size) : pos)
+	   - 1));
+}
+
+#define BUF_BYTE_ADDRESS(buf, pos) \
+  BI_BUF_BYTE_ADDRESS (buf, bufpos_to_bytind (buf, pos))
+
+/* Address of byte before position POS in buffer. */
+INLINE Bufbyte * BI_BUF_BYTE_ADDRESS_BEFORE (struct buffer *buf, Bytind pos);
+INLINE Bufbyte *
+BI_BUF_BYTE_ADDRESS_BEFORE (struct buffer *buf, Bytind pos)
+{
+  return (buf->text->beg +
+	  ((pos > buf->text->gpt ? (pos + buf->text->gap_size) : pos)
+	   - 2));
+}
+
+#define BUF_BYTE_ADDRESS_BEFORE(buf, pos) \
+  BI_BUF_BYTE_ADDRESS_BEFORE (buf, bufpos_to_bytind (buf, pos))
+
+/*----------------------------------------------------------------------*/
+/*	    Converting between byte indices and memory indices		*/
+/*----------------------------------------------------------------------*/
+
+INLINE int valid_memind_p (struct buffer *buf, Memind x);
+INLINE int
+valid_memind_p (struct buffer *buf, Memind x)
+{
+  return ((x >= 1 && x <= (Memind) buf->text->gpt) ||
+	  (x  > (Memind) (buf->text->gpt + buf->text->gap_size) &&
+	   x <= (Memind) (buf->text->z   + buf->text->gap_size)));
+}
+
+INLINE Memind bytind_to_memind (struct buffer *buf, Bytind x);
+INLINE Memind
+bytind_to_memind (struct buffer *buf, Bytind x)
+{
+  return (Memind) ((x > buf->text->gpt) ? (x + buf->text->gap_size) : x);
+}
+
+
+INLINE Bytind memind_to_bytind (struct buffer *buf, Memind x);
+INLINE Bytind
+memind_to_bytind (struct buffer *buf, Memind x)
+{
+#ifdef ERROR_CHECK_BUFPOS
+  assert (valid_memind_p (buf, x));
+#endif
+  return (Bytind) ((x > (Memind) buf->text->gpt) ?
+		   x - buf->text->gap_size :
+		   x);
+}
+
+#define memind_to_bufpos(buf, x) \
+  bytind_to_bufpos (buf, memind_to_bytind (buf, x))
+#define bufpos_to_memind(buf, x) \
+  bytind_to_memind (buf, bufpos_to_bytind (buf, x))
+
+/* These macros generalize many standard buffer-position functions to
+   either a buffer or a string. */
+
+/* Converting between Meminds and Bytinds, for a buffer-or-string.
+   For strings, this is a no-op.  For buffers, this resolves
+   to the standard memind<->bytind converters. */
+
+#define buffer_or_string_bytind_to_memind(obj, ind) \
+  (BUFFERP (obj) ? bytind_to_memind (XBUFFER (obj), ind) : (Memind) ind)
+
+#define buffer_or_string_memind_to_bytind(obj, ind) \
+  (BUFFERP (obj) ? memind_to_bytind (XBUFFER (obj), ind) : (Bytind) ind)
+
+/* Converting between Bufpos's and Bytinds, for a buffer-or-string.
+   For strings, this maps to the bytecount<->charcount converters. */
+
+#define buffer_or_string_bufpos_to_bytind(obj, pos)		\
+  (BUFFERP (obj) ? bufpos_to_bytind (XBUFFER (obj), pos) :	\
+   (Bytind) charcount_to_bytecount (XSTRING_DATA (obj), pos))
+
+#define buffer_or_string_bytind_to_bufpos(obj, ind)		\
+  (BUFFERP (obj) ? bytind_to_bufpos (XBUFFER (obj), ind) :	\
+   (Bufpos) bytecount_to_charcount (XSTRING_DATA (obj), ind))
+
+/* Similar for Bufpos's and Meminds. */
+
+#define buffer_or_string_bufpos_to_memind(obj, pos)		\
+  (BUFFERP (obj) ? bufpos_to_memind (XBUFFER (obj), pos) :	\
+   (Memind) charcount_to_bytecount (XSTRING_DATA (obj), pos))
+
+#define buffer_or_string_memind_to_bufpos(obj, ind)		\
+  (BUFFERP (obj) ? memind_to_bufpos (XBUFFER (obj), ind) :	\
+   (Bufpos) bytecount_to_charcount (XSTRING_DATA (obj), ind))
+
+/************************************************************************/
+/*                                                                      */
+/*                    working with buffer-level data                    */
+/*                                                                      */
+/************************************************************************/
+
+/*
+
+   (A) Working with byte indices:
+   ------------------------------
+
+   VALID_BYTIND_P(buf, bi):
+	Given a byte index, does it point to the beginning of a character?
+
+   ASSERT_VALID_BYTIND_UNSAFE(buf, bi):
+	If error-checking is enabled, assert that the given byte index
+	is within range and points to the beginning of a character
+	or to the end of the buffer.  Otherwise, do nothing.
+
+   ASSERT_VALID_BYTIND_BACKWARD_UNSAFE(buf, bi):
+	If error-checking is enabled, assert that the given byte index
+	is within range and satisfies ASSERT_VALID_BYTIND() and also
+        does not refer to the beginning of the buffer. (i.e. movement
+	backwards is OK.) Otherwise, do nothing.
+
+   ASSERT_VALID_BYTIND_FORWARD_UNSAFE(buf, bi):
+	If error-checking is enabled, assert that the given byte index
+	is within range and satisfies ASSERT_VALID_BYTIND() and also
+        does not refer to the end of the buffer. (i.e. movement
+	forwards is OK.) Otherwise, do nothing.
+
+   VALIDATE_BYTIND_BACKWARD(buf, bi):
+	Make sure that the given byte index 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"
+	byte index.
+
+   VALIDATE_BYTIND_FORWARD(buf, bi):
+	Make sure that the given byte index 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" byte index.
+
+   INC_BYTIND(buf, bi):
+	Given a byte index (assumed to point at the beginning of a
+	character), modify that value so it points to the beginning
+	of the next character.
+
+   DEC_BYTIND(buf, bi):
+	Given a byte index (assumed to point at the beginning of a
+	character), modify that value so it points to the beginning
+	of the previous character.  Unlike for DEC_CHARPTR(), we can
+	do all the assert()s because there are sentinels at the
+	beginning of the gap and the end of the buffer.
+
+   BYTIND_INVALID:
+	A constant representing an invalid Bytind.  Valid Bytinds
+	can never have this value.
+
+
+   (B) Converting between Bufpos's and Bytinds:
+   --------------------------------------------
+
+    bufpos_to_bytind(buf, bu):
+	Given a Bufpos, return the equivalent Bytind.
+
+    bytind_to_bufpos(buf, bi):
+	Given a Bytind, return the equivalent Bufpos.
+
+    make_bufpos(buf, bi):
+	Given a Bytind, return the equivalent Bufpos as a Lisp Object.
+ */
+
+
+/*----------------------------------------------------------------------*/
+/*			 working with byte indices			*/
+/*----------------------------------------------------------------------*/
+
+#ifdef MULE
+# define VALID_BYTIND_P(buf, x) \
+  BUFBYTE_FIRST_BYTE_P (*BI_BUF_BYTE_ADDRESS (buf, x))
+#else
+# define VALID_BYTIND_P(buf, x) 1
+#endif
+
+#ifdef ERROR_CHECK_BUFPOS
+
+# define ASSERT_VALID_BYTIND_UNSAFE(buf, x) do {		\
+  assert (BUFFER_LIVE_P (buf));					\
+  assert ((x) >= BI_BUF_BEG (buf) && x <= BI_BUF_Z (buf));	\
+  assert (VALID_BYTIND_P (buf, x));				\
+} while (0)
+# define ASSERT_VALID_BYTIND_BACKWARD_UNSAFE(buf, x) do {	\
+  assert (BUFFER_LIVE_P (buf));					\
+  assert ((x) > BI_BUF_BEG (buf) && x <= BI_BUF_Z (buf));	\
+  assert (VALID_BYTIND_P (buf, x));				\
+} while (0)
+# define ASSERT_VALID_BYTIND_FORWARD_UNSAFE(buf, x) do {	\
+  assert (BUFFER_LIVE_P (buf));					\
+  assert ((x) >= BI_BUF_BEG (buf) && x < BI_BUF_Z (buf));	\
+  assert (VALID_BYTIND_P (buf, x));				\
+} while (0)
+
+#else /* not ERROR_CHECK_BUFPOS */
+# define ASSERT_VALID_BYTIND_UNSAFE(buf, x)
+# define ASSERT_VALID_BYTIND_BACKWARD_UNSAFE(buf, x)
+# define ASSERT_VALID_BYTIND_FORWARD_UNSAFE(buf, x)
+
+#endif /* not ERROR_CHECK_BUFPOS */
+
+/* Note that, although the Mule version will work fine for non-Mule
+   as well (it should reduce down to nothing), we provide a separate
+   version to avoid compilation warnings and possible non-optimal
+   results with stupid compilers. */
+
+#ifdef MULE
+# define VALIDATE_BYTIND_BACKWARD(buf, x) do {		\
+  Bufbyte *VBB_ptr = BI_BUF_BYTE_ADDRESS (buf, x);	\
+  while (!BUFBYTE_FIRST_BYTE_P (*VBB_ptr))		\
+    VBB_ptr--, (x)--;					\
+} while (0)
+#else
+# define VALIDATE_BYTIND_BACKWARD(buf, x)
+#endif
+
+/* Note that, although the Mule version will work fine for non-Mule
+   as well (it should reduce down to nothing), we provide a separate
+   version to avoid compilation warnings and possible non-optimal
+   results with stupid compilers. */
+
+#ifdef MULE
+# define VALIDATE_BYTIND_FORWARD(buf, x) do {		\
+  Bufbyte *VBF_ptr = BI_BUF_BYTE_ADDRESS (buf, x);	\
+  while (!BUFBYTE_FIRST_BYTE_P (*VBF_ptr))		\
+    VBF_ptr++, (x)++;					\
+} while (0)
+#else
+# define VALIDATE_BYTIND_FORWARD(buf, x)
+#endif
+
+/* Note that in the simplest case (no MULE, no ERROR_CHECK_BUFPOS),
+   this crap reduces down to simply (x)++. */
+
+#define INC_BYTIND(buf, x) do				\
+{							\
+  ASSERT_VALID_BYTIND_FORWARD_UNSAFE (buf, x);		\
+  /* Note that we do the increment first to		\
+     make sure that the pointer in			\
+     VALIDATE_BYTIND_FORWARD() ends up on		\
+     the correct side of the gap */			\
+  (x)++;						\
+  VALIDATE_BYTIND_FORWARD (buf, x);			\
+} while (0)
+
+/* Note that in the simplest case (no MULE, no ERROR_CHECK_BUFPOS),
+   this crap reduces down to simply (x)--. */
+
+#define DEC_BYTIND(buf, x) do				\
+{							\
+  ASSERT_VALID_BYTIND_BACKWARD_UNSAFE (buf, x);		\
+  /* Note that we do the decrement first to		\
+     make sure that the pointer in			\
+     VALIDATE_BYTIND_BACKWARD() ends up on		\
+     the correct side of the gap */			\
+  (x)--;						\
+  VALIDATE_BYTIND_BACKWARD (buf, x);			\
+} while (0)
+
+INLINE Bytind prev_bytind (struct buffer *buf, Bytind x);
+INLINE Bytind
+prev_bytind (struct buffer *buf, Bytind x)
+{
+  DEC_BYTIND (buf, x);
+  return x;
+}
+
+INLINE Bytind next_bytind (struct buffer *buf, Bytind x);
+INLINE Bytind
+next_bytind (struct buffer *buf, Bytind x)
+{
+  INC_BYTIND (buf, x);
+  return x;
+}
+
+#define BYTIND_INVALID ((Bytind) -1)
+
+/*----------------------------------------------------------------------*/
+/*	   Converting between buffer positions and byte indices		*/
+/*----------------------------------------------------------------------*/
+
+#ifdef MULE
+
+Bytind bufpos_to_bytind_func (struct buffer *buf, Bufpos x);
+Bufpos bytind_to_bufpos_func (struct buffer *buf, Bytind 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 Bufpos and
+   Bytind 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.
+   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 bufpos/bytind 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.
+
+   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.
+   */
+
+extern short three_to_one_table[];
+
+INLINE int real_bufpos_to_bytind (struct buffer *buf, Bufpos x);
+INLINE int
+real_bufpos_to_bytind (struct buffer *buf, Bufpos 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) +
+	    (buf->text->mule_three_p ? (x - buf->text->mule_bufmin) : 0));
+  else
+    return bufpos_to_bytind_func (buf, x);
+}
+
+INLINE int real_bytind_to_bufpos (struct buffer *buf, Bytind x);
+INLINE int
+real_bytind_to_bufpos (struct buffer *buf, Bytind x)
+{
+  if (x >= buf->text->mule_bytmin && x <= buf->text->mule_bytmax)
+    return (buf->text->mule_bufmin +
+	    ((buf->text->mule_three_p
+	      ? three_to_one_table[x - buf->text->mule_bytmin]
+	      : (x - buf->text->mule_bytmin) >> buf->text->mule_shifter)));
+  else
+    return bytind_to_bufpos_func (buf, x);
+}
+
+#else /* not MULE */
+
+# define real_bufpos_to_bytind(buf, x)	((Bytind) x)
+# define real_bytind_to_bufpos(buf, x)	((Bufpos) x)
+
+#endif /* not MULE */
+
+#ifdef ERROR_CHECK_BUFPOS
+
+Bytind bufpos_to_bytind (struct buffer *buf, Bufpos x);
+Bufpos bytind_to_bufpos (struct buffer *buf, Bytind x);
+
+#else /* not ERROR_CHECK_BUFPOS */
+
+#define bufpos_to_bytind real_bufpos_to_bytind
+#define bytind_to_bufpos real_bytind_to_bufpos
+
+#endif /* not ERROR_CHECK_BUFPOS */
+
+#define make_bufpos(buf, ind) make_int (bytind_to_bufpos (buf, ind))
+
+/*----------------------------------------------------------------------*/
+/*         Converting between buffer bytes and Emacs characters         */
+/*----------------------------------------------------------------------*/
+
+/* The character at position POS in buffer. */
+#define BI_BUF_FETCH_CHAR(buf, pos) \
+  charptr_emchar (BI_BUF_BYTE_ADDRESS (buf, pos))
+#define BUF_FETCH_CHAR(buf, pos) \
+  BI_BUF_FETCH_CHAR (buf, bufpos_to_bytind (buf, pos))
+
+/* The character at position POS in buffer, as a string.  This is
+   equivalent to set_charptr_emchar (str, BUF_FETCH_CHAR (buf, pos))
+   but is faster for Mule. */
+
+# define BI_BUF_CHARPTR_COPY_CHAR(buf, pos, str) \
+  charptr_copy_char (BI_BUF_BYTE_ADDRESS (buf, pos), str)
+#define BUF_CHARPTR_COPY_CHAR(buf, pos, str) \
+  BI_BUF_CHARPTR_COPY_CHAR (buf, bufpos_to_bytind (buf, pos), str)
+
+
+
+
+/************************************************************************/
+/*									*/
+/*		    working with externally-formatted data		*/
+/*									*/
+/************************************************************************/
+
+/* Sometimes strings need to be converted into one or another
+   external format, for passing to a library function. (Note
+   that we encapsulate and automatically convert the arguments
+   of some functions, but not others.) At times this conversion
+   also has to go the other way -- i.e. when we get external-
+   format strings back from a library function.
+*/
+
+#ifdef FILE_CODING
+
+/* WARNING: These use a static buffer.  This can lead to disaster if
+   these functions are not used *very* carefully.  Under normal
+   circumstances, do not call these functions; call the front ends
+   below. */
+
+Extbyte *convert_to_external_format (CONST Bufbyte *ptr,
+				     Bytecount len,
+				     Extcount *len_out,
+				     enum external_data_format fmt);
+Bufbyte *convert_from_external_format (CONST Extbyte *ptr,
+				       Extcount len,
+				       Bytecount *len_out,
+				       enum external_data_format fmt);
+
+#else /* ! MULE */
+
+#define convert_to_external_format(ptr, len, len_out, fmt) \
+     (*(len_out) = (int) (len), (Extbyte *) (ptr))
+#define convert_from_external_format(ptr, len, len_out, fmt) \
+     (*(len_out) = (Bytecount) (len), (Bufbyte *) (ptr))
+
+#endif /* ! MULE */
+
+/* In all of the following macros we use the following general principles:
+
+   -- Functions that work with charptr's accept two sorts of charptr's:
+
+      a) Pointers to memory with a length specified.  The pointer will be
+         fundamentally of type `unsigned char *' (although labelled
+	 as `Bufbyte *' for internal-format data and `Extbyte *' for
+	 external-format data) and the length will be fundamentally of
+	 type `int' (although labelled as `Bytecount' for internal-format
+	 data and `Extcount' for external-format data).  The length is
+	 always a count in bytes.
+      b) Zero-terminated pointers; no length specified.  The pointer
+         is of type `char *', whether the data pointed to is internal-format
+	 or external-format.  These sorts of pointers are available for
+	 convenience in working with C library functions and literal
+	 strings.  In general you should use these sorts of pointers only
+	 to interface to library routines and not for general manipulation,
+	 as you are liable to lose embedded nulls and such.  This could
+	 be a big problem for routines that want Unicode-formatted data,
+	 which is likely to have lots of embedded nulls in it.
+	 (In the real world, though, external Unicode data will be UTF-8,
+	 which will not have embedded nulls and is ASCII-compatible - martin)
+
+   -- Functions that work with Lisp strings accept strings as Lisp Objects
+      (as opposed to the `struct Lisp_String *' for some of the other
+      string accessors).  This is for convenience in working with the
+      functions, as otherwise you will almost always have to call
+      XSTRING() on the object.
+
+   -- Functions that work with charptr's are not guaranteed to copy
+      their data into alloca()ed space.  Functions that work with
+      Lisp strings are, however.  The reason is that Lisp strings can
+      be relocated any time a GC happens, and it could happen at some
+      rather unexpected times.  The internal-external conversion is
+      rarely done in time-critical functions, and so the slight
+      extra time required for alloca() and copy is well-worth the
+      safety of knowing your string data won't be relocated out from
+      under you.
+      */
+
+
+/* Maybe convert charptr's data into ext-format and store the result in
+   alloca()'ed space.
+
+   You may wonder why this is written in this fashion and not as a
+   function call.  With a little trickery it could certainly be
+   written this way, but it won't work because of those DAMN GCC WANKERS
+   who couldn't be bothered to handle alloca() properly on the x86
+   architecture. (If you put a call to alloca() in the argument to
+   a function call, the stack space gets allocated right in the
+   middle of the arguments to the function call and you are unbelievably
+   hosed.) */
+
+#ifdef MULE
+
+#define GET_CHARPTR_EXT_DATA_ALLOCA(ptr, len, fmt, ptr_out, len_out) do	\
+{									\
+  Bytecount gceda_len_in = (Bytecount) (len);				\
+  Extcount  gceda_len_out;						\
+  CONST Bufbyte *gceda_ptr_in = (ptr);					\
+  Extbyte *gceda_ptr_out =						\
+    convert_to_external_format (gceda_ptr_in, gceda_len_in,		\
+				&gceda_len_out, fmt);			\
+  /* If the new string is identical to the old (will be the case most	\
+     of the time), just return the same string back.  This saves	\
+     on alloca()ing, which can be useful on C alloca() machines and	\
+     on stack-space-challenged environments. */				\
+									\
+  if (gceda_len_in == gceda_len_out &&					\
+      !memcmp (gceda_ptr_in, gceda_ptr_out, gceda_len_out))		\
+    {									\
+      (ptr_out) = (Extbyte *) gceda_ptr_in;				\
+    }									\
+  else									\
+    {									\
+      (ptr_out) = (Extbyte *) alloca (1 + gceda_len_out);		\
+      memcpy ((void *) ptr_out, gceda_ptr_out, 1 + gceda_len_out);	\
+    }									\
+  (len_out) = gceda_len_out;						\
+} while (0)
+
+#else /* ! MULE */
+
+#define GET_CHARPTR_EXT_DATA_ALLOCA(ptr, len, fmt, ptr_out, len_out) do	\
+{					\
+  (ptr_out) = (Extbyte *) (ptr);	\
+  (len_out) = (Extcount) (len);		\
+} while (0)
+
+#endif /* ! MULE */
+
+#define GET_C_CHARPTR_EXT_DATA_ALLOCA(ptr, fmt, ptr_out) do	\
+{								\
+  Extcount gcceda_ignored_len;					\
+  CONST Bufbyte *gcceda_ptr_in = (CONST Bufbyte *) (ptr);	\
+  Extbyte *gcceda_ptr_out;					\
+								\
+  GET_CHARPTR_EXT_DATA_ALLOCA (gcceda_ptr_in,			\
+			       strlen ((char *) gcceda_ptr_in),	\
+			       fmt,				\
+			       gcceda_ptr_out,			\
+			       gcceda_ignored_len);		\
+  (ptr_out) = (char *) gcceda_ptr_out;				\
+} while (0)
+
+#define GET_C_CHARPTR_EXT_BINARY_DATA_ALLOCA(ptr, ptr_out) \
+  GET_C_CHARPTR_EXT_DATA_ALLOCA (ptr, FORMAT_BINARY, ptr_out)
+#define GET_CHARPTR_EXT_BINARY_DATA_ALLOCA(ptr, len, ptr_out, len_out) \
+  GET_CHARPTR_EXT_DATA_ALLOCA (ptr, len, FORMAT_BINARY, ptr_out, len_out)
+
+#define GET_C_CHARPTR_EXT_FILENAME_DATA_ALLOCA(ptr, ptr_out) \
+  GET_C_CHARPTR_EXT_DATA_ALLOCA (ptr, FORMAT_FILENAME, ptr_out)
+#define GET_CHARPTR_EXT_FILENAME_DATA_ALLOCA(ptr, len, ptr_out, len_out) \
+  GET_CHARPTR_EXT_DATA_ALLOCA (ptr, len, FORMAT_FILENAME, ptr_out, len_out)
+
+#define GET_C_CHARPTR_EXT_CTEXT_DATA_ALLOCA(ptr, ptr_out) \
+  GET_C_CHARPTR_EXT_DATA_ALLOCA (ptr, FORMAT_CTEXT, ptr_out)
+#define GET_CHARPTR_EXT_CTEXT_DATA_ALLOCA(ptr, len, ptr_out, len_out) \
+  GET_CHARPTR_EXT_DATA_ALLOCA (ptr, len, FORMAT_CTEXT, ptr_out, len_out)
+
+/* Maybe convert external charptr's data into internal format and store
+   the result in alloca()'ed space.
+
+   You may wonder why this is written in this fashion and not as a
+   function call.  With a little trickery it could certainly be
+   written this way, but it won't work because of those DAMN GCC WANKERS
+   who couldn't be bothered to handle alloca() properly on the x86
+   architecture. (If you put a call to alloca() in the argument to
+   a function call, the stack space gets allocated right in the
+   middle of the arguments to the function call and you are unbelievably
+   hosed.) */
+
+#ifdef MULE
+
+#define GET_CHARPTR_INT_DATA_ALLOCA(ptr, len, fmt, ptr_out, len_out) do	\
+{									\
+  Extcount gcida_len_in = (Extcount) (len);				\
+  Bytecount gcida_len_out;						\
+  CONST Extbyte *gcida_ptr_in = (ptr);					\
+  Bufbyte *gcida_ptr_out =						\
+    convert_from_external_format (gcida_ptr_in, gcida_len_in,		\
+				  &gcida_len_out, fmt);			\
+  /* If the new string is identical to the old (will be the case most	\
+     of the time), just return the same string back.  This saves	\
+     on alloca()ing, which can be useful on C alloca() machines and	\
+     on stack-space-challenged environments. */				\
+									\
+  if (gcida_len_in == gcida_len_out &&					\
+      !memcmp (gcida_ptr_in, gcida_ptr_out, gcida_len_out))		\
+    {									\
+      (ptr_out) = (Bufbyte *) gcida_ptr_in;				\
+    }									\
+  else									\
+    {									\
+      (ptr_out) = (Extbyte *) alloca (1 + gcida_len_out);		\
+      memcpy ((void *) ptr_out, gcida_ptr_out, 1 + gcida_len_out);	\
+    }									\
+  (len_out) = gcida_len_out;						\
+} while (0)
+
+#else /* ! MULE */
+
+#define GET_CHARPTR_INT_DATA_ALLOCA(ptr, len, fmt, ptr_out, len_out) do \
+{					\
+  (ptr_out) = (Bufbyte *) (ptr);	\
+  (len_out) = (Bytecount) (len);	\
+} while (0)
+
+#endif /* ! MULE */
+
+#define GET_C_CHARPTR_INT_DATA_ALLOCA(ptr, fmt, ptr_out) do	\
+{								\
+  Bytecount gccida_ignored_len;					\
+  CONST Extbyte *gccida_ptr_in = (CONST Extbyte *) (ptr);	\
+  Bufbyte *gccida_ptr_out;					\
+								\
+  GET_CHARPTR_INT_DATA_ALLOCA (gccida_ptr_in,			\
+			       strlen ((char *) gccida_ptr_in),	\
+			       fmt,				\
+			       gccida_ptr_out,			\
+			       gccida_ignored_len);		\
+  (ptr_out) = gccida_ptr_out;					\
+} while (0)
+
+#define GET_C_CHARPTR_INT_BINARY_DATA_ALLOCA(ptr, ptr_out)	\
+  GET_C_CHARPTR_INT_DATA_ALLOCA (ptr, FORMAT_BINARY, ptr_out)
+#define GET_CHARPTR_INT_BINARY_DATA_ALLOCA(ptr, len, ptr_out, len_out) \
+  GET_CHARPTR_INT_DATA_ALLOCA (ptr, len, FORMAT_BINARY, ptr_out, len_out)
+
+#define GET_C_CHARPTR_INT_FILENAME_DATA_ALLOCA(ptr, ptr_out)	\
+  GET_C_CHARPTR_INT_DATA_ALLOCA (ptr, FORMAT_FILENAME, ptr_out)
+#define GET_CHARPTR_INT_FILENAME_DATA_ALLOCA(ptr, len, ptr_out, len_out) \
+  GET_CHARPTR_INT_DATA_ALLOCA (ptr, len, FORMAT_FILENAME, ptr_out, len_out)
+
+#define GET_C_CHARPTR_INT_CTEXT_DATA_ALLOCA(ptr, ptr_out)	\
+  GET_C_CHARPTR_INT_DATA_ALLOCA (ptr, FORMAT_CTEXT, ptr_out)
+#define GET_CHARPTR_INT_CTEXT_DATA_ALLOCA(ptr, len, ptr_out, len_out) \
+  GET_CHARPTR_INT_DATA_ALLOCA (ptr, len, FORMAT_CTEXT, ptr_out, len_out)
+
+
+/* Maybe convert Lisp string's data into ext-format and store the result in
+   alloca()'ed space.
+
+   You may wonder why this is written in this fashion and not as a
+   function call.  With a little trickery it could certainly be
+   written this way, but it won't work because of those DAMN GCC WANKERS
+   who couldn't be bothered to handle alloca() properly on the x86
+   architecture. (If you put a call to alloca() in the argument to
+   a function call, the stack space gets allocated right in the
+   middle of the arguments to the function call and you are unbelievably
+   hosed.) */
+
+#define GET_STRING_EXT_DATA_ALLOCA(s, fmt, ptr_out, len_out) do	\
+{								\
+  Extcount gseda_len_out;					\
+  struct Lisp_String *gseda_s = XSTRING (s);			\
+  Extbyte * gseda_ptr_out =					\
+    convert_to_external_format (string_data (gseda_s),		\
+				string_length (gseda_s),	\
+				&gseda_len_out, fmt);		\
+  (ptr_out) = (Extbyte *) alloca (1 + gseda_len_out);		\
+  memcpy ((void *) ptr_out, gseda_ptr_out, 1 + gseda_len_out);	\
+  (len_out) = gseda_len_out;					\
+} while (0)
+
+
+#define GET_C_STRING_EXT_DATA_ALLOCA(s, fmt, ptr_out) do	\
+{								\
+  Extcount gcseda_ignored_len;					\
+  Extbyte *gcseda_ptr_out;					\
+								\
+  GET_STRING_EXT_DATA_ALLOCA (s, fmt, gcseda_ptr_out,		\
+			      gcseda_ignored_len);		\
+  (ptr_out) = (char *) gcseda_ptr_out;				\
+} while (0)
+
+#define GET_STRING_BINARY_DATA_ALLOCA(s, ptr_out, len_out)	\
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_BINARY, ptr_out, len_out)
+#define GET_C_STRING_BINARY_DATA_ALLOCA(s, ptr_out)		\
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_BINARY, ptr_out)
+
+#define GET_STRING_FILENAME_DATA_ALLOCA(s, ptr_out, len_out)	\
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_FILENAME, ptr_out, len_out)
+#define GET_C_STRING_FILENAME_DATA_ALLOCA(s, ptr_out)		\
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_FILENAME, ptr_out)
+
+#define GET_STRING_OS_DATA_ALLOCA(s, ptr_out, len_out)		\
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_OS, ptr_out, len_out)
+#define GET_C_STRING_OS_DATA_ALLOCA(s, ptr_out)			\
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_OS, ptr_out)
+
+#define GET_STRING_CTEXT_DATA_ALLOCA(s, ptr_out, len_out)	\
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_CTEXT, ptr_out, len_out)
+#define GET_C_STRING_CTEXT_DATA_ALLOCA(s, ptr_out)		\
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_CTEXT, ptr_out)
+
+
+
+/************************************************************************/
+/*                                                                      */
+/*                          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              */
+/*                                                                      */
+/************************************************************************/
+
+/*----------------------------------------------------------------------*/
+/*           Settor macros for important positions in a buffer          */
+/*----------------------------------------------------------------------*/
+
+/* Set beginning of accessible range of buffer.  */
+#define SET_BOTH_BUF_BEGV(buf, val, bival)	\
+do						\
+{						\
+  (buf)->begv = (bival);			\
+  (buf)->bufbegv = (val);			\
+} while (0)
+
+/* Set end of accessible range of buffer.  */
+#define SET_BOTH_BUF_ZV(buf, val, bival)	\
+do						\
+{						\
+  (buf)->zv = (bival);				\
+  (buf)->bufzv = (val);				\
+} while (0)
+
+/* Set point. */
+/* Since BEGV and ZV are almost never set, it's reasonable to enforce
+   the restriction that the Bufpos and Bytind values must both be
+   specified.  However, point is set in lots and lots of places.  So
+   we provide the ability to specify both (for efficiency) or just
+   one. */
+#define BOTH_BUF_SET_PT(buf, val, bival) set_buffer_point (buf, val, bival)
+#define BI_BUF_SET_PT(buf, bival) \
+  BOTH_BUF_SET_PT (buf, bytind_to_bufpos (buf, bival), bival)
+#define BUF_SET_PT(buf, value) \
+  BOTH_BUF_SET_PT (buf, value, bufpos_to_bytind (buf, value))
+
+
+#if 0 /* FSFmacs */
+/* These macros exist in FSFmacs because SET_PT() in FSFmacs incorrectly
+   does too much stuff, such as moving out of invisible extents. */
+#define TEMP_SET_PT(position) (temp_set_point ((position), current_buffer))
+#define SET_BUF_PT(buf, value) ((buf)->pt = (value))
+#endif /* FSFmacs */
+
+/*----------------------------------------------------------------------*/
+/*                      Miscellaneous buffer values                     */
+/*----------------------------------------------------------------------*/
+
+/* Number of characters in buffer */
+#define BUF_SIZE(buf) (BUF_Z (buf) - BUF_BEG (buf))
+
+/* Is this buffer narrowed? */
+#define BUF_NARROWED(buf) \
+   ((BI_BUF_BEGV (buf) != BI_BUF_BEG (buf)) || \
+    (BI_BUF_ZV   (buf) != BI_BUF_Z   (buf)))
+
+/* Modification count.  */
+#define BUF_MODIFF(buf) ((buf)->text->modiff)
+
+/* Saved modification count.  */
+#define BUF_SAVE_MODIFF(buf) ((buf)->text->save_modiff)
+
+/* Face changed.  */
+#define BUF_FACECHANGE(buf) ((buf)->face_change)
+
+#define POINT_MARKER_P(marker) \
+   (XMARKER (marker)->buffer != 0 && \
+    EQ ((marker), XMARKER (marker)->buffer->point_marker))
+
+#define BUF_MARKERS(buf) ((buf)->markers)
+
+/* WARNING:
+
+   The new definitions of CEILING_OF() and FLOOR_OF() differ semantically
+   from the old ones (in FSF Emacs and XEmacs 19.11 and before).
+   Conversion is as follows:
+
+   OLD_BI_CEILING_OF(n) = NEW_BI_CEILING_OF(n) - 1
+   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.
+ */
+
+/* Properties of CEILING_OF and FLOOR_OF (also apply to BI_ variants):
+
+   1) FLOOR_OF (CEILING_OF (n)) = n
+      CEILING_OF (FLOOR_OF (n)) = n
+
+   2) CEILING_OF (n) = n if and only if n = ZV
+      FLOOR_OF (n) = n if and only if n = BEGV
+
+   3) CEILING_OF (CEILING_OF (n)) = ZV
+      FLOOR_OF (FLOOR_OF (n)) = BEGV
+
+   4) The bytes in the regions
+
+      [BYTE_ADDRESS (n), BYTE_ADDRESS_BEFORE (CEILING_OF (n))]
+
+      and
+
+      [BYTE_ADDRESS (FLOOR_OF (n)), BYTE_ADDRESS_BEFORE (n)]
+
+      are contiguous.
+   */
+
+
+/*  Return the maximum index in the buffer it is safe to scan forwards
+    past N to.  This is used to prevent buffer scans from running into
+    the gap (e.g. search.c).  All characters between N and CEILING_OF(N)
+    are located contiguous in memory.  Note that the character *at*
+    CEILING_OF(N) is not contiguous in memory. */
+#define BI_BUF_CEILING_OF(b, n)						\
+  ((n) < (b)->text->gpt && (b)->text->gpt < BI_BUF_ZV (b) ?		\
+   (b)->text->gpt : BI_BUF_ZV (b))
+#define BUF_CEILING_OF(b, n)						\
+  bytind_to_bufpos (b, BI_BUF_CEILING_OF (b, bufpos_to_bytind (b, n)))
+
+/*  Return the minimum index in the buffer it is safe to scan backwards
+    past N to.  All characters between FLOOR_OF(N) and N are located
+    contiguous in memory.  Note that the character *at* N may not be
+    contiguous in memory. */
+#define BI_BUF_FLOOR_OF(b, n)						\
+        (BI_BUF_BEGV (b) < (b)->text->gpt && (b)->text->gpt < (n) ?	\
+	 (b)->text->gpt : BI_BUF_BEGV (b))
+#define BUF_FLOOR_OF(b, n)						\
+  bytind_to_bufpos (b, BI_BUF_FLOOR_OF (b, bufpos_to_bytind (b, n)))
+
+#define BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE(b, n)			\
+  ((n) < (b)->text->gpt && (b)->text->gpt < BI_BUF_Z (b) ?		\
+   (b)->text->gpt : BI_BUF_Z (b))
+#define BUF_CEILING_OF_IGNORE_ACCESSIBLE(b, n) 				\
+  bytind_to_bufpos							\
+   (b, BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE (b, bufpos_to_bytind (b, n)))
+
+#define BI_BUF_FLOOR_OF_IGNORE_ACCESSIBLE(b, n)				\
+        (BI_BUF_BEG (b) < (b)->text->gpt && (b)->text->gpt < (n) ?	\
+	 (b)->text->gpt : BI_BUF_BEG (b))
+#define BUF_FLOOR_OF_IGNORE_ACCESSIBLE(b, n) 				\
+  bytind_to_bufpos							\
+   (b, BI_BUF_FLOOR_OF_IGNORE_ACCESSIBLE (b, bufpos_to_bytind (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.
+   The value has only one nonzero bit.
+
+   When a buffer has its own local value for a slot,
+   the bit for that slot (found in the same slot in this structure)
+   is turned on in the buffer's local_var_flags slot.
+
+   If a slot in this structure is zero, then even though there may
+   be a DEFVAR_BUFFER_LOCAL for the slot, there is no default value for it;
+   and the corresponding slot in Vbuffer_defaults is not used.  */
+
+extern struct buffer buffer_local_flags;
+
+
+/* Allocation of buffer data. */
+
+#ifdef REL_ALLOC
+
+char *r_alloc (unsigned char **, unsigned long);
+char *r_re_alloc (unsigned char **, unsigned long);
+void r_alloc_free (unsigned char **);
+
+#define BUFFER_ALLOC(data, size) \
+  ((Bufbyte *) r_alloc ((unsigned char **) &data, (size) * sizeof(Bufbyte)))
+#define BUFFER_REALLOC(data, size) \
+  ((Bufbyte *) r_re_alloc ((unsigned char **) &data, (size) * sizeof(Bufbyte)))
+#define BUFFER_FREE(data) r_alloc_free ((unsigned char **) &(data))
+#define R_ALLOC_DECLARE(var,data) r_alloc_declare (&(var), data)
+
+#else /* !REL_ALLOC */
+
+#define BUFFER_ALLOC(data,size)\
+	(data = xnew_array (Bufbyte, size))
+#define BUFFER_REALLOC(data,size)\
+	((Bufbyte *) xrealloc (data, (size) * sizeof(Bufbyte)))
+/* Avoid excess parentheses, or syntax errors may rear their heads. */
+#define BUFFER_FREE(data) xfree (data)
+#define R_ALLOC_DECLARE(var,data)
+
+#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, Bufpos pt);
+
+/* from insdel.c */
+void set_buffer_point (struct buffer *buf, Bufpos pos, Bytind bipos);
+void find_charsets_in_bufbyte_string (unsigned char *charsets,
+				      CONST Bufbyte *str,
+				      Bytecount len);
+void find_charsets_in_emchar_string (unsigned char *charsets,
+				     CONST Emchar *str,
+				     Charcount len);
+int bufbyte_string_displayed_columns (CONST Bufbyte *str, Bytecount len);
+int emchar_string_displayed_columns (CONST Emchar *str, Charcount len);
+void convert_bufbyte_string_into_emchar_dynarr (CONST Bufbyte *str,
+						Bytecount len,
+						Emchar_dynarr *dyn);
+Charcount convert_bufbyte_string_into_emchar_string (CONST Bufbyte *str,
+						     Bytecount len,
+						     Emchar *arr);
+void convert_emchar_string_into_bufbyte_dynarr (Emchar *arr, int nels,
+						Bufbyte_dynarr *dyn);
+Bufbyte *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)
+
+Bufpos get_buffer_pos_char (struct buffer *b, Lisp_Object pos,
+			    unsigned int flags);
+Bytind 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,
+			    Bufpos *from_out, Bufpos *to_out,
+			    unsigned int flags);
+void get_buffer_range_byte (struct buffer *b, Lisp_Object from, Lisp_Object to,
+			    Bytind *from_out, Bytind *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);
+Bufpos get_buffer_or_string_pos_char (Lisp_Object object, Lisp_Object pos,
+				      unsigned int flags);
+Bytind 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, Bufpos *from_out,
+				      Bufpos *to_out, unsigned int flags);
+void get_buffer_or_string_range_byte (Lisp_Object object, Lisp_Object from,
+				      Lisp_Object to, Bytind *from_out,
+				      Bytind *to_out, unsigned int flags);
+Bufpos buffer_or_string_accessible_begin_char (Lisp_Object object);
+Bufpos buffer_or_string_accessible_end_char (Lisp_Object object);
+Bytind buffer_or_string_accessible_begin_byte (Lisp_Object object);
+Bytind buffer_or_string_accessible_end_byte (Lisp_Object object);
+Bufpos buffer_or_string_absolute_begin_char (Lisp_Object object);
+Bufpos buffer_or_string_absolute_end_char (Lisp_Object object);
+Bytind buffer_or_string_absolute_begin_byte (Lisp_Object object);
+Bytind 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                              */
+/************************************************************************/
+
+/* A "trt" table is a mapping from characters to other characters,
+   typically used to convert between uppercase and lowercase.  For
+   compatibility reasons, trt tables are currently in the form of
+   a Lisp string of 256 characters, specifying the conversion for each
+   of the first 256 Emacs characters (i.e. the 256 Latin-1 characters).
+   This should be generalized at some point to support conversions for
+   all of the allowable Mule characters.
+   */
+
+/* The _1 macros are named as such because they assume that you have
+   already guaranteed that the character values are all in the range
+   0 - 255.  Bad lossage will happen otherwise. */
+
+# define MAKE_TRT_TABLE() Fmake_string (make_int (256), make_char (0))
+# define TRT_TABLE_AS_STRING(table) XSTRING_DATA (table)
+# define TRT_TABLE_CHAR_1(table, ch) \
+  string_char (XSTRING (table), (Charcount) ch)
+# define SET_TRT_TABLE_CHAR_1(table, ch1, ch2) \
+  set_string_char (XSTRING (table), (Charcount) ch1, ch2)
+
+#ifdef MULE
+# define MAKE_MIRROR_TRT_TABLE() make_opaque (256, 0)
+# define MIRROR_TRT_TABLE_AS_STRING(table) ((Bufbyte *) XOPAQUE_DATA (table))
+# define MIRROR_TRT_TABLE_CHAR_1(table, ch) \
+  ((Emchar) (MIRROR_TRT_TABLE_AS_STRING (table)[ch]))
+# define SET_MIRROR_TRT_TABLE_CHAR_1(table, ch1, ch2) \
+  (MIRROR_TRT_TABLE_AS_STRING (table)[ch1] = (Bufbyte) (ch2))
+#endif
+
+# define IN_TRT_TABLE_DOMAIN(c) (((EMACS_UINT) (c)) <= 255)
+
+#ifdef MULE
+#define MIRROR_DOWNCASE_TABLE_AS_STRING(buf) \
+  MIRROR_TRT_TABLE_AS_STRING (buf->mirror_downcase_table)
+#define MIRROR_UPCASE_TABLE_AS_STRING(buf) \
+  MIRROR_TRT_TABLE_AS_STRING (buf->mirror_upcase_table)
+#define MIRROR_CANON_TABLE_AS_STRING(buf) \
+  MIRROR_TRT_TABLE_AS_STRING (buf->mirror_case_canon_table)
+#define MIRROR_EQV_TABLE_AS_STRING(buf) \
+  MIRROR_TRT_TABLE_AS_STRING (buf->mirror_case_eqv_table)
+#else
+#define MIRROR_DOWNCASE_TABLE_AS_STRING(buf) \
+  TRT_TABLE_AS_STRING (buf->downcase_table)
+#define MIRROR_UPCASE_TABLE_AS_STRING(buf) \
+  TRT_TABLE_AS_STRING (buf->upcase_table)
+#define MIRROR_CANON_TABLE_AS_STRING(buf) \
+  TRT_TABLE_AS_STRING (buf->case_canon_table)
+#define MIRROR_EQV_TABLE_AS_STRING(buf) \
+  TRT_TABLE_AS_STRING (buf->case_eqv_table)
+#endif
+
+INLINE Emchar TRT_TABLE_OF (Lisp_Object trt, Emchar c);
+INLINE Emchar
+TRT_TABLE_OF (Lisp_Object trt, Emchar c)
+{
+  return IN_TRT_TABLE_DOMAIN (c) ? TRT_TABLE_CHAR_1 (trt, c) : c;
+}
+
+/* Macros used below. */
+#define DOWNCASE_TABLE_OF(buf, c) TRT_TABLE_OF (buf->downcase_table, c)
+#define UPCASE_TABLE_OF(buf, c) TRT_TABLE_OF (buf->upcase_table, c)
+
+/* 1 if CH is upper case.  */
+
+INLINE int UPPERCASEP (struct buffer *buf, Emchar ch);
+INLINE int
+UPPERCASEP (struct buffer *buf, Emchar ch)
+{
+  return DOWNCASE_TABLE_OF (buf, ch) != ch;
+}
+
+/* 1 if CH is lower case.  */
+
+INLINE int LOWERCASEP (struct buffer *buf, Emchar ch);
+INLINE int
+LOWERCASEP (struct buffer *buf, Emchar ch)
+{
+  return (UPCASE_TABLE_OF   (buf, ch) != ch &&
+	  DOWNCASE_TABLE_OF (buf, ch) == ch);
+}
+
+/* 1 if CH is neither upper nor lower case.  */
+
+INLINE int NOCASEP (struct buffer *buf, Emchar ch);
+INLINE int
+NOCASEP (struct buffer *buf, Emchar ch)
+{
+  return UPCASE_TABLE_OF (buf, ch) == ch;
+}
+
+/* Upcase a character, or make no change if that cannot be done.  */
+
+INLINE Emchar UPCASE (struct buffer *buf, Emchar ch);
+INLINE Emchar
+UPCASE (struct buffer *buf, Emchar ch)
+{
+  return (DOWNCASE_TABLE_OF (buf, ch) == ch) ? UPCASE_TABLE_OF (buf, ch) : ch;
+}
+
+/* Upcase a character known to be not upper case.  Unused. */
+
+#define UPCASE1(buf, ch) UPCASE_TABLE_OF (buf, ch)
+
+/* Downcase a character, or make no change if that cannot be done. */
+
+#define DOWNCASE(buf, ch) DOWNCASE_TABLE_OF (buf, ch)
+
+#endif /* _XEMACS_BUFFER_H_ */