(parse_single_submenu): Use individual keymap's prompt
[bpt/emacs.git] / src / buffer.c
index d96c3df..9836ecc 100644 (file)
@@ -1,5 +1,5 @@
 /* Buffer manipulation primitives for GNU Emacs.
-   Copyright (C) 1985,86,87,88,89,93,94,95,97,98, 1999, 2000, 2001
+   Copyright (C) 1985,86,87,88,89,93,94,95,97,98, 1999, 2000, 2001, 2002
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -157,6 +157,7 @@ Lisp_Object Vfirst_change_hook;
 Lisp_Object Qfirst_change_hook;
 Lisp_Object Qbefore_change_functions;
 Lisp_Object Qafter_change_functions;
+Lisp_Object Qucs_set_table_for_input;
 
 /* If nonzero, all modification hooks are suppressed.  */
 int inhibit_modification_hooks;
@@ -193,7 +194,7 @@ nsberror (spec)
      Lisp_Object spec;
 {
   if (STRINGP (spec))
-    error ("No buffer named %s", XSTRING (spec)->data);
+    error ("No buffer named %s", SDATA (spec));
   error ("Invalid buffer argument");
 }
 \f
@@ -209,7 +210,9 @@ Value is nil if OBJECT is not a buffer or if it has been killed.  */)
 
 DEFUN ("buffer-list", Fbuffer_list, Sbuffer_list, 0, 1, 0,
        doc: /* Return a list of all existing live buffers.
-If the optional arg FRAME is a frame, we return that frame's buffer list.  */)
+If the optional arg FRAME is a frame, we return the buffer list
+in the proper order for that frame: the buffers in FRAME's `buffer-list'
+frame parameter come first, followed by the rest of the buffers.  */)
      (frame)
      Lisp_Object frame;
 {
@@ -247,10 +250,10 @@ assoc_ignore_text_properties (key, list)
      Lisp_Object list;
 {
   register Lisp_Object tail;
-  for (tail = list; !NILP (tail); tail = Fcdr (tail))
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
       register Lisp_Object elt, tem;
-      elt = Fcar (tail);
+      elt = XCAR (tail);
       tem = Fstring_equal (Fcar (elt), key);
       if (!NILP (tem))
        return elt;
@@ -341,7 +344,7 @@ The value is never nil.  */)
   if (!NILP (buf))
     return buf;
 
-  if (XSTRING (name)->size == 0)
+  if (SCHARS (name) == 0)
     error ("Empty string for buffer name is not allowed");
 
   b = (struct buffer *) allocate_buffer ();
@@ -361,16 +364,16 @@ The value is never nil.  */)
   if (! BUF_BEG_ADDR (b))
     buffer_memory_full ();
 
-  BUF_PT (b) = 1;
-  BUF_GPT (b) = 1;
-  BUF_BEGV (b) = 1;
-  BUF_ZV (b) = 1;
-  BUF_Z (b) = 1;
-  BUF_PT_BYTE (b) = 1;
-  BUF_GPT_BYTE (b) = 1;
-  BUF_BEGV_BYTE (b) = 1;
-  BUF_ZV_BYTE (b) = 1;
-  BUF_Z_BYTE (b) = 1;
+  BUF_PT (b) = BEG;
+  BUF_GPT (b) = BEG;
+  BUF_BEGV (b) = BEG;
+  BUF_ZV (b) = BEG;
+  BUF_Z (b) = BEG;
+  BUF_PT_BYTE (b) = BEG_BYTE;
+  BUF_GPT_BYTE (b) = BEG_BYTE;
+  BUF_BEGV_BYTE (b) = BEG_BYTE;
+  BUF_ZV_BYTE (b) = BEG_BYTE;
+  BUF_Z_BYTE (b) = BEG_BYTE;
   BUF_MODIFF (b) = 1;
   BUF_OVERLAY_MODIFF (b) = 1;
   BUF_SAVE_MODIFF (b) = 1;
@@ -397,10 +400,10 @@ The value is never nil.  */)
   b->zv_marker = Qnil;
 
   name = Fcopy_sequence (name);
-  XSTRING (name)->intervals = NULL_INTERVAL;
+  STRING_SET_INTERVALS (name, NULL_INTERVAL);
   b->name = name;
 
-  if (XSTRING (name)->data[0] != ' ')
+  if (SREF (name, 0) != ' ')
     b->undo_list = Qnil;
   else
     b->undo_list = Qt;
@@ -408,13 +411,20 @@ The value is never nil.  */)
   reset_buffer (b);
   reset_buffer_local_variables (b, 1);
 
+  b->mark = Fmake_marker ();
+  BUF_MARKERS (b) = Qnil;
+  b->name = name;
+
   /* Put this in the alist of all live buffers.  */
   XSETBUFFER (buf, b);
   Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buf), Qnil));
 
-  b->mark = Fmake_marker ();
-  BUF_MARKERS (b) = Qnil;
-  b->name = name;
+  /* Fixme:  Protect against errors, which would trigger infinite
+     regress?  */
+  if (!NILP (Ffboundp (Qucs_set_table_for_input)))
+    /* buff is on buffer-alist, so no gcpro */
+    call1 (Qucs_set_table_for_input, buf);
+
   return buf;
 }
 
