Finish making it fit Emacs conventions. Add autoloads.
[bpt/emacs.git] / src / buffer.c
index cdf6d4a..d4c60f9 100644 (file)
@@ -364,11 +364,17 @@ The value is never nil.")
   BUF_OVERLAY_MODIFF (b) = 1;
   BUF_SAVE_MODIFF (b) = 1;
   BUF_INTERVALS (b) = 0;
+  BUF_UNCHANGED_MODIFIED (b) = 1;
+  BUF_OVERLAY_UNCHANGED_MODIFIED (b) = 1;
+  BUF_END_UNCHANGED (b) = 0;
+  BUF_BEG_UNCHANGED (b) = 0;
   *(BUF_GPT_ADDR (b)) = *(BUF_Z_ADDR (b)) = 0; /* Put an anchor '\0'.  */
 
   b->newline_cache = 0;
   b->width_run_cache = 0;
   b->width_table = Qnil;
+  b->minibuffer_prompt_length = Qnil;
+  b->prevent_redisplay_optimizations_p = 1;
 
   /* Put this on the chain of all buffers including killed ones.  */
   b->next = all_buffers;
@@ -447,6 +453,7 @@ NAME should be a string which is not the name of an existing buffer.")
   b->newline_cache = 0;
   b->width_run_cache = 0;
   b->width_table = Qnil;
+  b->minibuffer_prompt_length = Qnil;
 
   /* Put this on the chain of all buffers including killed ones.  */
   b->next = all_buffers;
@@ -519,7 +526,8 @@ reset_buffer (b)
   XSETFASTINT (b->save_length, 0);
   b->last_window_start = 1;
   /* It is more conservative to start out "changed" than "unchanged".  */
-  b->clip_changed = 1;
+  b->clip_changed = 0;
+  b->prevent_redisplay_optimizations_p = 1;
   b->backed_up = Qnil;
   b->auto_save_modified = 0;
   b->auto_save_failure_time = -1;
@@ -1215,6 +1223,7 @@ with SIGHUP.")
       b->width_run_cache = 0;
     }
   b->width_table = Qnil;
+  b->minibuffer_prompt_length = Qnil;
   UNBLOCK_INPUT;
   b->undo_list = Qnil;
 
@@ -1311,26 +1320,30 @@ the current buffer's major mode.")
   return unbind_to (count, Qnil);
 }
 
-DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "BSwitch to buffer: ",
-  "Select buffer BUFFER in the current window.\n\
-BUFFER may be a buffer or a buffer name.\n\
-Optional second arg NORECORD non-nil means\n\
-do not put this buffer at the front of the list of recently selected ones.\n\
-\n\
-WARNING: This is NOT the way to work on another buffer temporarily\n\
-within a Lisp program!  Use `set-buffer' instead.  That avoids messing with\n\
-the window-buffer correspondences.")
-  (buffer, norecord)
-     Lisp_Object buffer, norecord;
+/* If switching buffers in WINDOW would be an error, return
+   a C string saying what the error would be.  */
+
+char *
+no_switch_window (window)
+     Lisp_Object window;
 {
-  register Lisp_Object buf;
   Lisp_Object tem;
-
-  if (EQ (minibuf_window, selected_window))
-    error ("Cannot switch buffers in minibuffer window");
-  tem = Fwindow_dedicated_p (selected_window);
+  if (EQ (minibuf_window, window))
+    return "Cannot switch buffers in minibuffer window";
+  tem = Fwindow_dedicated_p (window);
   if (!NILP (tem))
-    error ("Cannot switch buffers in a dedicated window");
+    return "Cannot switch buffers in a dedicated window";
+  return NULL;
+}
+
+/* Switch to buffer BUFFER in the selected window.
+   If NORECORD is non-nil, don't call record_buffer.  */
+
+Lisp_Object
+switch_to_buffer_1 (buffer, norecord)
+     Lisp_Object buffer, norecord;
+{
+  register Lisp_Object buf;
 
   if (NILP (buffer))
     buf = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
@@ -1355,6 +1368,26 @@ the window-buffer correspondences.")
   return buf;
 }
 
+DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2, "BSwitch to buffer: ",
+  "Select buffer BUFFER in the current window.\n\
+BUFFER may be a buffer or a buffer name.\n\
+Optional second arg NORECORD non-nil means\n\
+do not put this buffer at the front of the list of recently selected ones.\n\
+\n\
+WARNING: This is NOT the way to work on another buffer temporarily\n\
+within a Lisp program!  Use `set-buffer' instead.  That avoids messing with\n\
+the window-buffer correspondences.")
+  (buffer, norecord)
+     Lisp_Object buffer, norecord;
+{
+  char *err;
+
+  err = no_switch_window (selected_window);
+  if (err) error (err);
+
+  return switch_to_buffer_1 (buffer, norecord);
+}
+
 DEFUN ("pop-to-buffer", Fpop_to_buffer, Spop_to_buffer, 1, 3, 0,
   "Select buffer BUFFER in some window, preferably a different one.\n\
 If BUFFER is nil, then some other buffer is chosen.\n\
@@ -1397,21 +1430,21 @@ DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
   return buf;
 }
 \f
-/* Set the current buffer to B.  */
+/* Set the current buffer to B.
+
+   We previously set windows_or_buffers_changed here to invalidate
+   global unchanged information in beg_unchanged and end_unchanged.
+   This is no longer necessary because we now compute unchanged
+   information on a buffer-basis.  Every action affecting other
+   windows than the selected one requires a select_window at some
+   time, and that increments windows_or_buffers_changed.  */
 
 void
 set_buffer_internal (b)
      register struct buffer *b;
 {
-  register struct buffer *old_buf;
-  register Lisp_Object tail, valcontents;
-  Lisp_Object tem;
-
-  if (current_buffer == b)
-    return;
-
-  windows_or_buffers_changed = 1;
-  set_buffer_internal_1 (b);
+  if (current_buffer != b)
+    set_buffer_internal_1 (b);
 }
 
 /* Set the current buffer to B, and do not set windows_or_buffers_changed.
@@ -1715,7 +1748,7 @@ advance_to_char_boundary (byte_pos)
   c = FETCH_BYTE (byte_pos);
   if (! CHAR_HEAD_P (c))
     {
-      /* We should advance BYTE_POS only when C is a constituen of a
+      /* We should advance BYTE_POS only when C is a constituent of a
          multibyte sequence.  */
       DEC_POS (byte_pos);
       INC_POS (byte_pos);
@@ -1973,7 +2006,8 @@ swap_out_buffer_local_variables (b)
    Store in *NEXT_PTR the next position after POS where an overlay starts,
      or ZV if there are no more overlays.
    Store in *PREV_PTR the previous position before POS where an overlay ends,
-     or BEGV if there are no previous overlays.
+     or where an overlay starts which ends at or after POS;
+     or BEGV if there are no such overlays.
    NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
 
    *VEC_PTR and *LEN_PTR should contain a valid vector and size
@@ -2018,9 +2052,13 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
            prev = endpos;
          break;
        }
+      startpos = OVERLAY_POSITION (start);
+      /* This one ends at or after POS
+        so its start counts for PREV_PTR if it's before POS.  */
+      if (prev < startpos && startpos < pos)
+       prev = startpos;
       if (endpos == pos)
        continue;
-      startpos = OVERLAY_POSITION (start);
       if (startpos <= pos)
        {
          if (idx == len)
@@ -2029,7 +2067,11 @@ overlays_at (pos, 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;
                }
@@ -2071,6 +2113,8 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
              if (extend)
                {
                  *len_ptr = len *= 2;
+                 if (len == 0)
+                   len = *len_ptr = 4;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
                }
@@ -2081,9 +2125,14 @@ overlays_at (pos, extend, vec_ptr, len_ptr, next_ptr, prev_ptr)
          if (!inhibit_storing)
            vec[idx] = overlay;
          idx++;
+
+         if (startpos < pos && startpos > prev)
+           prev = startpos;
        }
       else if (endpos < pos && endpos > prev)
        prev = endpos;
+      else if (endpos == pos && startpos > prev)
+       prev = startpos;
     }
 
   if (next_ptr)
@@ -3045,28 +3094,11 @@ modify_overlay (buf, start, end)
      we must do other windows.  */
   if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
     windows_or_buffers_changed = 1;
-  /* If it's not current, we can't use beg_unchanged, end_unchanged for it.  */
-  else if (buf != current_buffer)
-    windows_or_buffers_changed = 1;
   /* If multiple windows show this buffer, we must do other windows.  */
   else if (buffer_shared > 1)
     windows_or_buffers_changed = 1;
   else
-    {
-      if (unchanged_modified == MODIFF
-         && overlay_unchanged_modified == OVERLAY_MODIFF)
-       {
-         beg_unchanged = start - BEG;
-         end_unchanged = Z - end;
-       }
-      else
-       {
-         if (Z - end < end_unchanged)
-           end_unchanged = Z - end;
-         if (start - BEG < beg_unchanged)
-           beg_unchanged = start - BEG;
-       }
-    }
+    BUF_COMPUTE_UNCHANGED (buf, start, end);
 
   ++BUF_OVERLAY_MODIFF (buf);
 }
