(resize_mini_window): Don't resize while redisplaying.
[bpt/emacs.git] / src / xdisp.c
index a046603..6a56fe1 100644 (file)
@@ -659,6 +659,7 @@ enum move_it_result
 \f
 /* Function prototypes.  */
 
+static void setup_for_ellipsis P_ ((struct it *));
 static void mark_window_display_accurate_1 P_ ((struct window *, int));
 static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
 static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
@@ -732,7 +733,7 @@ static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
                               int, int, struct it *, int, int, int, int));
 static void compute_line_metrics P_ ((struct it *));
 static void run_redisplay_end_trigger_hook P_ ((struct it *));
-static int get_overlay_strings P_ ((struct it *));
+static int get_overlay_strings P_ ((struct it *, int));
 static void next_overlay_string P_ ((struct it *));
 static void reseat P_ ((struct it *, struct text_pos, int));
 static void reseat_1 P_ ((struct it *, struct text_pos, int));
@@ -746,7 +747,7 @@ static int next_element_from_buffer P_ ((struct it *));
 static int next_element_from_composition P_ ((struct it *));
 static int next_element_from_image P_ ((struct it *));
 static int next_element_from_stretch P_ ((struct it *));
-static void load_overlay_strings P_ ((struct it *));
+static void load_overlay_strings P_ ((struct it *, int));
 static void init_from_display_pos P_ ((struct it *, struct window *,
                                       struct display_pos *));
 static void reseat_to_string P_ ((struct it *, unsigned char *,
@@ -1848,7 +1849,7 @@ init_from_display_pos (it, w, pos)
          it->current.overlay_string_index = 0;
          while (n--)
            {
-             load_overlay_strings (it);
+             load_overlay_strings (it, 0);
              it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
            }
        }
@@ -2531,12 +2532,14 @@ handle_invisible_prop (it)
     }
   else
     {
-      int visible_p, newpos, next_stop;
-      Lisp_Object pos, prop;
+      int visible_p, newpos, next_stop, start_charpos;
+      Lisp_Object pos, prop, overlay;
 
       /* First of all, is there invisible text at this position?  */
+      start_charpos = IT_CHARPOS (*it);
       pos = make_number (IT_CHARPOS (*it));
-      prop = Fget_char_property (pos, Qinvisible, it->window);
+      prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
+                                           &overlay);
       
       /* If we are on invisible text, skip over it.  */
       if (TEXT_PROP_MEANS_INVISIBLE (prop)
@@ -2585,36 +2588,25 @@ handle_invisible_prop (it)
                IT_CHARPOS (*it) = next_stop;
            }
          while (!visible_p);
-         
+
          /* The position newpos is now either ZV or on visible text.  */
          IT_CHARPOS (*it) = newpos;
          IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
          
-         /* Maybe return `...' next for the end of the invisible text.  */
-         if (display_ellipsis_p)
+         /* If there are before-strings at the start of invisible
+            text, and the text is invisible because of a text
+            property, arrange to show before-strings because 20.x did
+            it that way.  (If the text is invisible because of an
+            overlay property instead of a text property, this is
+            already handled in the overlay code.)  */
+         if (NILP (overlay)
+             && get_overlay_strings (it, start_charpos))
            {
-             if (it->dp 
-                 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
-               {
-                 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
-                 it->dpvec = v->contents;
-                 it->dpend = v->contents + v->size;
-               }
-             else 
-               {
-                 /* Default `...'.  */
-                 it->dpvec = default_invis_vector;
-                 it->dpend = default_invis_vector + 3;
-               }
-
-             /* The ellipsis display does not replace the display of
-                the character at the new position.  Indicate this by
-                setting IT->dpvec_char_len to zero.  */
-             it->dpvec_char_len = 0;
-             
-             it->current.dpvec_index = 0;
-             it->method = next_element_from_display_vector;
+             handled = HANDLED_RECOMPUTE_PROPS;
+             it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
            }
+         else if (display_ellipsis_p)
+           setup_for_ellipsis (it);
        }
     }
 
@@ -2622,6 +2614,36 @@ handle_invisible_prop (it)
 }
 
 
