(Qbar, Qhbar, Qbox, Qhollow, Vblink_cursor_alist):
[bpt/emacs.git] / src / xdisp.c
index 2f8bc65..e7656d4 100644 (file)
@@ -227,6 +227,9 @@ Lisp_Object Qgrow_only;
 Lisp_Object Qinhibit_eval_during_redisplay;
 Lisp_Object Qbuffer_position, Qposition, Qobject;
 
+/* Cursor shapes */
+Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
+
 Lisp_Object Qrisky_local_variable;
 
 /* Holds the list (error).  */
@@ -531,9 +534,19 @@ static int message_cleared_p;
 /* Non-zero means we want a hollow cursor in windows that are not
    selected.  Zero means there's no cursor in such windows.  */
 
-int cursor_in_non_selected_windows;
+Lisp_Object Vcursor_in_non_selected_windows;
 Lisp_Object Qcursor_in_non_selected_windows;
 
+/* Specifies the desired cursor-type to use to show the blinking
+   cursor off state and cursor shown in non-selected windows.
+   t means to use the default.  */
+
+Lisp_Object Valternate_cursor_type;
+Lisp_Object Qalternate_cursor_type;
+
+/* How to blink the default frame cursor off.  */
+Lisp_Object Vblink_cursor_alist;
+
 /* A scratch glyph row with contents used for generating truncation
    glyphs.  Also used in direct_output_for_insert.  */
 
@@ -690,6 +703,28 @@ enum move_it_result
   MOVE_NEWLINE_OR_CR
 };
 
+/* This counter is used to clear the face cache every once in a while
+   in redisplay_internal.  It is incremented for each redisplay.
+   Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
+   cleared.  */
+
+#define CLEAR_FACE_CACHE_COUNT 500
+static int clear_face_cache_count;
+
+/* Record the previous terminal frame we displayed.  */
+
+static struct frame *previous_terminal_frame;
+
+/* Non-zero while redisplay_internal is in progress.  */
+
+int redisplaying_p;
+
+/* Non-zero means don't free realized faces.  Bound while freeing
+   realized faces is dangerous because glyph matrices might still
+   reference them.  */
+
+int inhibit_free_realized_faces;
+Lisp_Object Qinhibit_free_realized_faces;
 
 \f
 /* Function prototypes.  */
@@ -713,7 +748,7 @@ static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
 static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
 static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
 static void store_frame_title_char P_ ((char));
-static int store_frame_title P_ ((unsigned char *, int, int));
+static int store_frame_title P_ ((const unsigned char *, int, int));
 static void x_consider_frame_title P_ ((Lisp_Object));
 static void handle_stop P_ ((struct it *));
 static int tool_bar_lines_needed P_ ((struct frame *));
@@ -732,7 +767,7 @@ static int display_echo_area P_ ((struct window *));
 static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
 static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
 static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
-static int string_char_and_length P_ ((unsigned char *, int, int *));
+static int string_char_and_length P_ ((const unsigned char *, int, int *));
 static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
                                             struct text_pos));
 static int compute_window_start_on_continuation_line P_ ((struct window *));
@@ -1149,7 +1184,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
 
 static INLINE int
 string_char_and_length (str, maxlen, len)