@@ -3382,39 +3414,10 @@ If there are no more overlay boundaries before POS, return (point-min).")
 
   /* Put all the overlays we want in a vector in overlay_vec.
      Store the length in len.
-     prevpos gets the position of an overlay end.  */
+     prevpos gets the position of the previous change.  */
   noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
                           (int *) 0, &prevpos);
 
-  /* If any of these overlays starts after prevpos,
-     maybe use its starting point instead.  */
-  for (i = 0; i < noverlays; i++)
-    {
-      Lisp_Object ostart;
-      int ostartpos;
-
-      ostart = OVERLAY_START (overlay_vec[i]);
-      ostartpos = OVERLAY_POSITION (ostart);
-      if (ostartpos > prevpos && ostartpos < XINT (pos))
-       prevpos = ostartpos;
-    }
-
-  /* If any overlay ends at pos, consider its starting point too.  */
-  for (tail = current_buffer->overlays_before;
-       GC_CONSP (tail);
-       tail = XCONS (tail)->cdr)
-    {
-      Lisp_Object overlay, ostart;
-      int ostartpos;
-
-      overlay = XCONS (tail)->car;
-
-      ostart = OVERLAY_START (overlay);
-      ostartpos = OVERLAY_POSITION (ostart);
-      if (ostartpos > prevpos && ostartpos < XINT (pos))
-       prevpos = ostartpos;
-    }
-
   xfree (overlay_vec);
   return make_number (prevpos);
 }
@@ -3847,6 +3850,7 @@ init_buffer_once ()
 
   /* real setup is done in loaddefs.el */
   buffer_defaults.mode_line_format = build_string ("%-");
+  buffer_defaults.header_line_format = Qnil;
   buffer_defaults.abbrev_mode = Qnil;
   buffer_defaults.overwrite_mode = Qnil;
   buffer_defaults.case_fold_search = Qt;
@@ -3879,6 +3883,9 @@ init_buffer_once ()
   buffer_defaults.cache_long_line_scans = Qnil;
   buffer_defaults.file_truename = Qnil;
   XSETFASTINT (buffer_defaults.display_count, 0);
+  buffer_defaults.indicate_empty_lines = Qnil;
+  buffer_defaults.scroll_up_aggressively = Qnil;
+  buffer_defaults.scroll_down_aggressively = Qnil;
   buffer_defaults.display_time = Qnil;
 
   /* Assign the local-flags to the slots that have default values.
@@ -3937,6 +3944,12 @@ init_buffer_once ()
   XSETFASTINT (buffer_local_flags.buffer_file_coding_system, 0x80000);
   /* Make this one a permanent local.  */
   buffer_permanent_local_flags |= 0x80000;
+  XSETFASTINT (buffer_local_flags.left_margin_width, 0x100000);
+  XSETFASTINT (buffer_local_flags.right_margin_width, 0x200000);
+  XSETFASTINT (buffer_local_flags.indicate_empty_lines, 0x400000);
+  XSETFASTINT (buffer_local_flags.scroll_up_aggressively, 0x800000);
+  XSETFASTINT (buffer_local_flags.scroll_down_aggressively, 0x1000000);
+  XSETFASTINT (buffer_local_flags.header_line_format, 0x2000000);
   
   Vbuffer_alist = Qnil;
   current_buffer = 0;
@@ -4084,6 +4097,11 @@ syms_of_buffer ()
     "Default value of `mode-line-format' for buffers that don't override it.\n\
 This is the same as (default-value 'mode-line-format).");
 
+  DEFVAR_LISP_NOPRO ("default-header-line-format",
+                    &buffer_defaults.header_line_format,
+    "Default value of `header-line-format' for buffers that don't override it.\n\
+This is the same as (default-value 'header-line-format).");
+
   DEFVAR_LISP_NOPRO ("default-abbrev-mode",
              &buffer_defaults.abbrev_mode,
     "Default value of `abbrev-mode' for buffers that do not override it.\n\
@@ -4101,7 +4119,7 @@ This is the same as (default-value 'ctl-arrow).");
  
    DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
              &buffer_defaults.enable_multibyte_characters,