@@ -520,13 +530,13 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
 
   buf = Fget_buffer (name);
   if (!NILP (buf))
-    error ("Buffer name `%s' is in use", XSTRING (name)->data);
+    error ("Buffer name `%s' is in use", SDATA (name));
 
   base_buffer = Fget_buffer (base_buffer);
   if (NILP (base_buffer))
-    error ("No such buffer: `%s'", XSTRING (name)->data);
+    error ("No such buffer: `%s'", SDATA (name));
 
-  if (XSTRING (name)->size == 0)
+  if (SCHARS (name) == 0)
     error ("Empty string for buffer name is not allowed");
 
   b = (struct buffer *) allocate_buffer ();
@@ -556,7 +566,7 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
   all_buffers = b;
 
   name = Fcopy_sequence (name);
-  XSTRING (name)->intervals = NULL_INTERVAL;
+  STRING_SET_INTERVALS (name, NULL_INTERVAL);
   b->name = name;
 
   reset_buffer (b);
@@ -646,6 +656,8 @@ reset_buffer (b)
   b->enable_multibyte_characters = buffer_defaults.enable_multibyte_characters;
   b->cursor_type = buffer_defaults.cursor_type;
   b->extra_line_spacing = buffer_defaults.extra_line_spacing;
+
+  b->display_error_modiff = 0;
 }
 
 /* Reset buffer B's local variables info.
@@ -691,11 +703,6 @@ reset_buffer_local_variables (b, permanent_too)
   b->buffer_file_type = Qnil;
 #endif
 
-#if 0
-  b->sort_table = XSTRING (Vascii_sort_table);
-  b->folding_sort_table = XSTRING (Vascii_folding_sort_table);
-#endif /* 0 */
-
   /* Reset all (or most) per-buffer variables to their defaults.  */
   b->local_var_alist = Qnil;
   for (i = 0; i < last_per_buffer_idx; ++i)
@@ -852,7 +859,26 @@ is the default binding of variable. */)
        result = Fdefault_value (symbol);
     }
   else
-    result = XCDR (result);
+    {
+      Lisp_Object valcontents;
+      Lisp_Object current_alist_element;
+
+      /* What binding is loaded right now?  */
+      valcontents = SYMBOL_VALUE (symbol);
+      current_alist_element
+       = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
+
+      /* The value of the currently loaded binding is not
+        stored in it, but rather in the realvalue slot.
+        Store that value into the binding it belongs to
+        in case that is the one we are about to use.  */
+
+      Fsetcdr (current_alist_element,
+              do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
+
+      /* Now get the (perhaps updated) value out of the binding.  */
+      result = XCDR (result);
+    }
 
   if (EQ (result, Qunbound))
     return Fsignal (Qvoid_variable, Fcons (symbol, Qnil));
@@ -1070,7 +1096,7 @@ This does not change the name of the visited file (if any).  */)
 
   CHECK_STRING (newname);
 
-  if (XSTRING (newname)->size == 0)
+  if (SCHARS (newname) == 0)
     error ("Empty string is invalid as a buffer name");
 
   tem = Fget_buffer (newname);
@@ -1085,7 +1111,7 @@ This does not change the name of the visited file (if any).  */)
       if (!NILP (unique))
        newname = Fgenerate_new_buffer_name (newname, current_buffer->name);
       else
-       error ("Buffer name `%s' is in use", XSTRING (newname)->data);
+       error ("Buffer name `%s' is in use", SDATA (newname));
     }
 
   current_buffer->name = newname;
@@ -1137,12 +1163,12 @@ If BUFFER is omitted or nil, some interesting buffer is returned.  */)
     }
   tail = nconc2 (Fnreverse (add_ons), tail);
 
-  for (; !NILP (tail); tail = Fcdr (tail))
+  for (; CONSP (tail); tail = XCDR (tail))
     {
-      buf = Fcdr (Fcar (tail));
+      buf = Fcdr (XCAR (tail));
       if (EQ (buf, buffer))
        continue;
-      if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+      if (SREF (XBUFFER (buf)->name, 0) == ' ')
        continue;
       /* If the selected frame has a buffer_predicate,
         disregard buffers that don't fit the predicate.  */
@@ -1268,7 +1294,7 @@ with SIGHUP.  */)
     {
       GCPRO1 (buf);
       tem = do_yes_or_no_p (format1 ("Buffer %s modified; kill anyway? ",
-                                    XSTRING (b->name)->data));
+                                    SDATA (b->name)));
       UNGCPRO;
       if (NILP (tem))
        return Qnil;
@@ -1276,7 +1302,7 @@ with SIGHUP.  */)
 
   /* Run hooks with the buffer to be killed the current buffer.  */
   {
-    int count = specpdl_ptr - specpdl;
+    int count = SPECPDL_INDEX ();
     Lisp_Object list;
 
     record_unwind_protect (save_excursion_restore, save_excursion_save ());
@@ -1284,16 +1310,15 @@ with SIGHUP.  */)
 
     /* First run the query functions; if any query is answered no,
        don't kill the buffer.  */
