Include keymap.h.
[bpt/emacs.git] / src / buffer.c
index 5df8e2d..b5d1ab8 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
+   Copyright (C) 1985,86,87,88,89,93,94,95,97,98, 1999, 2000, 2001
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <errno.h>
+#include <stdio.h>
 
 #ifndef USE_CRT_DLL
 extern int errno;
@@ -48,6 +49,7 @@ extern int errno;
 #include "indent.h"
 #include "blockinput.h"
 #include "keyboard.h"
+#include "keymap.h"
 #include "frame.h"
 
 struct buffer *current_buffer;         /* the current buffer */
@@ -178,6 +180,8 @@ Lisp_Object Qinsert_behind_hooks;
 
 static void alloc_buffer_text P_ ((struct buffer *, size_t));
 static void free_buffer_text P_ ((struct buffer *b));
+static Lisp_Object copy_overlays P_ ((struct buffer *, Lisp_Object));
+static void modify_overlay P_ ((struct buffer *, int, int));
 
 
 /* For debugging; temporary.  See set_buffer_internal.  */
@@ -414,6 +418,49 @@ The value is never nil.")
 }
 
 
+/* Return a list of overlays which is a copy of the overlay list
+   LIST, but for buffer B.  */
+
+static Lisp_Object
+copy_overlays (b, list)
+     struct buffer *b;
+     Lisp_Object list;
+{
+  Lisp_Object result, buffer;
+
+  XSETBUFFER (buffer, b);
+
+  for (result = Qnil; CONSP (list); list = XCDR (list))
+    {
+      Lisp_Object overlay, start, end, old_overlay;
+      int charpos;
+
+      old_overlay = XCAR (list);
+      charpos = marker_position (OVERLAY_START (old_overlay));
+      start = Fmake_marker ();
+      Fset_marker (start, make_number (charpos), buffer);
+      XMARKER (start)->insertion_type
+       = XMARKER (OVERLAY_START (old_overlay))->insertion_type;
+
+      charpos = marker_position (OVERLAY_END (old_overlay));
+      end = Fmake_marker ();
+      Fset_marker (end, make_number (charpos), buffer);
+      XMARKER (end)->insertion_type
+       = XMARKER (OVERLAY_END (old_overlay))->insertion_type;
+
+      overlay = allocate_misc ();
+      XMISCTYPE (overlay) = Lisp_Misc_Overlay;
+      OVERLAY_START (overlay) = start;
+      OVERLAY_END (overlay) = end;
+      OVERLAY_PLIST (overlay) = Fcopy_sequence (OVERLAY_PLIST (old_overlay));
+      
+      result = Fcons (overlay, result);
+    }
+
+  return Fnreverse (result);
+}
+     
+
 /* Clone per-buffer values of buffer FROM.
 
    Buffer TO gets the same per-buffer values as FROM, with the
@@ -448,9 +495,10 @@ clone_per_buffer_values (from, to)
       PER_BUFFER_VALUE (to, offset) = obj;
     }
 
-  to->overlays_after = Fcopy_sequence (from->overlays_after);
-  to->overlays_before = Fcopy_sequence (to->overlays_before);
   bcopy (from->local_flags, to->local_flags, sizeof to->local_flags);
+  
+  to->overlays_before = copy_overlays (to, from->overlays_before);
+  to->overlays_after = copy_overlays (to, from->overlays_after);
 }
 
 
@@ -475,8 +523,7 @@ CLONE nil means the indirect buffer's state is reset to default values.")
 
   base_buffer = Fget_buffer (base_buffer);
   if (NILP (base_buffer))
-    error ("No such buffer: `%s'",
-          XSTRING (XBUFFER (base_buffer)->name)->data);
+    error ("No such buffer: `%s'", XSTRING (name)->data);
 
   if (XSTRING (name)->size == 0)
     error ("Empty string for buffer name is not allowed");
@@ -894,7 +941,10 @@ A non-nil FLAG means mark the buffer modified.")
   XSETBUFFER (buffer, current_buffer);
   window = Fget_buffer_window (buffer, Qt);
   if (WINDOWP (window))
-    update_mode_lines++;
+    {
+      ++update_mode_lines;
+      current_buffer->prevent_redisplay_optimizations_p = 1;
+    }
   
   return flag;
 }
@@ -1235,6 +1285,16 @@ with SIGHUP.")
        return Qnil;
     }
 
+  /* Notice if the buffer to kill is the sole visible buffer
+     when we're currently in the mini-buffer, and give up if so.  */
+  XSETBUFFER (tem, current_buffer);
+  if (EQ (tem, XWINDOW (minibuf_window)->buffer))
+    {
+      tem = Fother_buffer (buf, Qnil, Qnil);
+      if (EQ (buf, tem))
+       return Qnil;
+    }
+
   /* Now there is no question: we can kill the buffer.  */
 
 #ifdef CLASH_DETECTION