-     unsigned char *str;
+     const unsigned char *str;
      int maxlen, *len;
 {
   int c;
@@ -1180,7 +1215,7 @@ string_pos_nchars_ahead (pos, string, nchars)
   if (STRING_MULTIBYTE (string))
     {
       int rest = SBYTES (string) - BYTEPOS (pos);
-      unsigned char *p = SDATA (string) + BYTEPOS (pos);
+      const unsigned char *p = SDATA (string) + BYTEPOS (pos);
       int len;
 
       while (nchars--)
@@ -1328,7 +1363,7 @@ safe_eval (sexpr)
     val = Qnil;
   else
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
 
       GCPRO1 (sexpr);
@@ -1360,7 +1395,7 @@ safe_call (nargs, args)
     val = Qnil;
   else
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
 
       GCPRO1 (args[0]);
@@ -1503,8 +1538,9 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* If face attributes have been changed since the last redisplay,
      free realized faces now because they depend on face definitions
-     that might have changed.  */
-  if (face_change_count)
+     that might have changed.  Don't free faces while there might be 
+     desired matrices pending which reference these faces.  */
+  if (face_change_count && !inhibit_free_realized_faces)
     {
       face_change_count = 0;
       free_all_realized_faces (Qnil);
@@ -1878,8 +1914,8 @@ init_from_display_pos (it, w, pos)
 
   for (i = 0; i < it->n_overlay_strings; ++i)
     {
-      char *s = SDATA (it->overlay_strings[i]);
-      char *e = s + SBYTES (it->overlay_strings[i]);
+      const char *s = SDATA (it->overlay_strings[i]);
+      const char *e = s + SBYTES (it->overlay_strings[i]);
 
       while (s < e && *s != '\n')
        ++s;
@@ -2241,7 +2277,7 @@ handle_fontified_prop (it)
          prop = Fget_char_property (pos, Qfontified, Qnil),
          NILP (prop)))
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       Lisp_Object val;
 
       val = Vfontification_functions;
@@ -2485,7 +2521,7 @@ face_before_or_after_it_pos (it, before_p)
         suitable for unibyte text if IT->string is unibyte.  */
       if (STRING_MULTIBYTE (it->string))
        {
-         unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
+         const unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
          int rest = SBYTES (it->string) - BYTEPOS (pos);
          int c, len;
          struct face *face = FACE_FROM_ID (it->f, face_id);
@@ -2528,7 +2564,7 @@ face_before_or_after_it_pos (it, before_p)
         suitable for unibyte text if current_buffer is unibyte.  */
       if (it->multibyte_p)
        {
-         int c = FETCH_MULTIBYTE_CHAR (CHARPOS (pos));
+         int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
          struct face *face = FACE_FROM_ID (it->f, face_id);
          face_id = FACE_FOR_CHAR (it->f, face, c);
        }
@@ -2864,7 +2900,7 @@ handle_single_display_prop (it, prop, object, position,
 
   if (!NILP (form) && !EQ (form, Qt))
     {
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
 
       /* Bind `object' to the object having the `display' property, a
@@ -2935,7 +2971,7 @@ handle_single_display_prop (it, prop, object, position,
              /* Evaluate IT->font_height with `height' bound to the
                 current specified height to get the new height.  */
              Lisp_Object value;
-             int count = BINDING_STACK_SIZE ();
+             int count = SPECPDL_INDEX ();
 
              specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
              value = safe_eval (it->font_height);
@@ -3698,7 +3734,7 @@ get_overlay_strings (it, charpos)
       it->stop_charpos = 0;
       xassert (STRINGP (it->string));
       it->end_charpos = SCHARS (it->string);
-      it->multibyte_p = SMBP (it->string);
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
       it->method = next_element_from_string;
     }
   else
@@ -3849,14 +3885,14 @@ forward_to_next_line_start (it, skipped_p)
        n += STRINGP (it->string) ? 0 : 1)
     {
       if (!get_next_display_element (it))
-       break;
+       return 0;
       newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
       set_iterator_to_next (it, 0);
     }
 
   /* If we didn't find a newline near enough, see if we can use a
      short-cut.  */
-  if (n == MAX_NEWLINE_DISTANCE)
+  if (!newline_found_p)
     {
       int start = IT_CHARPOS (*it);
       int limit = find_next_newline_no_quit (start, 1);
@@ -3920,7 +3956,7 @@ back_to_previous_visible_line_start (it)
         are invisible.  */
       if (it->selective > 0
          && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
-                               (float) it->selective)) /* iftc */
+                               (double) it->selective)) /* iftc */
        visible_p = 0;
       else
        {
@@ -3980,7 +4016,7 @@ reseat_at_next_visible_line_start (it, on_newline_p)
   if (it->selective > 0)
     while (IT_CHARPOS (*it) < ZV
           && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
-                                (float) it->selective)) /* iftc */
+                                (double) it->selective)) /* iftc */
       {
        xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
        newline_found_p = forward_to_next_line_start (it, &skipped_p);
@@ -4238,14 +4274,22 @@ get_next_display_element (it)
             the translation.  This could easily be changed but I
             don't believe that it is worth doing.
 
-            Non-printable multibyte characters are also translated
-            octal form.  */
-         else if ((it->c < ' '
+            If it->multibyte_p is nonzero, eight-bit characters and
+            non-printable multibyte characters are also translated to
+            octal form.
+
+            If it->multibyte_p is zero, eight-bit characters that
+            don't have corresponding multibyte char code are also
+            translated to octal form.  */
+         else if (((it->c < ' ' || it->c == 127)
                    && (it->area != TEXT_AREA
                        || (it->c != '\n' && it->c != '\t')))
-                  || (it->c >= 127
-                      && it->len == 1)
-                  || !CHAR_PRINTABLE_P (it->c))
+                  || (it->multibyte_p
+                      ? ((it->c >= 127
+                          && it->len == 1)
+                         || !CHAR_PRINTABLE_P (it->c))
+                      : (it->c >= 128
+                         && it->c == unibyte_char_to_multibyte (it->c))))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -4612,7 +4656,8 @@ next_element_from_string (it)
       else if (STRING_MULTIBYTE (it->string))
        {
          int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
-         unsigned char *s = SDATA (it->string) + IT_STRING_BYTEPOS (*it);
+         const unsigned char *s = (SDATA (it->string)
+                                   + IT_STRING_BYTEPOS (*it));
          it->c = string_char_and_length (s, remaining, &it->len);
        }
       else
@@ -4641,7 +4686,8 @@ next_element_from_string (it)
       else if (STRING_MULTIBYTE (it->string))
        {
          int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
-         unsigned char *s = SDATA (it->string) + IT_STRING_BYTEPOS (*it);
+         const unsigned char *s = (SDATA (it->string)
+                                   + IT_STRING_BYTEPOS (*it));
          it->c = string_char_and_length (s, maxlen, &it->len);
        }
       else
@@ -4873,7 +4919,7 @@ next_element_from_buffer (it)
                  && IT_CHARPOS (*it) + 1 < ZV
                  && indented_beyond_p (IT_CHARPOS (*it) + 1,
                                        IT_BYTEPOS (*it) + 1,
-                                       (float) it->selective)) /* iftc */
+                                       (double) it->selective)) /* iftc */
                {
                  success_p = next_element_from_ellipsis (it);
                  it->dpvec_char_len = -1;
@@ -5653,9 +5699,12 @@ message_log_maybe_newline ()
 
 void
 message_dolog (m, nbytes, nlflag, multibyte)
-     char *m;
+     const char *m;
      int nbytes, nlflag, multibyte;
 {
+  if (!NILP (Vmemory_full))
+    return;
+
   if (!NILP (Vmessage_log_max))
     {
       struct buffer *oldbuf;
@@ -5864,7 +5913,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
 
 void
 message2 (m, nbytes, multibyte)
-     char *m;
+     const char *m;
      int nbytes;
      int multibyte;
 {
@@ -5880,7 +5929,7 @@ message2 (m, nbytes, multibyte)
 
 void
 message2_nolog (m, nbytes, multibyte)
-     char *m;
+     const char *m;
      int nbytes;
 {
   struct frame *sf = SELECTED_FRAME ();
@@ -6099,9 +6148,9 @@ message_with_string (m, string, log)
          message = Fformat (2, args);
 
          if (log)
-           message3 (message, SBYTES (message), SMBP (message));
+           message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
          else
-           message3_nolog (message, SBYTES (message), SMBP (message));
+           message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
 
          UNGCPRO;
 
@@ -6216,8 +6265,8 @@ update_echo_area ()
 }
 
 
-/* Make sure echo area buffers in echo_buffers[] are life.  If they
-   aren't, make new ones.  */
+/* Make sure echo area buffers in `echo_buffers' are live.
+   If they aren't, make new ones.  */
 
 static void
 ensure_echo_area_buffers ()
@@ -6271,7 +6320,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
 {
   Lisp_Object buffer;
   int this_one, the_other, clear_buffer_p, rc;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
 
   /* If buffers aren't live, make new ones.  */
   ensure_echo_area_buffers ();
@@ -6446,8 +6495,9 @@ setup_echo_area_for_printing (multibyte_p)
 
       if (Z > BEG)
        {
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
          specbind (Qinhibit_read_only, Qt);
+         /* Note that undo recording is always disabled.  */
          del_range (BEG, Z);
          unbind_to (count, Qnil);
        }
@@ -6820,7 +6870,7 @@ restore_message ()
   xassert (CONSP (Vmessage_stack));
   msg = XCAR (Vmessage_stack);
   if (STRINGP (msg))
-    message3_nolog (msg, SBYTES (msg), SMBP (msg));
+    message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
   else
     message3_nolog (msg, 0, 0);
 }
@@ -6900,7 +6950,7 @@ truncate_message_1 (nchars, a2, a3, a4)
 
 void
 set_message (s, string, nbytes, multibyte_p)
-     char *s;
+     const char *s;
      Lisp_Object string;
      int nbytes;
 {
@@ -6926,7 +6976,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
      Lisp_Object a2;
      EMACS_INT nbytes, multibyte_p;
 {
-  char *s = (char *) a1;
+  const char *s = (const char *) a1;
   Lisp_Object string = a2;
 
   xassert (BEG == Z);
@@ -6980,7 +7030,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
        {
          /* Convert from single-byte to multi-byte.  */
          int i, c, n;
-         unsigned char *msg = (unsigned char *) s;
+         const unsigned char *msg = (const unsigned char *) s;
          unsigned char str[MAX_MULTIBYTE_LENGTH];
 
          /* Convert a single-byte string to multibyte.  */
@@ -7126,7 +7176,7 @@ echo_area_display (update_frame_p)
              /* Must update other windows.  Likewise as in other
                 cases, don't let this update be interrupted by
                 pending input.  */
-             int count = BINDING_STACK_SIZE ();
+             int count = SPECPDL_INDEX ();
              specbind (Qredisplay_dont_pause, Qt);
              windows_or_buffers_changed = 1;
              redisplay_internal (0);
@@ -7218,7 +7268,7 @@ store_frame_title_char (c)
 
 static int
 store_frame_title (str, field_width, precision)
-     unsigned char *str;
+     const unsigned char *str;
      int field_width, precision;
 {
   int n = 0;
@@ -7359,7 +7409,7 @@ prepare_menu_bars ()
   if (all_windows)
     {
       Lisp_Object tail, frame;
-      int count = BINDING_STACK_SIZE ();
+      int count = SPECPDL_INDEX ();
 
       record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
 
@@ -7477,7 +7527,7 @@ update_menu_bar (f, save_match_data)
              != !NILP (w->region_showing)))
        {
          struct buffer *prev = current_buffer;
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
 
          specbind (Qinhibit_menubar_update, Qt);
 
@@ -7571,7 +7621,7 @@ update_tool_bar (f, save_match_data)
              != !NILP (w->region_showing)))
        {
          struct buffer *prev = current_buffer;
-         int count = BINDING_STACK_SIZE ();
+         int count = SPECPDL_INDEX ();
 
          /* Set current_buffer to the buffer of the selected
             window of the frame, so that we get the right local
@@ -8282,23 +8332,6 @@ debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 #endif /* GLYPH_DEBUG */
 
 
-/* This counter is used to clear the face cache every once in a while
-   in redisplay_internal.  It is incremented for each redisplay.
-   Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
-   cleared.  */
-
-#define CLEAR_FACE_CACHE_COUNT 500
-static int clear_face_cache_count;
-
-/* Record the previous terminal frame we displayed.  */
-
-static struct frame *previous_terminal_frame;
-
-/* Non-zero while redisplay_internal is in progress.  */
-
-int redisplaying_p;
-
-
 /* Value is non-zero if all changes in window W, which displays
    current_buffer, are in the text between START and END.  START is a
    buffer position, END is given as a distance from Z.  Used in
@@ -8416,9 +8449,7 @@ reconsider_clip_changes (w, b)
      struct window *w;
      struct buffer *b;
 {
-  if (b->prevent_redisplay_optimizations_p)
-    b->clip_changed = 1;
-  else if (b->clip_changed
+  if (b->clip_changed
           && !NILP (w->window_end_valid)
           && w->current_matrix->buffer == b
           && w->current_matrix->zv == BUF_ZV (b)
@@ -8504,9 +8535,10 @@ redisplay_internal (preserve_echo_area)
 
   /* Record a function that resets redisplaying_p to its old value
      when we leave this function.  */
-  count = BINDING_STACK_SIZE ();
+  count = SPECPDL_INDEX ();
   record_unwind_protect (unwind_redisplay, make_number (redisplaying_p));
   ++redisplaying_p;
+  specbind (Qinhibit_free_realized_faces, Qnil);
 
  retry:
   pause = 0;
@@ -8685,6 +8717,7 @@ redisplay_internal (preserve_echo_area)
       && CHARPOS (tlbufpos) > 0
       && NILP (w->update_mode_line)
       && !current_buffer->clip_changed
+      && !current_buffer->prevent_redisplay_optimizations_p
       && FRAME_VISIBLE_P (XFRAME (w->frame))
       && !FRAME_OBSCURED_P (XFRAME (w->frame))
       /* Make sure recorded data applies to current buffer, etc.  */
@@ -8997,8 +9030,8 @@ redisplay_internal (preserve_echo_area)
                                 redisplay_window_error);
 
       /* Compare desired and current matrices, perform output.  */
+      
     update:
-
       /* If fonts changed, display again.  */
       if (fonts_changed_p)
        goto retry;
@@ -9123,8 +9156,7 @@ redisplay_internal (preserve_echo_area)
   if (windows_or_buffers_changed && !pause)
     goto retry;
 
- end_of_redisplay:;
-
+ end_of_redisplay:
   unbind_to (count, Qnil);
 }
 
@@ -9160,8 +9192,9 @@ redisplay_preserve_echo_area (from_where)
 
 
 /* Function registered with record_unwind_protect in
-   redisplay_internal.  Clears the flag indicating that a redisplay is
-   in progress.  */
+   redisplay_internal.  Reset redisplaying_p to the value it had
+   before redisplay_internal was called, and clear
+   prevent_freeing_realized_faces_p.  */
 
 static Lisp_Object
 unwind_redisplay (old_redisplaying_p)
@@ -9470,10 +9503,12 @@ run_window_scroll_functions (window, startp)
 }
 
 
-/* Modify the desired matrix of window W and W->vscroll so that the
-   line containing the cursor is fully visible.
-   A value of 1 means there is nothing to be done or we did it.
-   A value of 0 causes redisplay.  */
+/* Make sure the line containing the cursor is fully visible.
+   A value of 1 means there is nothing to be done.
+   (Either the line is fully visible, or it cannot be made so,
+   or we cannot tell.)
+   A value of 0 means the caller should do scrolling
+   as if point had gone off the screen.  */
 
 static int
 make_cursor_line_fully_visible (w)
@@ -9501,6 +9536,13 @@ make_cursor_line_fully_visible (w)
   if (row->height >= window_height)
     return 1;
 
+  return 0;
+
+#if 0
+  /* This code used to try to scroll the window just enough to make
+     the line visible.  It returned 0 to say that the caller should
+     allocate larger glyph matrices.  */
+
   if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
     {
       int dy = row->height - row->visible_height;
@@ -9532,6 +9574,7 @@ make_cursor_line_fully_visible (w)
     }
 
   return 1;
+#endif /* 0 */
 }
 
 
@@ -9628,6 +9671,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     {
       int y0;
 
+    too_near_end:
       /* Point is in the scroll margin at the bottom of the window, or
         below.  Compute a new window start that makes point visible.  */
 
@@ -9748,13 +9792,11 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
          || BEG_UNCHANGED < CHARPOS (startp))
        w->base_line_number = Qnil;
 
-      /* If cursor ends up on a partially visible line, shift display
-        lines up or down.  If that fails because we need larger
-        matrices, give up.  */
-      if (!make_cursor_line_fully_visible (w))
-       rc = SCROLLING_NEED_LARGER_MATRICES;
-      else
-       rc = SCROLLING_SUCCESS;
+      /* If cursor ends up on a partially visible line,
+        treat that as being off the bottom of the screen.  */
+      if (! make_cursor_line_fully_visible (w))
+       goto too_near_end;
+      rc = SCROLLING_SUCCESS;
     }
 
   return rc;
@@ -10043,7 +10085,7 @@ try_cursor_movement (window, startp, scroll_step)
                  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
                  try_window (window, startp);
                  if (!make_cursor_line_fully_visible (w))
-                   rc = CURSOR_MOVEMENT_NEED_LARGER_MATRICES;
+                   rc = CURSOR_MOVEMENT_MUST_SCROLL;
                  else
                    rc = CURSOR_MOVEMENT_SUCCESS;
                }
@@ -10080,9 +10122,13 @@ redisplay_window (window, just_this_one_p)
   struct it it;
   /* Record it now because it's overwritten.  */
   int current_matrix_up_to_date_p = 0;
+  /* This is less strict than current_matrix_up_to_date_p.
+     It indictes that the buffer contents and narrowing are unchanged.  */
+  int buffer_unchanged_p = 0;
   int temp_scroll_step = 0;
-  int count = BINDING_STACK_SIZE ();
+  int count = SPECPDL_INDEX ();
   int rc;
+  int centering_position;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
   opoint = lpoint;
@@ -10100,7 +10146,8 @@ redisplay_window (window, just_this_one_p)
   /* Has the mode line to be updated?  */
   update_mode_line = (!NILP (w->update_mode_line)
                      || update_mode_lines
-                     || buffer->clip_changed);
+                     || buffer->clip_changed
+                     || buffer->prevent_redisplay_optimizations_p);
 
   if (MINI_WINDOW_P (w))
     {
@@ -10141,6 +10188,13 @@ redisplay_window (window, just_this_one_p)
   SET_TEXT_POS (opoint, PT, PT_BYTE);
 
   current_matrix_up_to_date_p
+    = (!NILP (w->window_end_valid)
+       && !current_buffer->clip_changed
+       && !current_buffer->prevent_redisplay_optimizations_p
+       && XFASTINT (w->last_modified) >= MODIFF
+       && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
+
+  buffer_unchanged_p
     = (!NILP (w->window_end_valid)
        && !current_buffer->clip_changed
        && XFASTINT (w->last_modified) >= MODIFF
@@ -10263,8 +10317,7 @@ redisplay_window (window, just_this_one_p)
       w->window_end_valid = Qnil;
 
       /* Forget any recorded base line for line number display.  */
-      if (!current_matrix_up_to_date_p
-         || current_buffer->clip_changed)
+      if (!buffer_unchanged_p)
        w->base_line_number = Qnil;
 
       /* Redisplay the mode line.  Select the buffer properly for that.
@@ -10333,7 +10386,44 @@ redisplay_window (window, just_this_one_p)
        }
 
       if (!make_cursor_line_fully_visible (w))
-       goto need_larger_matrices;
+       {
+         /* CVS rev. 1.761 had changed this to ``goto try_to_scroll''.
+
+            The intention of the fix -- AFAIU -- was to ensure that 
+            the cursor didn't end up on a partially visible last (or
+            first?) line when scrolling.
+
+
+            But that change causes havoc when scrolling backwards and
+            a partially visible first (or last?) line is present when
+            we reach the top of the buffer.  In effect, the text
+            already in the window is repeated (each line is appended
+            to the same or another lines in the window)...
+
+            I changed it back to ``goto need_larger_matrices'' which
+            in effect mean that we don't go through `try_scrolling'
+            when the cursor is already at the first line of the buffer,
+            and there is really only a few pixels [rather than lines]
+            to scroll backwards.  I guess move_it_by_lines etc. really
+            isn't the right device for doing that, ref. the code in
+            make_cursor_line_fully_visible which was also disabled by
+            CVS rev. 1.761.
+
+            But how do we know that we are already on the top line of
+            the window showing the first line in the buffer, so that
+            scrolling really wont help here?
+
+            I cannot find a simple fix for this (I tried various
+            approaches), but I prefer to an occasional partial line
+            rather than the visual messup, so I reverted this part of
+            the fix.
+
+            Someone will need to look into this when time allows.
+
+            -- 2002-08-22, Kim F. Storm  */
+
+         goto need_larger_matrices;
+       }
 #if GLYPH_DEBUG
       debug_method_add (w, "forced window start");
 #endif
@@ -10341,7 +10431,8 @@ redisplay_window (window, just_this_one_p)
     }
 
   /* Handle case where text has not changed, only point, and it has
-     not moved off the frame.  */
+     not moved off the frame, and we are not retrying after hscroll.
+     (current_matrix_up_to_date_p is nonzero when retrying.)  */
   if (current_matrix_up_to_date_p
       && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
          rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
@@ -10429,7 +10520,8 @@ redisplay_window (window, just_this_one_p)
            w->base_line_number = Qnil;
 
          if (!make_cursor_line_fully_visible (w))
-           goto need_larger_matrices;
+           /* Drop through and scroll.  */
+           ;
          goto done;
        }
       else
@@ -10483,6 +10575,10 @@ redisplay_window (window, just_this_one_p)
   /* Finally, just choose place to start which centers point */
 
  recenter:
+  centering_position = window_box_height (w) / 2;
+
+ point_at_top:
+  /* Jump here with centering_position already set to 0.  */
 
 #if GLYPH_DEBUG
   debug_method_add (w, "recenter");
@@ -10491,14 +10587,13 @@ redisplay_window (window, just_this_one_p)
   /* w->vscroll = 0; */
 
   /* Forget any previously recorded base line for line number display.  */
-  if (!current_matrix_up_to_date_p
-      || current_buffer->clip_changed)
+  if (!buffer_unchanged_p)
     w->base_line_number = Qnil;
 
   /* Move backward half the height of the window.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
   it.current_y = it.last_visible_y;
-  move_it_vertically_backward (&it, window_box_height (w) / 2);
+  move_it_vertically_backward (&it, centering_position);
   xassert (IT_CHARPOS (it) >= BEGV);
 
   /* The function move_it_vertically_backward may move over more
@@ -10580,7 +10675,13 @@ redisplay_window (window, just_this_one_p)
     }
 
   if (!make_cursor_line_fully_visible (w))
-    goto need_larger_matrices;
+    {
+      /* If centering point failed to make the whole line visible,
+        put point at the top instead.  That has to make the whole line
+        visible, if it can be done.  */
+      centering_position = 0;
+      goto point_at_top;
+    }
 
  done:
 