-    for (list = Vkill_buffer_query_functions; !NILP (list); list = Fcdr (list))
+    for (list = Vkill_buffer_query_functions; CONSP (list); list = XCDR (list))
       {
-       tem = call0 (Fcar (list));
+       tem = call0 (XCAR (list));
        if (NILP (tem))
          return unbind_to (count, Qnil);
       }
 
     /* Then run the hooks.  */
-    if (!NILP (Vrun_hooks))
-      call1 (Vrun_hooks, Qkill_buffer_hook);
+    Frun_hooks (1, &Qkill_buffer_hook);
     unbind_to (count, Qnil);
   }
 
@@ -1367,10 +1392,12 @@ with SIGHUP.  */)
   frames_discard_buffer (buf);
   Vinhibit_quit = tem;
 
-  /* Delete any auto-save file, if we saved it in this session.  */
+  /* Delete any auto-save file, if we saved it in this session.
+     But not if the buffer is modified.  */
   if (STRINGP (b->auto_save_file_name)
       && b->auto_save_modified != 0
-      && BUF_SAVE_MODIFF (b) < b->auto_save_modified)
+      && BUF_SAVE_MODIFF (b) < b->auto_save_modified
+      && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
     {
       Lisp_Object tem;
       tem = Fsymbol_value (intern ("delete-auto-save-files"));
@@ -1513,7 +1540,7 @@ the current buffer's major mode.  */)
   Lisp_Object function;
 
   if (STRINGP (XBUFFER (buffer)->name)
-      && strcmp (XSTRING (XBUFFER (buffer)->name)->data, "*scratch*") == 0)
+      && strcmp (SDATA (XBUFFER (buffer)->name), "*scratch*") == 0)
     function = find_symbol_value (intern ("initial-major-mode"));
   else
     {
@@ -1526,7 +1553,7 @@ the current buffer's major mode.  */)
   if (NILP (function) || EQ (function, Qfundamental_mode))
     return Qnil;
 
-  count = specpdl_ptr - specpdl;
+  count = SPECPDL_INDEX ();
 
   /* To select a nonfundamental mode,
      select the buffer temporarily and then call the mode function. */
@@ -1550,7 +1577,7 @@ no_switch_window (window)
   if (EQ (minibuf_window, window))
     return "Cannot switch buffers in minibuffer window";
   tem = Fwindow_dedicated_p (window);
-  if (!NILP (tem))
+  if (EQ (tem, Qt))
     return "Cannot switch buffers in a dedicated window";
   return NULL;
 }
@@ -1898,12 +1925,14 @@ selected window if it is displayed there.  */)
       tem = Fwindow_buffer (selected_window);
       /* If we're burying the current buffer, unshow it.  */
       if (EQ (buffer, tem))
-       if (NILP (Fwindow_dedicated_p (selected_window)))
-         Fswitch_to_buffer (Fother_buffer (buffer, Qnil, Qnil), Qnil);
-       else if (NILP (XWINDOW (selected_window)->parent))
-         Ficonify_frame (Fwindow_frame (selected_window));
-       else
-         Fdelete_window (selected_window);
+       {
+         if (NILP (Fwindow_dedicated_p (selected_window)))
+           Fswitch_to_buffer (Fother_buffer (buffer, Qnil, Qnil), Qnil);
+         else if (NILP (XWINDOW (selected_window)->parent))
+           Ficonify_frame (Fwindow_frame (selected_window));
+         else
+           Fdelete_window (selected_window);
+       }
     }
   else
     {
@@ -1927,7 +1956,10 @@ selected window if it is displayed there.  */)
       XSETCDR (link, Qnil);
       Vbuffer_alist = nconc2 (Vbuffer_alist, link);
 
-      frames_bury_buffer (buffer);
+      /* Removing BUFFER from frame-specific lists
+        has the effect of putting BUFFER at the end
+        of the combined list in each frame.  */
+      frames_discard_buffer (buffer);
     }
 
   return Qnil;
@@ -1980,7 +2012,7 @@ advance_to_char_boundary (byte_pos)
 
   if (byte_pos == BEG)
     /* Beginning of buffer is always a character boundary.  */
-    return 1;
+    return BEG;
 
   c = FETCH_BYTE (byte_pos);
   if (! CHAR_HEAD_P (c))