+/* Make iterator IT return `...' next.  */
+
+static void
+setup_for_ellipsis (it)
+     struct it *it;
+{
+  if (it->dp 
+      && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+    {
+      struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
+      it->dpvec = v->contents;
+      it->dpend = v->contents + v->size;
+    }
+  else 
+    {
+      /* Default `...'.  */
+      it->dpvec = default_invis_vector;
+      it->dpend = default_invis_vector + 3;
+    }
+  
+  /* The ellipsis display does not replace the display of the
+     character at the new position.  Indicate this by setting
+     IT->dpvec_char_len to zero.  */
+  it->dpvec_char_len = 0;
+  
+  it->current.dpvec_index = 0;
+  it->method = next_element_from_display_vector;
+}
+
+
 \f
 /***********************************************************************
                            'display' property
@@ -3285,7 +3307,7 @@ static enum prop_handled
 handle_overlay_change (it)
      struct it *it;
 {
-  if (!STRINGP (it->string) && get_overlay_strings (it))
+  if (!STRINGP (it->string) && get_overlay_strings (it, 0))
     return HANDLED_RECOMPUTE_PROPS;
   else
     return HANDLED_NORMALLY;
@@ -3309,6 +3331,8 @@ next_overlay_string (it)
       /* No more overlay strings.  Restore IT's settings to what
         they were before overlay strings were processed, and
         continue to deliver from current_buffer.  */
+      int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
+      
       pop_it (it);
       xassert (it->stop_charpos >= BEGV
               && it->stop_charpos <= it->end_charpos);
@@ -3323,6 +3347,11 @@ next_overlay_string (it)
         next_element_from_buffer doesn't try it again.  */
       if (IT_CHARPOS (*it) >= it->end_charpos)
        it->overlay_strings_at_end_processed_p = 1;
+
+      /* If we have to display `...' for invisible text, set
+        the iterator up for that.  */
+      if (display_ellipsis_p)
+       setup_for_ellipsis (it);
     }
   else
     {
@@ -3333,7 +3362,7 @@ next_overlay_string (it)
       int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
   
       if (it->current.overlay_string_index && i == 0)
-       load_overlay_strings (it);
+       load_overlay_strings (it, 0);
 
       /* Initialize IT to deliver display elements from the overlay
          string.  */
@@ -3393,8 +3422,8 @@ compare_overlay_entries (e1, e2)
 
 
 /* Load the vector IT->overlay_strings with overlay strings from IT's
-   current buffer position.  Set IT->n_overlays to the total number of
-   overlay strings found.  
+   current buffer position, or from CHARPOS if that is > 0.  Set
+   IT->n_overlays to the total number of overlay strings found.
 
    Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
    a time.  On entry into load_overlay_strings,
@@ -3417,8 +3446,9 @@ compare_overlay_entries (e1, e2)
    compare_overlay_entries.  */
    
 static void
-load_overlay_strings (it)
+load_overlay_strings (it, charpos)
      struct it *it;
+     int charpos;
 {
   extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
   Lisp_Object ov, overlay, window, str, invisible;
@@ -3427,7 +3457,9 @@ load_overlay_strings (it)
   int n = 0, i, j, invis_p;
   struct overlay_entry *entries
     = (struct overlay_entry *) alloca (size * sizeof *entries);
-  int charpos = IT_CHARPOS (*it);
+
+  if (charpos <= 0)
+    charpos = IT_CHARPOS (*it);
 
   /* Append the overlay string STRING of overlay OVERLAY to vector
      `entries' which has size `size' and currently contains `n'
@@ -3559,12 +3591,13 @@ load_overlay_strings (it)
 
 
 /* Get the first chunk of overlay strings at IT's current buffer
-   position.  Value is non-zero if at least one overlay string was
-   found.   */
+   position, or at CHARPOS if that is > 0.  Value is non-zero if at
+   least one overlay string was found.  */
 
 static int
-get_overlay_strings (it)
+get_overlay_strings (it, charpos)
      struct it *it;
+     int charpos;
 {
   /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
      process.  This fills IT->overlay_strings with strings, and sets
@@ -3574,7 +3607,7 @@ get_overlay_strings (it)
      when no overlay strings are found because a zero value would
      indicate a position in the first overlay string.  */
   it->current.overlay_string_index = 0;
-  load_overlay_strings (it);
+  load_overlay_strings (it, charpos);
 
   /* If we found overlay strings, set up IT to deliver display
      elements from the first one.  Otherwise set up IT to deliver
@@ -3648,6 +3681,7 @@ push_it (it)
   p->font_height = it->font_height;
   p->voffset = it->voffset;
   p->string_from_display_prop_p = it->string_from_display_prop_p;
+  p->display_ellipsis_p = 0;
   ++it->sp;
 }
 
@@ -4193,7 +4227,22 @@ get_next_display_element (it)
                  if (SINGLE_BYTE_CHAR_P (it->c))
                    str[0] = it->c, len = 1;
                  else
-                   len = CHAR_STRING (it->c, str);
+                   {
+                     len = CHAR_STRING_NO_SIGNAL (it->c, str);
+                     if (len < 0)
+                       {
+                         /* It's an invalid character, which
+                            shouldn't happen actually, but due to
+                            bugs it may happen.  Let's print the char
+                            as is, there's not much meaningful we can
+                            do with it.  */
+                         str[0] = it->c;
+                         str[1] = it->c >> 8;
+                         str[2] = it->c >> 16;
+                         str[3] = it->c >> 24;
+                         len = 4;
+                       }
+                   }
 
                  for (i = 0; i < len; i++)
                    {
@@ -4702,7 +4751,7 @@ next_element_from_buffer (it)
          else
            {
              it->overlay_strings_at_end_processed_p = 1;
-             overlay_strings_follow_p = get_overlay_strings (it);
+             overlay_strings_follow_p = get_overlay_strings (it, 0);
            }
 
          if (overlay_strings_follow_p)
@@ -5465,6 +5514,12 @@ add_to_log (format, arg1, arg2)
   int len;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
+  /* Do nothing if called asynchronously.  Inserting text into
+     a buffer may call after-change-functions and alike and
+     that would means running Lisp asynchronously.  */
+  if (handling_signal)
+    return;
+
   fmt = msg = Qnil;
   GCPRO4 (fmt, msg, arg1, arg2);
   
@@ -6445,6 +6500,12 @@ resize_mini_window (w, exact_p)
 
   xassert (MINI_WINDOW_P (w));
 
+  /* Don't resize windows while redisplaying; it would confuse
+     redisplay functions when the size of the window they are
+     displaying changes from under them.  */
+  if (redisplaying_p)
+    return 0;
+  
   /* Nil means don't try to resize.  */
   if (NILP (Vresize_mini_windows)
       || (FRAME_X_P (f) && f->output_data.x == NULL))
@@ -9539,7 +9600,7 @@ try_cursor_movement (window, startp, scroll_step)
          || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
     {
       int this_scroll_margin;
-      struct glyph_row *row;
+      struct glyph_row *row = NULL;
 
 #if GLYPH_DEBUG
       debug_method_add (w, "cursor movement");
@@ -11106,7 +11167,7 @@ try_window_id (w)
   if (windows_or_buffers_changed)
     GIVE_UP (2);
   
-  /* Narrowing has not changed.  This flag is also set to prevent
+  /* Verify that narrowing has not changed.  This flag is also set 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)
@@ -11118,7 +11179,7 @@ try_window_id (w)
          || !WINDOW_FULL_WIDTH_P (w)))
     GIVE_UP (4);
 
-  /* Point is not known NOT to appear in W.  */
+  /* Give up if point is not known NOT to appear in W.  */
   if (PT < CHARPOS (start))
     GIVE_UP (5);
 
@@ -11126,11 +11187,11 @@ try_window_id (w)
   if (XFASTINT (w->last_modified) == 0)
     GIVE_UP (6);
   
-  /* Window is not hscrolled.  */
+  /* Verify that window is not hscrolled.  */
   if (XFASTINT (w->hscroll) != 0)
     GIVE_UP (7);
   
-  /* Display wasn't paused.  */
+  /* Verify that display wasn't paused.  */
   if (NILP (w->window_end_valid))
     GIVE_UP (8);
   
@@ -11179,9 +11240,9 @@ try_window_id (w)
      be adjusted, of course.  */
   row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
   if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
-      && ((first_changed_charpos < CHARPOS (start)
+      && ((last_changed_charpos < CHARPOS (start)
           && CHARPOS (start) == BEGV)
-         || (first_changed_charpos < CHARPOS (start) - 1
+         || (last_changed_charpos < CHARPOS (start) - 1
              && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
     {
       int Z_old, delta, Z_BYTE_old, delta_bytes;
@@ -11226,8 +11287,14 @@ try_window_id (w)
     }
 
   /* Handle the case that changes are all below what is displayed in
-     the window, and that PT is in the window.  */
-  if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row))
+     the window, and that PT is in the window.  This shortcut cannot
+     be taken if ZV is visible in the window, and text has been added
+     there that is visible in the window.  */
+  if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
+      /* ZV is not visible in the window, or there are no
+        changes at ZV, actually.  */
+      && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
+         || first_changed_charpos == last_changed_charpos))
     {
       struct glyph_row *r0;
 
@@ -11257,15 +11324,21 @@ try_window_id (w)
        }
     }
 
+  /* Give up if window start is in the changed area.
+     
+     The condition used to read
+
+     (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
+
+     but why that was tested escapes me at the moment.  */
+  if (CHARPOS (start) >= first_changed_charpos
+      && CHARPOS (start) <= last_changed_charpos)
+    GIVE_UP (15);
+  
   /* Check that window start agrees with the start of the first glyph
      row in its current matrix.  Check this after we know the window
      start is not in changed text, otherwise positions would not be
      comparable.  */
-  if (BEG_UNCHANGED + END_UNCHANGED != Z - BEG
-      && CHARPOS (start) >= first_changed_charpos
-      && CHARPOS (start) <= last_changed_charpos)
-    GIVE_UP (15);
-  
   row = MATRIX_FIRST_TEXT_ROW (current_matrix);
   if (!TEXT_POS_EQUAL_P (start, row->start.pos))
     GIVE_UP (16);
@@ -11376,7 +11449,7 @@ try_window_id (w)
   
 #endif /* GLYPH_DEBUG != 0 */
 
-
+  
   /* Display new lines.  Set last_text_row to the last new line
      displayed which has text on it, i.e. might end up as being the
      line where the window_end_vpos is.  */
@@ -11655,6 +11728,8 @@ try_window_id (w)
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
       w->window_end_vpos
        = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
+      xassert (w->window_end_bytepos >= 0);
+      IF_DEBUG (debug_method_add (w, "A"));
     }
   else if (last_text_row_at_end)
     {
@@ -11664,6 +11739,8 @@ try_window_id (w)
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
       w->window_end_vpos
        = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
+      xassert (w->window_end_bytepos >= 0);
+      IF_DEBUG (debug_method_add (w, "B"));
     }
   else if (last_text_row)
     {
@@ -11676,6 +11753,7 @@ try_window_id (w)
        = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
       w->window_end_vpos
        = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
+      xassert (w->window_end_bytepos >= 0);
     }
   else if (first_unchanged_at_end_row == NULL
           && last_text_row == NULL
@@ -11683,20 +11761,30 @@ try_window_id (w)
     {
       /* Displayed to end of window, but no line containing text was
         displayed.  Lines were deleted at the end of the window.  */
-      int vpos;
-      int header_line_p = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
-
-      for (vpos = XFASTINT (w->window_end_vpos); vpos > 0; --vpos)
-       if ((w->desired_matrix->rows[vpos + header_line_p].enabled_p
-            && w->desired_matrix->rows[vpos + header_line_p].displays_text_p)
-           || (!w->desired_matrix->rows[vpos + header_line_p].enabled_p
-               && w->current_matrix->rows[vpos + header_line_p].displays_text_p))
-         break;
+      int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
+      int vpos = XFASTINT (w->window_end_vpos);
+      struct glyph_row *current_row = current_matrix->rows + vpos;
+      struct glyph_row *desired_row = desired_matrix->rows + vpos;
+
+      for (row = NULL;
+          row == NULL && vpos >= first_vpos;
+          --vpos, --current_row, --desired_row)
+       {
+         if (desired_row->enabled_p)
+           {
+             if (desired_row->displays_text_p)
+               row = desired_row;
+           }
+         else if (current_row->displays_text_p)
+           row  = current_row;
+       }
 
-      w->window_end_vpos = make_number (vpos);
-      row = MATRIX_ROW (w->desired_matrix, vpos);
+      xassert (row != NULL);
+      w->window_end_vpos = make_number (vpos + 1);
       w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
       w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
+      xassert (w->window_end_bytepos >= 0);
+      IF_DEBUG (debug_method_add (w, "C"));
     }
   else
     abort ();
@@ -11845,7 +11933,7 @@ dump_glyph_row (matrix, vpos, glyphs)
       fprintf (stderr, "=======================================================================\n");
   
       fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d\
-%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
+%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d  %4d %4d %4d %4d %4d %4d %4d\n",
               row - matrix->rows,
               MATRIX_ROW_START_CHARPOS (row),
               MATRIX_ROW_END_CHARPOS (row),
@@ -11871,8 +11959,9 @@ dump_glyph_row (matrix, vpos, glyphs)
               row->visible_height,
               row->ascent,
               row->phys_ascent);
-      fprintf (stderr, "%9d %5d\n", row->start.overlay_string_index,
-              row->end.overlay_string_index);
+      fprintf (stderr, "%9d %5d\t%5d\n", row->start.overlay_string_index,
+              row->end.overlay_string_index,
+              row->continuation_lines_width);
       fprintf (stderr, "%9d %5d\n",
               CHARPOS (row->start.string_pos),
               CHARPOS (row->end.string_pos));
@@ -12202,6 +12291,10 @@ compute_line_metrics (it)
   else
     {
       row->pixel_width = row->used[TEXT_AREA];
+      if (row->continued_p)
+       row->pixel_width -= it->continuation_pixel_width;
+      else if (row->truncated_on_right_p)
+       row->pixel_width -= it->truncation_pixel_width;
       row->ascent = row->phys_ascent = 0;
       row->height = row->phys_height = row->visible_height = 1;
     }