@@ -11500,10 +11601,12 @@ try_window_id (w)
   if (windows_or_buffers_changed || cursor_type_changed)
     GIVE_UP (2);
 
-  /* Verify that narrowing has not changed.  This flag is also set to prevent
-     redisplay optimizations.  It would be nice to further
+  /* Verify that narrowing has not changed.
+     Also verify that we were not told to prevent redisplay optimizations.
+     It would be nice to further
      reduce the number of cases where this prevents try_window_id.  */
-  if (current_buffer->clip_changed)
+  if (current_buffer->clip_changed
+      || current_buffer->prevent_redisplay_optimizations_p)
     GIVE_UP (3);
 
   /* Window must either use window-based redisplay or be full width.  */
@@ -12446,7 +12549,8 @@ With ARG, turn tracing on if and only if ARG is positive.  */)
 
 
 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
-       doc: /* Like `format', but print result to stderr.  */)
+       doc: /* Like `format', but print result to stderr.
+usage: (trace-to-stderr STRING &rest OBJECTS)  */)
      (nargs, args)
      int nargs;
      Lisp_Object *args;
@@ -12474,10 +12578,10 @@ get_overlay_arrow_glyph_row (w)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct buffer *buffer = XBUFFER (w->buffer);
   struct buffer *old = current_buffer;