@@ -2294,10 +2326,6 @@ the normal hook `change-major-mode-hook'.  */)
 
   reset_buffer_local_variables (current_buffer, 0);
 
-  /* Redisplay mode lines; we are changing major mode.  */
-
-  update_mode_lines++;
-
   /* Any which are supposed to be permanent,
      make local again, with the same values they had.  */
      
@@ -2478,9 +2506,11 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
            {
              if (extend)
                {
-                 *len_ptr = len *= 2;
+                 /* Make it work with an initial len == 0.  */
+                 len *= 2;
                  if (len == 0)
-                   len = *len_ptr = 4;
+                   len = 4;
+                 *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
                }
@@ -2574,7 +2604,11 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
                 Either make it bigger, or don't store any more in it.  */
              if (extend)
                {
-                 *len_ptr = len *= 2;
+                 /* Make it work with an initial len == 0.  */
+                 len *= 2;
+                 if (len == 0)
+                   len = 4;
+                 *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
                }
@@ -2618,7 +2652,11 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
            {
              if (extend)
                {
-                 *len_ptr = len *= 2;
+                 /* Make it work with an initial len == 0.  */
+                 len *= 2;
+                 if (len == 0)
+                   len = 4;
+                 *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
                }
@@ -2860,24 +2898,24 @@ record_overlay_string (ssl, str, str2, pri, size)
   ssl->used++;
 
   if (NILP (current_buffer->enable_multibyte_characters))
-    nbytes = XSTRING (str)->size;
+    nbytes = SCHARS (str);
   else if (! STRING_MULTIBYTE (str))
-    nbytes = count_size_as_multibyte (XSTRING (str)->data,
-                                     STRING_BYTES (XSTRING (str)));
+    nbytes = count_size_as_multibyte (SDATA (str),
+                                     SBYTES (str));
   else
-    nbytes = STRING_BYTES (XSTRING (str));
+    nbytes = SBYTES (str);
 
   ssl->bytes += nbytes;
 
   if (STRINGP (str2))
     {
       if (NILP (current_buffer->enable_multibyte_characters))
-       nbytes = XSTRING (str2)->size;
+       nbytes = SCHARS (str2);
       else if (! STRING_MULTIBYTE (str2))
-       nbytes = count_size_as_multibyte (XSTRING (str2)->data,
-                                         STRING_BYTES (XSTRING (str2)));
+       nbytes = count_size_as_multibyte (SDATA (str2),
+                                         SBYTES (str2));
       else
-       nbytes = STRING_BYTES (XSTRING (str2));
+       nbytes = SBYTES (str2);
 
       ssl->bytes += nbytes;
     }
@@ -2989,8 +3027,8 @@ overlay_strings (pos, w, pstr)
        {
          int nbytes;
          tem = overlay_tails.buf[i].string;
-         nbytes = copy_text (XSTRING (tem)->data, p,
-                             STRING_BYTES (XSTRING (tem)),
+         nbytes = copy_text (SDATA (tem), p,
+                             SBYTES (tem),
                              STRING_MULTIBYTE (tem), multibyte);
          p += nbytes;
        }
@@ -2998,15 +3036,15 @@ overlay_strings (pos, w, pstr)
        {
          int nbytes;
          tem = overlay_heads.buf[i].string;
-         nbytes = copy_text (XSTRING (tem)->data, p,
-                             STRING_BYTES (XSTRING (tem)),
+         nbytes = copy_text (SDATA (tem), p,
+                             SBYTES (tem),
                              STRING_MULTIBYTE (tem), multibyte);
          p += nbytes;
          tem = overlay_heads.buf[i].string2;
          if (STRINGP (tem))
            {
-             nbytes = copy_text (XSTRING (tem)->data, p,
-                                 STRING_BYTES (XSTRING (tem)),
+             nbytes = copy_text (SDATA (tem), p,
+                                 SBYTES (tem),
                                  STRING_MULTIBYTE (tem), multibyte);
              p += nbytes;
            }
@@ -3227,18 +3265,26 @@ fix_overlays_in_range (start, end)
 {
   Lisp_Object overlay;
   Lisp_Object before_list, after_list;
-  Lisp_Object *ptail, *pbefore = &before_list, *pafter = &after_list;
+  /* These are either nil, indicating that before_list or after_list
+     should be assigned, or the cons cell the cdr of which should be
+     assigned.  */
+  Lisp_Object beforep = Qnil, afterp = Qnil;
+  /* 'Parent', likewise, indicates a cons cell or
+     current_buffer->overlays_before or overlays_after, depending
+     which loop we're in.  */
+  Lisp_Object tail, parent;
   int startpos, endpos;
 
   /* This algorithm shifts links around instead of consing and GCing.
      The loop invariant is that before_list (resp. after_list) is a
-     well-formed list except that its last element, the one that
-     *pbefore (resp. *pafter) points to, is still uninitialized.
-     So it's not a bug that before_list isn't initialized, although
-     it may look strange.  */
-  for (ptail = &current_buffer->overlays_before; CONSP (*ptail);)
+     well-formed list except that its last element, the CDR of beforep
+     (resp. afterp) if beforep (afterp) isn't nil or before_list
+     (after_list) if it is, is still uninitialized.  So it's not a bug
+     that before_list isn't initialized, although it may look
+     strange.  */
+  for (parent = Qnil, tail = current_buffer->overlays_before; CONSP (tail);)
     {
-      overlay = XCAR (*ptail);
+      overlay = XCAR (tail);
       endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
       if (endpos < start)
        break;
@@ -3260,22 +3306,32 @@ fix_overlays_in_range (start, end)
             recenter_overlay_lists will move it to the right place.  */
          if (endpos < XINT (current_buffer->overlay_center))
            {
-             *pafter = *ptail;
-             pafter = &XCDR (*ptail);
+             if (NILP (afterp))
+               after_list = tail;
+             else
+               XSETCDR (afterp, tail);
+             afterp = tail;
            }
          else
            {
-             *pbefore = *ptail;
-             pbefore = &XCDR (*ptail);
+             if (NILP (beforep))
+               before_list = tail;
+             else
+               XSETCDR (beforep, tail);
+             beforep = tail;
            }
-         *ptail = XCDR (*ptail);
+         if (NILP (parent))
+           current_buffer->overlays_before = XCDR (tail);
+         else
+           XSETCDR (parent, XCDR (tail));
+         tail = XCDR (tail);
        }
       else
-       ptail = &XCDR (*ptail);
+       parent = tail, tail = XCDR (parent);
     }
-  for (ptail = &current_buffer->overlays_after; CONSP (*ptail);)
+  for (parent = Qnil, tail = current_buffer->overlays_after; CONSP (tail);)
     {
-      overlay = XCAR (*ptail);
+      overlay = XCAR (tail);
       startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
       if (startpos >= end)
        break;
@@ -3294,29 +3350,45 @@ fix_overlays_in_range (start, end)
            }
          if (endpos < XINT (current_buffer->overlay_center))
            {
-             *pafter = *ptail;
-             pafter = &XCDR (*ptail);
+             if (NILP (afterp))
+               after_list = tail;
+             else
+               XSETCDR (afterp, tail);
+             afterp = tail;
            }
          else
            {
-             *pbefore = *ptail;
-             pbefore = &XCDR (*ptail);
+             if (NILP (beforep))
+               before_list = tail;
+             else
+               XSETCDR (beforep, tail);
+             beforep = tail;
            }
-         *ptail = XCDR (*ptail);
+         if (NILP (parent))
+           current_buffer->overlays_after = XCDR (tail);
+         else
+           XSETCDR (parent, XCDR (tail));
+         tail = XCDR (tail);
        }
       else
-       ptail = &XCDR (*ptail);
+       parent = tail, tail = XCDR (parent);
     }
 
   /* Splice the constructed (wrong) lists into the buffer's lists,
      and let the recenter function make it sane again.  */
-  *pbefore = current_buffer->overlays_before;
-  current_buffer->overlays_before = before_list;
+  if (!NILP (beforep))
+    {
+      XSETCDR (beforep, current_buffer->overlays_before);
+      current_buffer->overlays_before = before_list;
+    }
   recenter_overlay_lists (current_buffer,
                          XINT (current_buffer->overlay_center));
 
-  *pafter = current_buffer->overlays_after;
-  current_buffer->overlays_after = after_list;
+  if (!NILP (afterp))
+    {
+      XSETCDR (afterp, current_buffer->overlays_after);
+      current_buffer->overlays_after = after_list;
+    }
   recenter_overlay_lists (current_buffer,
                          XINT (current_buffer->overlay_center));
 }
@@ -3338,8 +3410,9 @@ fix_overlays_before (bp, prev, pos)
      struct buffer *bp;
      int prev, pos;
 {
-  Lisp_Object *tailp = &bp->overlays_before;
-  Lisp_Object *right_place;
+  /* If parent is nil, replace overlays_before; otherwise, XCDR(parent).  */
+  Lisp_Object tail = bp->overlays_before, parent = Qnil;
+  Lisp_Object right_pair;
   int end;
 
   /* After the insertion, the several overlays may be in incorrect
@@ -3353,45 +3426,61 @@ fix_overlays_before (bp, prev, pos)
      in.  It is where an overlay which end before POS exists. (i.e. an
      overlay whose ending marker is after-insertion-marker if disorder
      exists).  */
-  while (!NILP (*tailp)
-        && ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (*tailp))))
+  while (!NILP (tail)
+        && ((end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail))))
             >= pos))
-    tailp = &XCDR (*tailp);
+    {
+      parent = tail;
+      tail = XCDR (tail);
+    }
 
   /* If we don't find such an overlay,
      or the found one ends before PREV,
      or the found one is the last one in the list,
      we don't have to fix anything.  */
-  if (NILP (*tailp)
+  if (NILP (tail)
       || end < prev
-      || NILP (XCDR (*tailp)))
+      || NILP (XCDR (tail)))
     return;
 
-  right_place = tailp;
-  tailp = &XCDR (*tailp);
+  right_pair = parent;
+  parent = tail;
+  tail = XCDR (tail);
 
-  /* Now, end position of overlays in the list *TAILP should be before
+  /* Now, end position of overlays in the list TAIL should be before
      or equal to PREV.  In the loop, an overlay which ends at POS is
-     moved ahead to the place pointed by RIGHT_PLACE.  If we found an
-     overlay which ends before PREV, the remaining overlays are in
-     correct order.  */
-  while (!NILP (*tailp))
+     moved ahead to the place indicated by the CDR of RIGHT_PAIR.  If
+     we found an overlay which ends before PREV, the remaining
+     overlays are in correct order.  */
+  while (!NILP (tail))
     {
-      end = OVERLAY_POSITION (OVERLAY_END (XCAR (*tailp)));
+      end = OVERLAY_POSITION (OVERLAY_END (XCAR (tail)));
 
       if (end == pos)
        {                       /* This overlay is disordered. */
-         Lisp_Object found = *tailp;
+         Lisp_Object found = tail;
 
          /* Unlink the found overlay.  */
-         *tailp = XCDR (found);
-         /* Move an overlay at RIGHT_PLACE to the next of the found one.  */
-         XCDR (found) = *right_place;
-         /* Link it into the right place.  */
-         *right_place = found;
+         tail = XCDR (found);
+         XSETCDR (parent, tail);
+         /* Move an overlay at RIGHT_PLACE to the next of the found one,
+            and link it into the right place.  */
+         if (NILP (right_pair))
+           {
+             XSETCDR (found, bp->overlays_before);
+             bp->overlays_before = found;
+           }
+         else
+           {
+             XSETCDR (found, XCDR (right_pair));
+             XSETCDR (right_pair, found);
+           }
        }
       else if (end == prev)
-       tailp = &XCDR (*tailp);
+       {
+         parent = tail;
+         tail = XCDR (tail);
+       }
       else                     /* No more disordered overlay. */
        break;
     }
@@ -3512,7 +3601,7 @@ buffer.  */)
 {
   struct buffer *b, *ob;
   Lisp_Object obuffer;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
 
   CHECK_OVERLAY (overlay);
   if (NILP (buffer))
@@ -3613,7 +3702,7 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
 {
   Lisp_Object buffer;
   struct buffer *b;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
 
   CHECK_OVERLAY (overlay);
 
@@ -3860,28 +3949,8 @@ DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0,
      (overlay, prop)
      Lisp_Object overlay, prop;
 {
-  Lisp_Object plist, fallback;
-
   CHECK_OVERLAY (overlay);
-
-  fallback = Qnil;
-
-  for (plist = XOVERLAY (overlay)->plist;
-       CONSP (plist) && CONSP (XCDR (plist));
-       plist = XCDR (XCDR (plist)))
-    {
-      if (EQ (XCAR (plist), prop))
-       return XCAR (XCDR (plist));
-      else if (EQ (XCAR (plist), Qcategory))
-       {
-         Lisp_Object tem;
-         tem = Fcar (Fcdr (plist));
-         if (SYMBOLP (tem))
-           fallback = Fget (tem, prop);
-       }
-    }
-
-  return fallback;
+  return lookup_char_property (XOVERLAY (overlay)->plist, prop, 0);
 }
 
 DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
@@ -4148,13 +4217,13 @@ call_overlay_mod_hooks (list, overlay, after, arg1, arg2, arg3)
   if (! after)
     add_overlay_mod_hooklist (list, overlay);
 
-  while (!NILP (list))
+  while (CONSP (list))
     {
       if (NILP (arg3))
-       call4 (Fcar (list), overlay, after ? Qt : Qnil, arg1, arg2);
+       call4 (XCAR (list), overlay, after ? Qt : Qnil, arg1, arg2);
       else
-       call5 (Fcar (list), overlay, after ? Qt : Qnil, arg1, arg2, arg3);
-      list = Fcdr (list);
+       call5 (XCAR (list), overlay, after ? Qt : Qnil, arg1, arg2, arg3);
+      list = XCDR (list);
     }
   UNGCPRO;
 }
@@ -4228,7 +4297,7 @@ buffer_slot_type_mismatch (offset)
 
   sym = PER_BUFFER_SYMBOL (offset);
   error ("Only %s should be stored in the buffer-local variable %s",
-        type_name, XSYMBOL (sym)->name->data);
+        type_name, SDATA (SYMBOL_NAME (sym)));
 }
 
 \f
@@ -4342,6 +4411,18 @@ static int mmap_initialized_p;
 
 #define MEM_ALIGN      sizeof (double)
 
+/* Predicate returning true if part of the address range [START .. END]
+   is currently mapped.  Used to prevent overwriting an existing
+   memory mapping.
+
+   Default is to conservativly assume the address range is occupied by
+   something else.  This can be overridden by system configuration
+   files if system-specific means to determine this exists.  */
+
+#ifndef MMAP_ALLOCATED_P
+#define MMAP_ALLOCATED_P(start, end) 1
+#endif
+
 /* Function prototypes.  */
 
 static int mmap_free_1 P_ ((struct mmap_region *));
@@ -4434,16 +4515,13 @@ mmap_enlarge (r, npages)
     }
   else if (npages > 0)
     {
-      struct mmap_region *r2;
-      
       nbytes = npages * mmap_page_size;
       
       /* Try to map additional pages at the end of the region.  We
         cannot do this if the address range is already occupied by
         something else because mmap deletes any previous mapping.
         I'm not sure this is worth doing, let's see.  */
-      r2 = mmap_find (region_end, region_end + nbytes);
-      if (r2 == NULL)
+      if (!MMAP_ALLOCATED_P (region_end, region_end + nbytes))
        {
          POINTER_TYPE *p;
       
@@ -4611,8 +4689,12 @@ mmap_realloc (var, nbytes)
       else if (room - nbytes >= mmap_page_size)
        {
          /* Shrinking by at least a page.  Let's give some
-            memory back to the system.  */
-         mmap_enlarge (r, - (room - nbytes) / mmap_page_size);
+            memory back to the system.
+
+            The extra parens are to make the division happens first,
+            on positive values, so we know it will round towards
+            zero.  */
+         mmap_enlarge (r, - ((room - nbytes) / mmap_page_size));
          result = *var;
          r->nbytes_specified = nbytes;
        }
@@ -4927,6 +5009,8 @@ init_buffer_once ()
 
   Qkill_buffer_hook = intern ("kill-buffer-hook");
 
+  Qucs_set_table_for_input = intern ("ucs-set-table-for-input");
+
   Vprin1_to_string_buffer = Fget_buffer_create (build_string (" prin1"));
 
   /* super-magic invisible buffer */
@@ -4963,8 +5047,9 @@ init_buffer ()
   if (NILP (buffer_defaults.enable_multibyte_characters))
     Fset_buffer_multibyte (Qnil);
 
-  /* If PWD is accurate, use it instead of calling getwd.  This is faster
-     when PWD is right, and may avoid a fatal error.  */
+  /* If PWD is accurate, use it instead of calling getwd.  PWD is
+     sometimes a nicer name, and using it may avoid a fatal error if a
+     parent directory is searchable but not readable.  */
   if ((pwd = getenv ("PWD")) != 0
       && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
       && stat (pwd, &pwdstat) == 0
@@ -5002,7 +5087,7 @@ init_buffer ()
         because of the ange-ftp completion handler.
         However, it is not necessary to turn / into /:/.
         So avoid doing that.  */
-      && strcmp ("/", XSTRING (current_buffer->directory)->data))
+      && strcmp ("/", SDATA (current_buffer->directory)))
     current_buffer->directory
       = concat2 (build_string ("/:"), current_buffer->directory);
 
@@ -5053,6 +5138,7 @@ syms_of_buffer ()
   staticpro (&Qbefore_change_functions);
   Qafter_change_functions = intern ("after-change-functions");
   staticpro (&Qafter_change_functions);
+  staticpro (&Qucs_set_table_for_input);
 
   Fput (Qprotected_field, Qerror_conditions,
        Fcons (Qprotected_field, Fcons (Qerror, Qnil)));
@@ -5156,21 +5242,22 @@ This is the same as (default-value 'indicate-empty-lines).  */);
   
   DEFVAR_LISP_NOPRO ("default-scroll-up-aggressively",
                     &buffer_defaults.scroll_up_aggressively,
-                    doc: /* Default value of `scroll-up-aggressively' for buffers that
-don't override it.  This is the same as (default-value
-'scroll-up-aggressively).  */);
+                    doc: /* Default value of `scroll-up-aggressively'.
+This value applies in buffers that don't have their own local values.
+This variable is an alias for (default-value 'scroll-up-aggressively).  */);
   
   DEFVAR_LISP_NOPRO ("default-scroll-down-aggressively",
                     &buffer_defaults.scroll_down_aggressively,
-                    doc: /* Default value of `scroll-down-aggressively' for buffers that
-don't override it.  This is the same as (default-value
-'scroll-down-aggressively).  */);
+                    doc: /* Default value of `scroll-down-aggressively'.
+This value applies in buffers that don't have their own local values.
+This variable is an alias for (default-value 'scroll-down-aggressively).  */);
   
   DEFVAR_PER_BUFFER ("header-line-format",
                     &current_buffer->header_line_format,
                     Qnil,
-                    doc: /* Analogous to `mode-line-format', but for the mode line that can be
-displayed at the top of a window.  */);
+                    doc: /* Analogous to `mode-line-format', but controls the header line.
+The header line appears, optionally, at the top of a window;
+the mode line appears at the bottom.  */);
   
   DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format,
                     Qnil,
