diff src/buffer.h @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 9ee227acff29
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/buffer.h	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,1539 @@
+/* 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_
+
+/************************************************************************/
+/*                                                                      */
+/*                    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 modiff;			/* This counts buffer-modification events
+				   for this buffer.  It is incremented for
+				   each such event, and never otherwise
+				   changed.  */
+    int save_modiff;		/* Previous value of modiff, as of last
+				   time buffer visited or saved a file.  */
+
+
+    /* 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 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
+
+    /* 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 GC_BUFFERP(x) GC_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))
+extern Lisp_Object Qbuffer_live_p;
+#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_OR_STRING_P(x) (BUFFERP (x) || STRINGP (x))
+
+extern Lisp_Object Qbuffer_or_string_p;
+#define CHECK_BUFFER_OR_STRING(x)					\
+  do { if (!BUFFER_OR_STRING_P (x))					\
+	 dead_wrong_type_argument (Qbuffer_or_string_p, (x));		\
+     } while (0)
+#define CONCHECK_BUFFER_OR_STRING(x)					\
+  do { if (!BUFFER_OR_STRING_P (x))					\
+	 x = wrong_type_argument (Qbuffer_or_string_p, (x));		\
+     } while (0)
+
+#define CHECK_LIVE_BUFFER_OR_STRING(x)					\
+  do { CHECK_BUFFER_OR_STRING (x);					\
+       if (BUFFERP (x))							\
+	 CHECK_LIVE_BUFFER (x);						\
+     } while (0)
+#define CONCHECK_LIVE_BUFFER_OR_STRING(x)				\
+  do { CONCHECK_BUFFER_OR_STRING (x);					\
+       if (BUFFERP (x))							\
+	 CONCHECK_LIVE_BUFFER (x);					\
+     } while (0)
+
+
+
+/* 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 MTxx
+      variables 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.
+
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*                 working with raw internal-format data                */
+/*                                                                      */
+/************************************************************************/
+
+/* Use these 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. */
+
+/* Functions are as follows:
+
+
+   (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.
+
+   charptr_length(ptr):
+	Given a zero-terminated pointer to Emacs characters,
+	return the number of Emacs characters contained within.
+
+
+   (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:
+   -----------------------------
+
+   valid_char_p(ch):
+	Return whether the given Emchar is valid.
+
+   CHARP(ch):
+        Return whether the given Lisp_Object is a valid character.
+	This is approximately the same as saying the Lisp_Object is
+	an int whose value is a valid Emchar. (But not exactly
+	because when MULE is not defined, we allow arbitrary values
+	in all but the lowest 8 bits and mask them off, for backward
+	compatibility.)
+
+   CHECK_CHAR_COERCE_INT(ch):
+	Signal an error if CH is not a valid character as per CHARP().
+	Also canonicalize the value into a valid Emchar, as necessary.
+	(This only means anything when MULE is not defined.)
+
+   COERCE_CHAR(ch):
+	Coerce an object that is known to satisfy CHARP() into a
+	valid Emchar.
+
+   MAX_EMCHAR_LEN:
+	Maximum number of buffer bytes per Emacs character.
+
+*/
+
+
+/* ---------------------------------------------------------------------- */
+/* (A) For working with charptr's (pointers to internally-formatted text) */
+/* ---------------------------------------------------------------------- */
+
+#define VALID_CHARPTR_P(ptr) 1
+
+#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_fun(ptr) \
+  ((ptr) += REP_BYTES_BY_FIRST_BYTE (* (unsigned char *) (ptr)))
+#ifdef ERROR_CHECK_BUFPOS
+#define inc_charptr_fun(ptr) (ASSERT_VALID_CHARPTR (ptr), \
+			      real_inc_charptr_fun (ptr))
+#else
+#define inc_charptr_fun(ptr) real_inc_charptr_fun (ptr)
+#endif
+
+#define REAL_INC_CHARPTR(ptr) do		\
+{						\
+  real_inc_charptr_fun (ptr);			\
+} while (0)
+
+#define INC_CHARPTR(ptr) do			\
+{						\
+  ASSERT_VALID_CHARPTR (ptr);			\
+  REAL_INC_CHARPTR (ptr);			\
+} while (0)
+
+#define REAL_DEC_CHARPTR(ptr) do		\
+{						\
+  (ptr)--;					\
+} while (!VALID_CHARPTR_P (ptr))
+
+#ifdef ERROR_CHECK_BUFPOS
+#define DEC_CHARPTR(ptr) do			  \
+{						  \
+  CONST Bufbyte *__dcptr__ = (ptr);		  \
+  CONST Bufbyte *__dcptr2__ = __dcptr__;	  \
+  REAL_DEC_CHARPTR (__dcptr2__);		  \
+  assert (__dcptr__ - __dcptr2__ ==		  \
+	  REP_BYTES_BY_FIRST_BYTE (*__dcptr2__)); \
+  (ptr) = __dcptr2__;				  \
+} while (0)
+#else
+#define DEC_CHARPTR(ptr) REAL_DEC_CHARPTR (ptr)
+#endif
+
+#define VALIDATE_CHARPTR_BACKWARD(ptr)
+#define VALIDATE_CHARPTR_FORWARD(ptr)
+
+/* -------------------------------------------------------------- */
+/* (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);
+}
+
+INLINE Charcount charptr_length (CONST Bufbyte *ptr);
+INLINE Charcount
+charptr_length (CONST Bufbyte *ptr)
+{
+  return bytecount_to_charcount (ptr, strlen ((CONST char *) ptr));
+}
+
+
+/* -------------------------------------------------------------------- */
+/* (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)
+
+# 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)
+
+#define charptr_emchar_n(ptr, offset) \
+  charptr_emchar (charptr_n_addr (ptr, offset))
+
+
+/* ---------------------------- */
+/* (D) For working with Emchars */
+/* ---------------------------- */
+
+#define valid_char_p(ch) ((unsigned int) (ch) < 0400)
+
+#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 XREALINT (obj);
+}
+
+#else
+
+#define XCHAR_OR_CHAR_INT(obj) XREALINT (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)
+
+#define MAX_EMCHAR_LEN 1
+
+
+/*----------------------------------------------------------------------*/
+/*          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)
+{
+  if (x >= 1 && x <= (Memind) (buf)->text->gpt)
+    return 1;
+  if (x > (Memind) ((buf)->text->gpt + (buf)->text->gap_size)
+      && x <= (Memind) ((buf)->text->z + (buf)->text->gap_size))
+    return 1;
+  return 0;
+}
+
+INLINE Memind bytind_to_memind (struct buffer *buf, Bytind x);
+INLINE Memind
+bytind_to_memind (struct buffer *buf, Bytind x)
+{
+  if (x > (buf)->text->gpt)
+    return (Memind) (x + (buf)->text->gap_size);
+  else
+    return (Memind) (x);
+}
+
+#ifdef ERROR_CHECK_BUFPOS
+
+INLINE Bytind memind_to_bytind (struct buffer *buf, Memind x);
+INLINE Bytind
+memind_to_bytind (struct buffer *buf, Memind x)
+{
+  assert (valid_memind_p (buf, x));
+  if (x > (Memind) (buf)->text->gpt)
+    return (Bytind) (x - (buf)->text->gap_size);
+  else
+    return (Bytind) (x);
+}
+
+#else
+
+INLINE Bytind memind_to_bytind (struct buffer *buf, Memind x);
+INLINE Bytind
+memind_to_bytind (struct buffer *buf, Memind x)
+{
+  if (x > (Memind) (buf)->text->gpt)
+    return (Bytind) (x - (buf)->text->gap_size);
+  else
+    return (Bytind) (x);
+}
+
+#endif
+
+#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 (string_data (XSTRING (obj)), pos))
+
+#define buffer_or_string_bytind_to_bufpos(obj, ind) 			\
+  (BUFFERP (obj) ? bytind_to_bufpos (XBUFFER (obj), ind) :		\
+   (Bufpos) bytecount_to_charcount (string_data (XSTRING (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 (string_data (XSTRING (obj)), pos))
+
+#define buffer_or_string_memind_to_bufpos(obj, ind) 			\
+  (BUFFERP (obj) ? memind_to_bufpos (XBUFFER (obj), ind) :		\
+   (Bufpos) bytecount_to_charcount (string_data (XSTRING (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                      */
+/*----------------------------------------------------------------------*/
+
+#define VALID_BYTIND_P(buf, x) 1
+
+#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 */
+
+#define VALIDATE_BYTIND_BACKWARD(buf, x)
+
+#define VALIDATE_BYTIND_FORWARD(buf, x)
+
+/* 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         */
+/*----------------------------------------------------------------------*/
+
+#define real_bufpos_to_bytind(buf, x)	((Bytind) x)
+#define real_bytind_to_bufpos(buf, x)	((Bufpos) x)
+
+#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.
+*/
+
+#define convert_to_external_format(ptr, len, len_out, fmt) \
+     (*(len_out) = (int) (len), (CONST Extbyte *) (ptr))
+#define convert_from_external_format(ptr, len, len_out, fmt) \
+     (*(len_out) = (Bytecount) (len), (CONST Bufbyte *) (ptr))
+
+
+/* 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.
+
+   -- 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.) */
+     
+#define GET_CHARPTR_EXT_DATA_ALLOCA(ptr, len, fmt, stick_value_here, stick_len_here)\
+do								\
+{								\
+  (stick_value_here) = (CONST Extbyte *) (ptr);			\
+  (stick_len_here) = (Extcount) (len);				\
+} while (0)
+
+#define GET_C_CHARPTR_EXT_DATA_ALLOCA(ptr, fmt, stick_value_here)	\
+do									\
+{									\
+  Extcount __gcceda_ignored_len__;					\
+  CONST char *__gcceda_ptr_in__;					\
+  CONST Extbyte *__gcceda_ptr_out__;					\
+									\
+  __gcceda_ptr_in__ = ptr;						\
+  GET_CHARPTR_EXT_DATA_ALLOCA ((CONST Extbyte *) __gcceda_ptr_in__,	\
+			       strlen (__gcceda_ptr_in__), fmt,		\
+			       __gcceda_ptr_out__,			\
+				__gcceda_ignored_len__);		\
+  (stick_value_here) = (CONST char *) __gcceda_ptr_out__;		\
+} while (0)
+
+#define GET_C_CHARPTR_EXT_BINARY_DATA_ALLOCA(ptr, stick_value_here) \
+  GET_C_CHARPTR_EXT_DATA_ALLOCA (ptr, FORMAT_BINARY, stick_value_here)
+#define GET_CHARPTR_EXT_BINARY_DATA_ALLOCA(ptr, len, stick_value_here, stick_len_here) \
+  GET_CHARPTR_EXT_DATA_ALLOCA (ptr, len, FORMAT_BINARY, stick_value_here, \
+			       stick_len_here)
+
+#define GET_C_CHARPTR_EXT_FILENAME_DATA_ALLOCA(ptr, stick_value_here) \
+  GET_C_CHARPTR_EXT_DATA_ALLOCA (ptr, FORMAT_FILENAME, stick_value_here)
+#define GET_CHARPTR_EXT_FILENAME_DATA_ALLOCA(ptr, len, stick_value_here, stick_len_here) \
+  GET_CHARPTR_EXT_DATA_ALLOCA (ptr, len, FORMAT_FILENAME, stick_value_here, \
+			       stick_len_here)
+
+#define GET_C_CHARPTR_EXT_CTEXT_DATA_ALLOCA(ptr, stick_value_here) \
+  GET_C_CHARPTR_EXT_DATA_ALLOCA (ptr, FORMAT_CTEXT, stick_value_here)
+#define GET_CHARPTR_EXT_CTEXT_DATA_ALLOCA(ptr, len, stick_value_here, stick_len_here) \
+  GET_CHARPTR_EXT_DATA_ALLOCA (ptr, len, FORMAT_CTEXT, stick_value_here, \
+			       stick_len_here)
+
+/* 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.) */
+     
+#define GET_CHARPTR_INT_DATA_ALLOCA(ptr, len, fmt, stick_value_here, stick_len_here)\
+do								\
+{								\
+  (stick_value_here) = (CONST Bufbyte *) (ptr);			\
+  (stick_len_here) = (Bytecount) (len);				\
+} while (0)
+
+#define GET_C_CHARPTR_INT_DATA_ALLOCA(ptr, fmt, stick_value_here)	\
+do									\
+{									\
+  Bytecount __gccida_ignored_len__;					\
+  CONST char *__gccida_ptr_in__;					\
+  CONST Bufbyte *__gccida_ptr_out__;					\
+									\
+  __gccida_ptr_in__ = ptr;						\
+  GET_CHARPTR_INT_DATA_ALLOCA ((CONST Extbyte *) __gccida_ptr_in__,	\
+			       strlen (__gccida_ptr_in__), fmt,		\
+			       __gccida_ptr_out__,			\
+				__gccida_ignored_len__);		\
+  (stick_value_here) = (CONST char *) __gccida_ptr_out__;		\
+} while (0)
+
+#define GET_C_CHARPTR_INT_BINARY_DATA_ALLOCA(ptr, stick_value_here) \
+  GET_C_CHARPTR_INT_DATA_ALLOCA (ptr, FORMAT_BINARY, stick_value_here)
+#define GET_CHARPTR_INT_BINARY_DATA_ALLOCA(ptr, len, stick_value_here, stick_len_here) \
+  GET_CHARPTR_INT_DATA_ALLOCA (ptr, len, FORMAT_BINARY, stick_value_here, \
+			       stick_len_here)
+
+#define GET_C_CHARPTR_INT_FILENAME_DATA_ALLOCA(ptr, stick_value_here) \
+  GET_C_CHARPTR_INT_DATA_ALLOCA (ptr, FORMAT_FILENAME, stick_value_here)
+#define GET_CHARPTR_INT_FILENAME_DATA_ALLOCA(ptr, len, stick_value_here, stick_len_here) \
+  GET_CHARPTR_INT_DATA_ALLOCA (ptr, len, FORMAT_FILENAME, stick_value_here, \
+			       stick_len_here)
+
+#define GET_C_CHARPTR_INT_CTEXT_DATA_ALLOCA(ptr, stick_value_here) \
+  GET_C_CHARPTR_INT_DATA_ALLOCA (ptr, FORMAT_CTEXT, stick_value_here)
+#define GET_CHARPTR_INT_CTEXT_DATA_ALLOCA(ptr, len, stick_value_here, stick_len_here) \
+  GET_CHARPTR_INT_DATA_ALLOCA (ptr, len, FORMAT_CTEXT, stick_value_here, \
+			       stick_len_here)
+
+
+/* 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, stick_value_here, stick_len_here)\
+do									   \
+{									   \
+  Extcount __gseda_len__;						   \
+  CONST Extbyte *__gseda_ptr__;						   \
+  struct Lisp_String *__gseda_s__ = XSTRING (s);			   \
+									   \
+  __gseda_ptr__ = convert_to_external_format (string_data (__gseda_s__),   \
+					      string_length (__gseda_s__), \
+					      &__gseda_len__, fmt);	   \
+  (stick_value_here) = alloca (1 + __gseda_len__);			   \
+  memcpy ((Extbyte *) stick_value_here, __gseda_ptr__, 1 + __gseda_len__); \
+  (stick_len_here) = __gseda_len__;					   \
+} while (0)
+
+
+#define GET_C_STRING_EXT_DATA_ALLOCA(s, fmt, stick_value_here)	\
+do								\
+{								\
+  Extcount __gcseda_ignored_len__;				\
+  CONST Extbyte *__gcseda_ptr__;				\
+								\
+  GET_STRING_EXT_DATA_ALLOCA (s, fmt, __gcseda_ptr__,		\
+			      __gcseda_ignored_len__);		\
+  (stick_value_here) = (CONST char *) __gcseda_ptr__;		\
+} while (0)
+
+#define GET_STRING_BINARY_DATA_ALLOCA(s, stick_value_here, stick_len_here) \
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_BINARY, stick_value_here,	   \
+			      stick_len_here)
+#define GET_C_STRING_BINARY_DATA_ALLOCA(s, stick_value_here) \
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_BINARY, stick_value_here)
+
+#define GET_STRING_FILENAME_DATA_ALLOCA(s, stick_value_here, stick_len_here) \
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_FILENAME, stick_value_here,	     \
+			      stick_len_here)
+#define GET_C_STRING_FILENAME_DATA_ALLOCA(s, stick_value_here) \
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_FILENAME, stick_value_here)
+
+#define GET_STRING_OS_DATA_ALLOCA(s, stick_value_here, stick_len_here) \
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_OS, stick_value_here,	       \
+			      stick_len_here)
+#define GET_C_STRING_OS_DATA_ALLOCA(s, stick_value_here) \
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_OS, stick_value_here)
+
+#define GET_STRING_CTEXT_DATA_ALLOCA(s, stick_value_here, stick_len_here) \
+  GET_STRING_EXT_DATA_ALLOCA (s, FORMAT_CTEXT, stick_value_here,	  \
+			      stick_len_here)
+#define GET_C_STRING_CTEXT_DATA_ALLOCA(s, stick_value_here) \
+  GET_C_STRING_EXT_DATA_ALLOCA (s, FORMAT_CTEXT, stick_value_here)
+
+
+
+/************************************************************************/
+/*                                                                      */
+/*                          fake charset functions                      */
+/*                                                                      */
+/************************************************************************/
+
+#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(cs) 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(by) 1
+
+
+/************************************************************************/
+/*                                                                      */
+/*                  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
+
+/*----------------------------------------------------------------------*/
+/*                      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 structure holds the default values of the buffer-local variables
+   defined with DEFVAR_BUFFER_LOCAL, that have special slots in each buffer.
+   The default value occupies the same slot in this structure
+   as an individual buffer's value occupies in that buffer.
+   Setting the default value also goes through the alist of buffers
+   and stores into each buffer that does not say it has a local value.  */
+
+extern Lisp_Object Vbuffer_defaults;
+
+/* This structure marks which slots in a buffer have corresponding
+   default values in buffer_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 buffer_defaults is not used.  */
+
+extern struct buffer buffer_local_flags;
+
+
+/* Allocation of buffer data. */
+
+#ifdef REL_ALLOC
+
+char *r_alloc (char **, unsigned long);
+char *r_re_alloc (char **, unsigned long);
+void r_alloc_free (void **);
+
+#define BUFFER_ALLOC(data,size) \
+  ((Bufbyte *) r_alloc ((char **) &data, (size) * sizeof(Bufbyte)))
+#define BUFFER_REALLOC(data,size) \
+  ((Bufbyte *) r_re_alloc ((char **) &data, (size) * sizeof(Bufbyte)))
+#define BUFFER_FREE(data) r_alloc_free ((void **) &(data))
+#define R_ALLOC_DECLARE(var,data) r_alloc_declare (&(var), data)
+
+#else /* !REL_ALLOC */
+
+#define BUFFER_ALLOC(data,size)\
+	(data = (Bufbyte *) xmalloc ((size) * sizeof(Bufbyte)))
+#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);
+int 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);
+
+/* 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 extended-ASCII
+   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) string_data (XSTRING (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)
+
+# define IN_TRT_TABLE_DOMAIN(c) (((unsigned EMACS_INT) (c)) < 0400)
+
+#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)
+
+INLINE Emchar TRT_TABLE_OF (Lisp_Object trt, Emchar c);
+INLINE Emchar
+TRT_TABLE_OF (Lisp_Object trt, Emchar c)
+{
+  if (IN_TRT_TABLE_DOMAIN (c))
+    return TRT_TABLE_CHAR_1 (trt, c);
+  else
+    return 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)
+{
+  if (DOWNCASE_TABLE_OF (buf, ch) == ch)
+    return UPCASE_TABLE_OF (buf, ch);
+  else
+    return ch;
+}
+
+/* Upcase a character known to be not upper case.  */
+
+#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)
+
+
+/* put it here, somewhat arbitrarily ...  its needs to be in *some*
+   header file. */
+DECLARE_LRECORD (range_table, struct Lisp_Range_Table);
+
+#endif /* _XEMACS_BUFFER_H_ */