-  unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
+  const unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
   int arrow_len = SCHARS (Voverlay_arrow_string);
-  unsigned char *arrow_end = arrow_string + arrow_len;
-  unsigned char *p;
+  const unsigned char *arrow_end = arrow_string + arrow_len;
+  const unsigned char *p;
   struct it it;
   int multibyte_p;
   int n_glyphs_before;
@@ -13190,9 +13294,10 @@ display_line (it)
                {
                  /* Glyph is completely off the left margin of the
                     window.  This should not happen because of the
-                    move_it_in_display_line at the start of
-                    this function.  */
-                 abort ();
+                    move_it_in_display_line at the start of this
+                    function, unless the text display area of the
+                    window is empty.  */
+                 xassert (it->first_visible_x <= it->last_visible_x);
                }
            }
 
@@ -13681,7 +13786,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
       {
        /* A string: output it and check for %-constructs within it.  */
        unsigned char c;
-       unsigned char *this, *lisp_string;
+       const unsigned char *this, *lisp_string;
 
        if (!NILP (props) || risky)
          {
@@ -13758,7 +13863,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
                   || !NILP (mode_line_string_list)
                   || it->current_x < it->last_visible_x))
          {
-           unsigned char *last = this;
+           const unsigned char *last = this;
 
            /* Advance to end of string or next format specifier.  */
            while ((c = *this++) != '\0' && c != '%')
@@ -13797,7 +13902,7 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
              }
            else /* c == '%' */
              {
-               unsigned char *percent_position = this;
+               const unsigned char *percent_position = this;
 
                /* Get the specified minimum width.  Zero means
                   don't pad.  */
@@ -14163,7 +14268,6 @@ If third optional arg NO-PROPS is non-nil, string is not propertized.  */)
      Lisp_Object format, window, no_props;
 {
   struct it it;
-  struct face *face;
   int len;
   struct window *w;
   struct buffer *old_buffer = NULL;
@@ -14298,7 +14402,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 {
   Lisp_Object val;
   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
-  unsigned char *eol_str;
+  const unsigned char *eol_str;
   int eol_str_len;
   /* The EOL conversion we are using.  */
   Lisp_Object eoltype;
@@ -14350,8 +14454,9 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
       else if (INTEGERP (eoltype)
               && CHAR_VALID_P (XINT (eoltype), 0))
        {
-         eol_str = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
-         eol_str_len = CHAR_STRING (XINT (eoltype), eol_str);
+         unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
+         eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
+         eol_str = tmp;
        }
       else
        {
@@ -15101,6 +15206,199 @@ invisible_p (propval, list)
 }
 
 \f
+/***********************************************************************
+                            Cursor types
+ ***********************************************************************/
+
+/* Value is the internal representation of the specified cursor type
+   ARG.  If type is BAR_CURSOR, return in *WIDTH the specified width
+   of the bar cursor.  */
+
+enum text_cursor_kinds
+get_specified_cursor_type (arg, width)
+     Lisp_Object arg;
+     int *width;
+{
+  enum text_cursor_kinds type;
+  
+  if (NILP (arg))
+    return NO_CURSOR;
+
+  if (EQ (arg, Qbox))
+    return FILLED_BOX_CURSOR;
+
+  if (EQ (arg, Qhollow))
+    return HOLLOW_BOX_CURSOR;
+
+  if (EQ (arg, Qbar))
+    {
+      *width = 2;
+      return BAR_CURSOR;
+    }
+
+  if (CONSP (arg)
+      && EQ (XCAR (arg), Qbar)
+      && INTEGERP (XCDR (arg))
+      && XINT (XCDR (arg)) >= 0)
+    {
+      *width = XINT (XCDR (arg));
+      return BAR_CURSOR;
+    }
+
+  if (EQ (arg, Qhbar))
+    {
+      *width = 2;
+      return HBAR_CURSOR;
+    }
+
+  if (CONSP (arg)
+      && EQ (XCAR (arg), Qhbar)
+      && INTEGERP (XCDR (arg))
+      && XINT (XCDR (arg)) >= 0)
+    {
+      *width = XINT (XCDR (arg));
+      return HBAR_CURSOR;
+    }
+
+  /* Treat anything unknown as "hollow box cursor".
+     It was bad to signal an error; people have trouble fixing
+     .Xdefaults with Emacs, when it has something bad in it.  */
+  type = HOLLOW_BOX_CURSOR;
+
+  return type;
+}
+
+/* Set the default cursor types for specified frame.  */
+void
+set_frame_cursor_types (f, arg)
+     struct frame *f;
+     Lisp_Object arg;
+{
+  int width;
+  Lisp_Object tem;
+
+  FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
+  FRAME_CURSOR_WIDTH (f) = width;
+
+  /* By default, set up the blink-off state depending on the on-state.  */
+
+  tem = Fassoc (arg, Vblink_cursor_alist);
+  if (!NILP (tem))
+    {
+      FRAME_BLINK_OFF_CURSOR (f)
+       = get_specified_cursor_type (XCDR (tem), &width);
+      FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
+    }
+  else
+    FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
+}
+
+
+/* Return the cursor we want to be displayed.  In a mini-buffer
+   window, we want the cursor only to appear if we are reading input
+   from this window.  For the selected window, we want the cursor type
+   given by the frame parameter or buffer local setting of
+   cursor-type.  If explicitly marked off, draw no cursor.  In all
+   other cases, we want a hollow box cursor.  */
+
+enum text_cursor_kinds
+get_window_cursor_type (w, width)
+     struct window *w;
+     int *width;
+{
+  struct frame *f = XFRAME (w->frame);
+  struct buffer *b = XBUFFER (w->buffer);
+  int cursor_type = DEFAULT_CURSOR;
+  Lisp_Object alt_cursor;
+  int non_selected = 0;
+
+  /* Echo area */
+  if (cursor_in_echo_area
+      && FRAME_HAS_MINIBUF_P (f)
+      && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+    {
+      if (w == XWINDOW (echo_area_window))
+       {
+         *width = FRAME_CURSOR_WIDTH (f);
+         return FRAME_DESIRED_CURSOR (f);
+       }
+
+      non_selected = 1;
+    }
+
+  /* Nonselected window or nonselected frame.  */
+  else if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+      || w != XWINDOW (f->selected_window))
+    {
+      if (MINI_WINDOW_P (w) && minibuf_level == 0)
+       return NO_CURSOR;
+
+      non_selected = 1;
+    }
+
+  /* Never display a cursor in a window in which cursor-type is nil.  */
+  if (NILP (b->cursor_type))
+    return NO_CURSOR;
+
+  /* Use cursor-in-non-selected-windows for non-selected window or frame.  */
+  if (non_selected)
+    {
+      alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
+      return get_specified_cursor_type (alt_cursor, width);
+    }
+
+  /* Get the normal cursor type for this window.  */
+  if (EQ (b->cursor_type, Qt))
+    {
+      cursor_type = FRAME_DESIRED_CURSOR (f);
+      *width = FRAME_CURSOR_WIDTH (f);
+    }
+  else
+    cursor_type = get_specified_cursor_type (b->cursor_type, width);
+
+  /* Use normal cursor if not blinked off.  */
+  if (!w->cursor_off_p)
+    return cursor_type;
+
+  /* Cursor is blinked off, so determine how to "toggle" it.  */
+
+  /* First try to use alternate-cursor-type, unless it is t.  */
+  alt_cursor = Fbuffer_local_value (Qalternate_cursor_type, w->buffer);
+  if (!EQ (alt_cursor, Qt))
+    return get_specified_cursor_type (alt_cursor, width);
+
+  /* Then unless buffer's cursor-type is t (use default),
+     look for an entry matching normal cursor in blink-cursor-alist.  */
+  if (!EQ (b->cursor_type, Qt) &&
+      (alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
+    return get_specified_cursor_type (XCDR (alt_cursor), width);
+
+  /* Then see if frame has specified a specific blink off cursor type.  */
+  if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
+    {
+      *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
+      return FRAME_BLINK_OFF_CURSOR (f);
+    }
+  
+  /* Finally perform built-in cursor blinking: 
+       filled box      <->   hollow box
+       wide [h]bar     <->   narrow [h]bar
+       narrow [h]bar   <->   no cursor
+       other type      <->   no cursor  */
+
+  if (cursor_type == FILLED_BOX_CURSOR)
+    return HOLLOW_BOX_CURSOR;
+
+  if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
+    {
+      *width = 1;
+      return cursor_type;
+    }
+
+  return NO_CURSOR;
+}
+
+\f
 /***********************************************************************
                            Initialization
  ***********************************************************************/
@@ -15201,6 +15499,8 @@ syms_of_xdisp ()
   staticpro (&Qmessage_truncate_lines);
   Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
   staticpro (&Qcursor_in_non_selected_windows);
+  Qalternate_cursor_type = intern ("alternate-cursor-type");
+  staticpro (&Qalternate_cursor_type);
   Qgrow_only = intern ("grow-only");
   staticpro (&Qgrow_only);
   Qinhibit_menubar_update = intern ("inhibit-menubar-update");
@@ -15213,8 +15513,18 @@ syms_of_xdisp ()
   staticpro (&Qbuffer_position);
   Qobject = intern ("object");
   staticpro (&Qobject);
+  Qbar = intern ("bar");
+  staticpro (&Qbar);
+  Qhbar = intern ("hbar");
+  staticpro (&Qhbar);
+  Qbox = intern ("box");
+  staticpro (&Qbox);
+  Qhollow = intern ("hollow");
+  staticpro (&Qhollow);
   Qrisky_local_variable = intern ("risky-local-variable");
   staticpro (&Qrisky_local_variable);
+  Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
+  staticpro (&Qinhibit_free_realized_faces);
 
   list_of_error = Fcons (intern ("error"), Qnil);
   staticpro (&list_of_error);
@@ -15296,9 +15606,7 @@ of the top or bottom of the window.  */);
   DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
     doc: /* nil means display the mode-line/header-line/menu-bar in the default face.
 Any other value means to use the appropriate face, `mode-line',
-`header-line', or `menu' respectively.
-
-This variable is deprecated; please change the above faces instead.  */);
+`header-line', or `menu' respectively.  */);
   mode_line_inverse_video = 1;
 
   DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
@@ -15423,11 +15731,24 @@ only, until their display becomes empty, at which point the windows
 go back to their normal size.  */);
   Vresize_mini_windows = Qgrow_only;
 
-  DEFVAR_BOOL ("cursor-in-non-selected-windows",
-              &cursor_in_non_selected_windows,
-    doc: /* *Non-nil means display a hollow cursor in non-selected windows.
-nil means don't display a cursor there.  */);
-  cursor_in_non_selected_windows = 1;
+  DEFVAR_LISP ("cursor-in-non-selected-windows",
+              &Vcursor_in_non_selected_windows,
+    doc: /* *Cursor type to display in non-selected windows.
+t means to use hollow box cursor.  See `cursor-type' for other values.  */);
+  Vcursor_in_non_selected_windows = Qt;
+
+  DEFVAR_LISP ("alternate-cursor-type", &Valternate_cursor_type,
+    doc: /* *Cursor type displayed in the blinking cursor off state.
+t means to use default.  See `cursor-type' for other values.  */);
+  Valternate_cursor_type = Qt;
+
+  DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
+    doc: /* Alist specifying how to blink the cursor off.
+Each element has the form (ON-STATE . OFF-STATE).  Whenever the
+`cursor-type' frame-parameter or variable equals ON-STATE,
+comparing using `equal', Emacs uses OFF-STATE to specify
+how to blink it off.  */);
+  Vblink_cursor_alist = Qnil;
 
   DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
     doc: /* *Non-nil means scroll the display automatically to make point visible.  */);
@@ -15479,6 +15800,10 @@ Can be used to update submenus whose contents should vary.  */);
     doc: /* Non-nil means don't eval Lisp during redisplay.  */);
   inhibit_eval_during_redisplay = 0;
 
+  DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
+    doc: /* Non-nil means don't free realized faces.  Internal use only.  */);
+  inhibit_free_realized_faces = 0;
+
 #if GLYPH_DEBUG
   DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
               doc: /* Inhibit try_window_id display optimization.  */);