@@ -5181,8 +5268,14 @@ A value of nil means don't display a mode line.
 For a symbol, its value is used (but it is ignored if t or nil).
  A string appearing directly as the value of a symbol is processed verbatim
  in that the %-constructs below are not recognized.
+ Note that unless the symbol is marked as a `risky-local-variable', all
+ properties in any strings, as well as all :eval and :propertize forms 
+ in the value of that symbol will be ignored.
 For a list of the form `(:eval FORM)', FORM is evaluated and the result
- is used as a mode line element.
+ is used as a mode line element.  Be careful--FORM should not load any files,
+ because that can cause an infinite recursion.
+For a list of the form `(:propertize ELT PROPS...)', ELT is displayed
+ with the specified properties PROPS applied.
 For a list whose car is a symbol, the symbol's value is taken,
  and if that is non-nil, the cadr of the list is processed recursively.
  Otherwise, the caddr of the list (if there is one) is processed.
@@ -5224,7 +5317,7 @@ nil here means use current buffer's major mode.  */);
                     doc: /* Symbol for current buffer's major mode.  */);
 
   DEFVAR_PER_BUFFER ("mode-name", &current_buffer->mode_name,
-                     make_number (Lisp_String),
+                     Qnil,
                     doc: /* Pretty name of current buffer's major mode (a string).  */);
 
   DEFVAR_PER_BUFFER ("abbrev-mode", &current_buffer->abbrev_mode, Qnil,
@@ -5236,7 +5329,8 @@ nil here means use current buffer's major mode.  */);
 
   DEFVAR_PER_BUFFER ("fill-column", &current_buffer->fill_column,
                     make_number (Lisp_Int),
-                    doc: /* *Column beyond which automatic line-wrapping should happen.  */);
+                    doc: /* *Column beyond which automatic line-wrapping should happen.
+Interactively, you can set this using \\[set-fill-column].  */);
 
   DEFVAR_PER_BUFFER ("left-margin", &current_buffer->left_margin,
                     make_number (Lisp_Int),
@@ -5277,6 +5371,9 @@ If this is nil, the buffer is saved without any code conversion
 unless some coding system is specified in `file-coding-system-alist'
 for the buffer file.
 