@@ -1624,7 +1684,7 @@ set_buffer_internal_1 (b)
 
   for (tail = b->local_var_alist; !NILP (tail); tail = XCDR (tail))
     {
-      valcontents = XSYMBOL (XCAR (XCAR (tail)))->value;
+      valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
       if ((BUFFER_LOCAL_VALUEP (valcontents)
           || SOME_BUFFER_LOCAL_VALUEP (valcontents))
          && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
@@ -1639,7 +1699,7 @@ set_buffer_internal_1 (b)
   if (old_buf)
     for (tail = old_buf->local_var_alist; !NILP (tail); tail = XCDR (tail))
       {
-       valcontents = XSYMBOL (XCAR (XCAR (tail)))->value;
+       valcontents = SYMBOL_VALUE (XCAR (XCAR (tail)));
        if ((BUFFER_LOCAL_VALUEP (valcontents)
             || SOME_BUFFER_LOCAL_VALUEP (valcontents))
            && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
@@ -2201,27 +2261,27 @@ swap_out_buffer_local_variables (b)
       sym = XCAR (XCAR (alist));
 
       /* Need not do anything if some other buffer's binding is now encached.  */
-      tem = XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->buffer;
+      tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer;
       if (BUFFERP (tem) && XBUFFER (tem) == current_buffer)
        {
          /* Symbol is set up for this buffer's old local value.
             Set it up for the current buffer with the default value.  */
 
-         tem = XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->cdr;
+         tem = XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->cdr;
          /* Store the symbol's current value into the alist entry
             it is currently set up for.  This is so that, if the
             local is marked permanent, and we make it local again
             later in Fkill_all_local_variables, we don't lose the value.  */
          XCDR (XCAR (tem))
-           = do_symval_forwarding (XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->realvalue);
+           = do_symval_forwarding (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->realvalue);
          /* Switch to the symbol's default-value alist entry.  */
          XCAR (tem) = tem;
          /* Mark it as current for buffer B.  */
-         XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->buffer = buffer;
+         XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer = buffer;
          /* Store the current value into any forwarding in the symbol.  */
          store_symval_forwarding (sym,
-                                  XBUFFER_LOCAL_VALUE (XSYMBOL (sym)->value)->realvalue,
-                                  XCDR (tem));
+                                  XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->realvalue,
+                                  XCDR (tem), NULL);
        }
     }
 }
@@ -2362,7 +2422,8 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr, change_req)
        }
       else if (endpos < pos && endpos > prev)
        prev = endpos;
-      else if (endpos == pos && startpos > prev && !change_req)
+      else if (endpos == pos && startpos > prev
+              && (!change_req || startpos < pos))
        prev = startpos;
     }
 
@@ -2504,6 +2565,39 @@ overlays_in (beg, end, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
     *prev_ptr = prev;
   return idx;
 }