-     "Default value of `enable-multibyte-characters' for buffers not overriding it.\n\
+     "*Default value of `enable-multibyte-characters' for buffers not overriding it.\n\
 This is the same as (default-value 'enable-multibyte-characters).");
  
    DEFVAR_LISP_NOPRO ("default-buffer-file-coding-system",
@@ -4142,6 +4160,39 @@ This is the same as (default-value 'buffer-file-type).\n\
 The file type is nil for text, t for binary.");
 #endif
 
+  DEFVAR_LISP_NOPRO ("default-left-margin-width",
+             &buffer_defaults.left_margin_width,
+    "Default value of `left-margin-width' for buffers that don't override it.\n\
+This is the same as (default-value 'left-margin-width).");
+
+  DEFVAR_LISP_NOPRO ("default-right-margin-width",
+             &buffer_defaults.right_margin_width,
+    "Default value of `right_margin_width' for buffers that don't override it.\n\
+This is the same as (default-value 'right-margin-width).");
+  
+  DEFVAR_LISP_NOPRO ("default-indicate-empty-lines",
+             &buffer_defaults.indicate_empty_lines,
+    "Default value of `indicate-empty-lines' for buffers that don't override it.\n\
+This is the same as (default-value 'indicate-empty-lines).");
+  
+  DEFVAR_LISP_NOPRO ("default-scroll-up-aggressively",
+             &buffer_defaults.scroll_up_aggressively,
+    "Default value of `scroll-up-aggressively' for buffers that\n\
+don't override it.  This is the same as (default-value\n\
+'scroll-up-aggressively).");
+  
+  DEFVAR_LISP_NOPRO ("default-scroll-down-aggressively",
+             &buffer_defaults.scroll_down_aggressively,
+    "Default value of `scroll-down-aggressively' for buffers that\n\
+don't override it.  This is the same as (default-value\n\
+'scroll-down-aggressively).");
+  
+  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.");
+  
   DEFVAR_PER_BUFFER ("mode-line-format", &current_buffer->mode_line_format, 
                     Qnil, 0);
 
@@ -4151,7 +4202,8 @@ The file type is nil for text, t for binary.");
     Qnil,
     "Template for displaying mode line for current buffer.\n\
 Each buffer has its own value of this variable.\n\
-Value may be a string, a symbol or a list or cons cell.\n\
+Value may be nil, a string, a symbol or a list or cons cell.\n\
+A value of nil means don't display a mode line.\n\
 For a symbol, its value is used (but it is ignored if t or nil).\n\
  A string appearing directly as the value of a symbol is processed verbatim\n\
  in that the %-constructs below are not recognized.\n\
@@ -4382,6 +4434,39 @@ Each window can have its own, overriding display table.");
   DEFVAR_PER_BUFFER ("buffer-display-table", &current_buffer->display_table,
                     Qnil, 0);
 
+  DEFVAR_PER_BUFFER ("left-margin-width", &current_buffer->left_margin_width,
+                    Qnil,
+    "*Width of left marginal area for display of a buffer.\n\
+Automatically becomes buffer-local when set in any fashion.\n\
+A value of nil means no marginal area.");
+  
+  DEFVAR_PER_BUFFER ("right-margin-width", &current_buffer->right_margin_width,
+                    Qnil,
+    "*Width of right marginal area for display of a buffer.\n\
+Automatically becomes buffer-local when set in any fashion.\n\
+A value of nil means no marginal area.");
+  
+  DEFVAR_PER_BUFFER ("indicate-empty-lines",
+                    &current_buffer->indicate_empty_lines, Qnil,
+    "*Non-nil means visually indicate lines not displaying text.\n\
+Automatically becomes buffer-local when set in any fashion.\n");
+  
+  DEFVAR_PER_BUFFER ("scroll-up-aggressively",
+                    &current_buffer->scroll_up_aggressively, Qnil,
+    "*If a number, scroll display up aggressively.\n\
+If scrolling a window because point is above the window start, choose\n\
+a new window start so that point ends up that fraction of the window's\n\
+height from the bottom of the window.\n\
+Automatically becomes buffer-local when set in any fashion.");
+  
+  DEFVAR_PER_BUFFER ("scroll-down-aggressively",
+                    &current_buffer->scroll_down_aggressively, Qnil,
+    "*If a number, scroll display down aggressively.\n\
+If scrolling a window because point is below the window end, choose\n\
+a new window start so that point ends up that fraction of the window's\n\
+height from the top of the window.\n\
+Automatically becomes buffer-local when set in any fashion.");
+  
 /*DEFVAR_LISP ("debug-check-symbol", &Vcheck_symbol,
     "Don't ask.");
 */