+If the text to be saved cannot be encoded as specified by this variable,
+an alternative encoding is selected by `select-safe-coding-system', which see.
+
 The variable `coding-system-for-write', if non-nil, overrides this variable.
 
 This variable is never applied to a way of decoding a file while reading it.  */);
@@ -5286,8 +5383,8 @@ This variable is never applied to a way of decoding a file while reading it.  */
                     doc: /* *Non-nil means lines in the buffer are displayed right to left.  */);
 
   DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines, Qnil,
-                    doc: /* *Non-nil means do not display continuation lines;
-give each line of text one screen line.
+                    doc: /* *Non-nil means do not display continuation lines.
+Instead, give each line of text just one screen line.
 
 Note that this is overridden by the variable
 `truncate-partial-width-windows' if that variable is non-nil
@@ -5328,8 +5425,8 @@ and then abbreviated with `abbreviate-file-name'.  */);
   DEFVAR_PER_BUFFER ("buffer-auto-save-file-name",
                     &current_buffer->auto_save_file_name,
                     make_number (Lisp_String),
-                    doc: /* Name of file for auto-saving current buffer,
-or nil if buffer should not be auto-saved.  */);
+                    doc: /* Name of file for auto-saving current buffer.
+If it is nil, that means don't auto-save this buffer.  */);
 
   DEFVAR_PER_BUFFER ("buffer-read-only", &current_buffer->read_only, Qnil,
                     doc: /* Non-nil if this buffer is read-only.  */);