+
+
+/* Return non-zero if there exists an overlay with a non-nil
+   `mouse-face' property overlapping OVERLAY.  */
+
+int
+mouse_face_overlay_overlaps (overlay)
+     Lisp_Object overlay;
+{
+  int start = OVERLAY_POSITION (OVERLAY_START (overlay));
+  int end = OVERLAY_POSITION (OVERLAY_END (overlay));
+  int n, i, size;
+  Lisp_Object *v, tem;
+  
+  size = 10;
+  v = (Lisp_Object *) alloca (size * sizeof *v);
+  n = overlays_in (start, end, 0, &v, &size, NULL, NULL);
+  if (n > size)
+    {
+      v = (Lisp_Object *) alloca (n * sizeof *v);
+      overlays_in (start, end, 0, &v, &n, NULL, NULL);
+    }
+
+  for (i = 0; i < n; ++i)
+    if (!EQ (v[i], overlay)
+       && (tem = Foverlay_get (overlay, Qmouse_face),
+           !NILP (tem)))
+      break;
+
+  return i < n;
+}
+
+
 \f
 /* Fast function to just test if we're at an overlay boundary.  */
 int
@@ -3310,13 +3404,11 @@ modify_overlay (buf, start, end)
      struct buffer *buf;
      int start, end;
 {
-  if (start == end)
-    return;
-
   if (start > end)
     {
       int temp = start;
-      start = end; end = temp;
+      start = end;
+      end = temp;
     }
 
   BUF_COMPUTE_UNCHANGED (buf, start, end);
@@ -3455,19 +3547,25 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
     return Qnil;
 
   b = XBUFFER (buffer);
-
   specbind (Qinhibit_quit, Qt);
-
+  
   b->overlays_before = Fdelq (overlay, b->overlays_before);
-  b->overlays_after  = Fdelq (overlay, b->overlays_after);
-
+  b->overlays_after = Fdelq (overlay, b->overlays_after);
   modify_overlay (b,
                  marker_position (OVERLAY_START (overlay)),
                  marker_position (OVERLAY_END   (overlay)));
-
   Fset_marker (OVERLAY_START (overlay), Qnil, Qnil);
   Fset_marker (OVERLAY_END   (overlay), Qnil, Qnil);
 
+  /* When deleting an overlay with before or after strings, turn off
+     display optimizations for the affected buffer, on the basis that
+     these strings may contain newlines.  This is easier to do than to
+     check for that situation during redisplay.  */
+  if (!windows_or_buffers_changed
+      && (!NILP (Foverlay_get (overlay, Qbefore_string))
+         || !NILP (Foverlay_get (overlay, Qafter_string))))
+    b->prevent_redisplay_optimizations_p = 1;
+
   return unbind_to (count, Qnil);
 }
 \f
@@ -3741,8 +3839,8 @@ DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
     {
       if (changed)
        modify_overlay (XBUFFER (buffer),
-                         marker_position (OVERLAY_START (overlay)),
-                         marker_position (OVERLAY_END   (overlay)));
+                       marker_position (OVERLAY_START (overlay)),
+                       marker_position (OVERLAY_END   (overlay)));
       if (EQ (prop, Qevaporate) && ! NILP (value)
          && (OVERLAY_POSITION (OVERLAY_START (overlay))
              == OVERLAY_POSITION (OVERLAY_END (overlay))))
@@ -4076,6 +4174,10 @@ buffer_slot_type_mismatch (offset)
 #endif
 #endif
 
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
 #include <stdio.h>
 #include <errno.h>
 
@@ -4221,7 +4323,7 @@ mmap_free_1 (r)
   else
     mmap_regions = r->next;
   