@@ -5345,11 +5442,12 @@ Backing up is done before the first time the file is saved.  */);
 
   DEFVAR_PER_BUFFER ("selective-display", &current_buffer->selective_display,
                     Qnil,
-                    doc: /* Non-nil enables selective display:
-Integer N as value means display only lines
- that start with less than n columns of space.
-A value of t means, after a ^M, all the rest of the line is invisible.
- Then ^M's in the file are written into files as newlines.  */);
+                    doc: /* Non-nil enables selective display.
+An Integer N as value means display only lines
+that start with less than n columns of space.
+A value of t means that the character ^M makes itself and
+all the rest of the line invisible; also, when saving the buffer
+in a file, save the ^M as a newline.  */);
 
 #ifndef old
   DEFVAR_PER_BUFFER ("selective-display-ellipses",
@@ -5423,16 +5521,16 @@ window-systems.  */);
   DEFVAR_PER_BUFFER ("scroll-up-aggressively",
                     &current_buffer->scroll_up_aggressively, Qnil,
                     doc: /* *If a number, scroll display up aggressively.
-If scrolling a window because point is above the window start, choose
+If scrolling a window because point is below the window end, choose
 a new window start so that point ends up that fraction of the window's
-height from the top of the window.  */);
+height from the bottom of the window.  */);
   
   DEFVAR_PER_BUFFER ("scroll-down-aggressively",
                     &current_buffer->scroll_down_aggressively, Qnil,
                     doc: /* *If a number, scroll display down aggressively.
-If scrolling a window because point is below the window end, choose
+If scrolling a window because point is above the window start, choose
 a new window start so that point ends up that fraction of the window's
-height from the bottom of the window.  */);
+height from the top of the window.  */);
   
 /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
     "Don't ask.");