-  if (munmap (r, r->nbytes_mapped) == -1)
+  if (munmap ((POINTER_TYPE *) r, r->nbytes_mapped) == -1)
     {
       fprintf (stderr, "munmap: %s\n", emacs_strerror (errno));
       return 0;
@@ -4273,7 +4375,7 @@ mmap_enlarge (r, npages)
          p = mmap (region_end, nbytes, PROT_READ | PROT_WRITE,
                    MAP_ANON | MAP_PRIVATE | MAP_FIXED, mmap_fd, 0);
          if (p == MAP_FAILED)
-           fprintf (stderr, "mmap: %s\n", emacs_strerror (errno));
+           ; /* fprintf (stderr, "mmap: %s\n", emacs_strerror (errno)); */
          else if (p != (POINTER_TYPE *) region_end)
            {
              /* Kernels are free to choose a different address.  In
@@ -4526,7 +4628,7 @@ alloc_buffer_text (b, nbytes)
 #elif defined REL_ALLOC
   p = r_alloc ((POINTER_TYPE **) &b->text->beg, nbytes);
 #else
-  p = xmalloc (b->text->beg, nbytes);
+  p = xmalloc (nbytes);
 #endif
   
   if (p == NULL)
@@ -4992,8 +5094,8 @@ don't override it.  This is the same as (default-value\n\
   DEFVAR_PER_BUFFER ("header-line-format",
                     &current_buffer->header_line_format, 
                     Qnil,
-   "Analogous to `mode-line-format', but for a mode line displayed\n\
-at the top of windows.");
+   "Analogous to `mode-line-format', but for the mode line that can be\n\
+displayed at the top of a window.");
   
   DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format, 
                     Qnil, 0);
@@ -5142,7 +5244,8 @@ On other systems, this variable is normally always nil.");
   DEFVAR_PER_BUFFER ("default-directory", &current_buffer->directory,
                     make_number (Lisp_String),
     "Name of default directory of current buffer.  Should end with slash.\n\
-Each buffer has its own value of this variable.");
+Each buffer has its own value of this variable.  To change the\n\
+default directory, use function `cd'.");
 
   DEFVAR_PER_BUFFER ("auto-fill-function", &current_buffer->auto_fill_function,
                     Qnil,
@@ -5220,11 +5323,27 @@ Automatically becomes buffer-local when set in any fashion.");
                     Qnil,
     "Display table that controls display of the contents of current buffer.\n\
 Automatically becomes buffer-local when set in any fashion.\n\
+\n\
+If this variable is nil, the value of `standard-display-table' is used.\n\
+Each window can have its own, overriding display table, see\n\
+`set-window-display-table' and `window-display-table'.\n\
+\n\
 The display table is a char-table created with `make-display-table'.\n\
-The ordinary char-table elements control how to display each possible text\n\
-character.  Each value should be a vector of characters or nil;\n\
-nil means display the character in the default fashion.\n\
-There are six extra slots to control the display of\n\
+A char-table is an array indexed by character codes.  Normal array\n\
+primitives `aref' and `aset' can be used to access elements of a char-table.\n\
+\n\
+Each of the char-table elements control how to display the corresponding\n\
+text character: the element at index C in the table says how to display\n\
+the character whose code is C.  Each element should be a vector of\n\
+characters or nil.  nil means display the character in the default fashion;\n\
+otherwise, the characters from the vector are delivered to the screen\n\
+instead of the original character.\n\
+\n\
+For example, (aset buffer-display-table ?X ?Y) will cause Emacs to display\n\
+a capital Y instead of each X character.\n\
+\n\
+In addition, a char-table has six extra slots to control the display of:\n\
+\n\
   the end of a truncated screen line (extra-slot 0, a single character);\n\
   the end of a continued line (extra-slot 1, a single character);\n\
   the escape character used to display character codes in octal\n\
@@ -5235,9 +5354,8 @@ There are six extra slots to control the display of\n\
     a vector of characters);\n\
   the character used to draw the border between side-by-side windows\n\
     (extra-slot 5, a single character).\n\
-See also the functions `display-table-slot' and `set-display-table-slot'.\n\
-If this variable is nil, the value of `standard-display-table' is used.\n\
-Each window can have its own, overriding display table.");
+\n\
+See also the functions `display-table-slot' and `set-display-table-slot'.");
 #endif
   DEFVAR_PER_BUFFER ("buffer-display-table", &current_buffer->display_table,
                     Qnil, 0);