@@ -5458,7 +5556,7 @@ from happening repeatedly and making Emacs nonfunctional.  */);
   Vbefore_change_functions = Qnil;
 
   DEFVAR_LISP ("after-change-functions", &Vafter_change_functions,
-              doc: /* List of function to call after each text change.
+              doc: /* List of functions to call after each text change.
 Three arguments are passed to each function: the positions of
 the beginning and end of the range of changed text,
 and the length in bytes of the pre-change text replaced by that range.
@@ -5594,14 +5692,17 @@ is a member of the list.  */);
   Vinhibit_read_only = Qnil;
 
   DEFVAR_PER_BUFFER ("cursor-type", &current_buffer->cursor_type, Qnil,
-                    doc: /* Cursor to use in window displaying this buffer.
+     doc: /* Cursor to use when this buffer is in the selected window.
 Values are interpreted as follows:
 
-  t            use the cursor specified for the frame
-  nil          don't display a cursor
-  `bar'                display a bar cursor with default width
-  (bar . WIDTH)        display a bar cursor with width WIDTH
-  others       display a box cursor.  */);
+  t             use the cursor specified for the frame
+  nil           don't display a cursor
+  bar           display a bar cursor with default width
+  (bar . WIDTH)         display a bar cursor with width WIDTH
+  ANYTHING ELSE         display a box cursor.
+
+When the buffer is displayed in a nonselected window,
+this variable has no effect; the cursor appears as a hollow box.  */);
 
   DEFVAR_PER_BUFFER ("line-spacing",
                     &current_buffer->extra_line_spacing, Qnil,