remove Lisp_Free struct type
[bpt/emacs.git] / src / xdisp.c
index 6728a02..76ffdb4 100644 (file)
@@ -98,7 +98,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
       This function attempts to redisplay a window by reusing parts of
       its existing display.  It finds and reuses the part that was not
-      changed, and redraws the rest.
+      changed, and redraws the rest.  (The "id" part in the function's
+      name stands for "insert/delete", not for "identification" or
+      somesuch.)
 
     . try_window
 
@@ -113,6 +115,19 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
    optimizations were successful, redisplay calls redisplay_windows,
    which performs a full redisplay of all windows.
 
+   Note that there's one more important optimization up Emacs's
+   sleeve, but it is related to actually redrawing the potentially
+   changed portions of the window/frame, not to reproducing the
+   desired matrices of those potentially changed portions.  Namely,
+   the function update_frame and its subroutines, which you will find
+   in dispnew.c, compare the desired matrices with the current
+   matrices, and only redraw the portions that changed.  So it could
+   happen that the functions in this file for some reason decide that
+   the entire desired matrix needs to be regenerated from scratch, and
+   still only parts of the Emacs display, or even nothing at all, will
+   be actually delivered to the glass, because update_frame has found
+   that the new and the old screen contents are similar or identical.
+
    Desired matrices.
 
    Desired matrices are always built per Emacs window.  The function
@@ -2591,8 +2606,8 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
    following.  Return the result, or nil if something went
    wrong.  Prevent redisplay during the evaluation.  */
 
-Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+static Lisp_Object
+safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
 {
   Lisp_Object val;
 
@@ -2600,21 +2615,20 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
     val = Qnil;
   else
     {
-      va_list ap;
       ptrdiff_t i;
       ptrdiff_t count = SPECPDL_INDEX ();
       struct gcpro gcpro1;
       Lisp_Object *args = alloca (nargs * word_size);
 
       args[0] = func;
-      va_start (ap, func);
       for (i = 1; i < nargs; i++)
        args[i] = va_arg (ap, Lisp_Object);
-      va_end (ap);
 
       GCPRO1 (args[0]);
       gcpro1.nvars = nargs;
       specbind (Qinhibit_redisplay, Qt);
+      if (inhibit_quit)
+       specbind (Qinhibit_quit, Qt);
       /* Use Qt to ensure debugger does not run,
         so there is no possibility of wanting to redisplay.  */
       val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
@@ -2626,6 +2640,17 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
   return val;
 }
 
+Lisp_Object
+safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
+{
+  Lisp_Object retval;
+  va_list ap;
+
+  va_start (ap, func);
+  retval = safe__call (false, nargs, func, ap);
+  va_end (ap);
+  return retval;
+}
 
 /* Call function FN with one argument ARG.
    Return the result, or nil if something went wrong.  */
@@ -2636,12 +2661,30 @@ safe_call1 (Lisp_Object fn, Lisp_Object arg)
   return safe_call (2, fn, arg);
 }
 
+static Lisp_Object
+safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
+{
+  Lisp_Object retval;
+  va_list ap;
+
+  va_start (ap, fn);
+  retval = safe__call (inhibit_quit, 2, fn, ap);
+  va_end (ap);
+  return retval;
+}
+
 static Lisp_Object Qeval;
 
 Lisp_Object
 safe_eval (Lisp_Object sexpr)
 {
-  return safe_call1 (Qeval, sexpr);
+  return safe__call1 (false, Qeval, sexpr);
+}
+
+static Lisp_Object
+safe__eval (bool inhibit_quit, Lisp_Object sexpr)
+{
+  return safe__call1 (inhibit_quit, Qeval, sexpr);
 }
 
 /* Call function FN with two arguments ARG1 and ARG2.
@@ -8226,7 +8269,7 @@ next_element_from_buffer (struct it *it)
 
       /* Get the next character, maybe multibyte.  */
       p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-      if (it->multibyte_p && !ASCII_BYTE_P (*p))
+      if (it->multibyte_p && !ASCII_CHAR_P (*p))
        it->c = STRING_CHAR_AND_LENGTH (p, it->len);
       else
        it->c = *p, it->len = 1;
@@ -8528,7 +8571,7 @@ move_it_in_display_line_to (struct it *it,
        }
       else
        {
-         if (it->line_wrap == WORD_WRAP)
+         if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
            {
              if (IT_DISPLAYING_WHITESPACE (it))
                may_wrap = 1;
@@ -8812,8 +8855,11 @@ move_it_in_display_line_to (struct it *it,
                  if (closest_pos < ZV)
                    {
                      RESTORE_IT (it, &ppos_it, ppos_data);
-                     move_it_in_display_line_to (it, closest_pos, -1,
-                                                 MOVE_TO_POS);
+                     /* Don't recurse if closest_pos is equal to
+                        to_charpos, since we have just tried that.  */
+                     if (closest_pos != to_charpos)
+                       move_it_in_display_line_to (it, closest_pos, -1,
+                                                   MOVE_TO_POS);
                      result = MOVE_POS_MATCH_OR_ZV;
                    }
                  else
@@ -8874,8 +8920,9 @@ move_it_in_display_line_to (struct it *it,
                      && !at_eob_p && closest_pos < ZV)
                    {
                      RESTORE_IT (it, &ppos_it, ppos_data);
-                     move_it_in_display_line_to (it, closest_pos, -1,
-                                                 MOVE_TO_POS);
+                     if (closest_pos != to_charpos)
+                       move_it_in_display_line_to (it, closest_pos, -1,
+                                                   MOVE_TO_POS);
                    }
                  result = MOVE_POS_MATCH_OR_ZV;
                  break;
@@ -8893,7 +8940,9 @@ move_it_in_display_line_to (struct it *it,
              if (closest_pos < ZV)
                {
                  RESTORE_IT (it, &ppos_it, ppos_data);
-                 move_it_in_display_line_to (it, closest_pos, -1, MOVE_TO_POS);
+                 if (closest_pos != to_charpos)
+                   move_it_in_display_line_to (it, closest_pos, -1,
+                                               MOVE_TO_POS);
                }
              result = MOVE_POS_MATCH_OR_ZV;
              break;
@@ -9883,9 +9932,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
          for (i = 0; i < nbytes; i += char_bytes)
            {
              c = string_char_and_length (msg + i, &char_bytes);
-             work[0] = (ASCII_CHAR_P (c)
-                        ? c
-                        : multibyte_char_to_unibyte (c));
+             work[0] = CHAR_TO_BYTE8 (c);
              insert_1_both (work, 1, 1, 1, 0, 0);
            }
        }
@@ -10167,19 +10214,17 @@ message_with_string (const char *m, Lisp_Object string, int log)
     {
       if (m)
        {
-         /* ENCODE_SYSTEM below can GC and/or relocate the Lisp
-            String whose data pointer might be passed to us in M.  So
-            we use a local copy.  */
-         char *fmt = xstrdup (m);
+         /* ENCODE_SYSTEM below can GC and/or relocate the
+            Lisp data, so make sure we don't use it here.  */
+         eassert (relocatable_string_data_p (m) != 1);
 
          if (noninteractive_need_newline)
            putc ('\n', stderr);
          noninteractive_need_newline = 0;
-         fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string)));
+         fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string)));
          if (!cursor_in_echo_area)
            fprintf (stderr, "\n");
          fflush (stderr);
-         xfree (fmt);
        }
     }
   else if (INTERACTIVE)
@@ -10614,13 +10659,6 @@ display_echo_area (struct window *w)
 {
   int i, no_message_p, window_height_changed_p;
 
-  /* Temporarily disable garbage collections while displaying the echo
-     area.  This is done because a GC can print a message itself.
-     That message would modify the echo area buffer's contents while a
-     redisplay of the buffer is going on, and seriously confuse
-     redisplay.  */
-  ptrdiff_t count = inhibit_garbage_collection ();
-
   /* If there is no message, we must call display_echo_area_1
      nevertheless because it resizes the window.  But we will have to
      reset the echo_area_buffer in question to nil at the end because
@@ -10636,7 +10674,6 @@ display_echo_area (struct window *w)
   if (no_message_p)
     echo_area_buffer[i] = Qnil;
 
-  unbind_to (count, Qnil);
   return window_height_changed_p;
 }
 
@@ -11543,7 +11580,7 @@ prepare_menu_bars (void)
                }
            }
        }
-      safe_call1 (Vpre_redisplay_function, windows);
+      safe__call1 (true, Vpre_redisplay_function, windows);
     }
 
   /* Update all frame titles based on their buffer names, etc.  We do
@@ -11774,11 +11811,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run)
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-/* Tool-bar item index of the item on which a mouse button was pressed
-   or -1.  */
-
-int last_tool_bar_item;
-
 /* Select `frame' temporarily without running all the code in
    do_switch_frame.
    FIXME: Maybe do_switch_frame should be trimmed down similarly
@@ -12237,11 +12269,6 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
 
 #endif /* !USE_GTK && !HAVE_NS */
 
-#if defined USE_GTK || defined HAVE_NS
-EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST;
-EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
-#endif
-
 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
        0, 2, 0,
        doc: /* Return the number of lines occupied by the tool bar of FRAME.
@@ -12580,7 +12607,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
      where the button was pressed, disregarding where it was
      released.  */
   if (NILP (Vmouse_highlight) && !down_p)
-    prop_idx = last_tool_bar_item;
+    prop_idx = f->last_tool_bar_item;
 
   /* If item is disabled, do nothing.  */
   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
@@ -12592,7 +12619,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
       /* Show item in pressed state.  */
       if (!NILP (Vmouse_highlight))
        show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
-      last_tool_bar_item = prop_idx;
+      f->last_tool_bar_item = prop_idx;
     }
   else
     {
@@ -12617,7 +12644,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p,
       event.arg = key;
       event.modifiers = modifiers;
       kbd_buffer_store_event (&event);
-      last_tool_bar_item = -1;
+      f->last_tool_bar_item = -1;
     }
 }
 
@@ -12667,8 +12694,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y)
   mouse_down_p = (x_mouse_grabbed (dpyinfo)
                  && f == dpyinfo->last_mouse_frame);
 
-  if (mouse_down_p
-      && last_tool_bar_item != prop_idx)
+  if (mouse_down_p && f->last_tool_bar_item != prop_idx)
     return;
 
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
@@ -14387,7 +14413,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                              pos_after, 0);
 
                if (prop_pos >= pos_before)
-                 bpos_max = prop_pos - 1;
+                 bpos_max = prop_pos;
              }
            if (INTEGERP (chprop))
              {
@@ -14461,7 +14487,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                                              pos_after, 0);
 
                if (prop_pos >= pos_before)
-                 bpos_max = prop_pos - 1;
+                 bpos_max = prop_pos;
              }
            if (INTEGERP (chprop))
              {
@@ -14491,7 +14517,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
      GLYPH_BEFORE and GLYPH_AFTER.  */
   if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
        && BUFFERP (glyph->object) && glyph->charpos == pt_old)
-      && !(bpos_max < pt_old && pt_old <= bpos_covered))
+      && !(bpos_max <= pt_old && pt_old <= bpos_covered))
     {
       /* An empty line has a single glyph whose OBJECT is zero and
         whose CHARPOS is the position of a newline on that line.
@@ -15678,9 +15704,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
   return rc;
 }
 
-#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK
-static
-#endif
 void
 set_vertical_scroll_bar (struct window *w)
 {
@@ -15723,7 +15746,51 @@ set_vertical_scroll_bar (struct window *w)
    selected_window is redisplayed.
 
    We can return without actually redisplaying the window if fonts has been
-   changed on window's frame.  In that case, redisplay_internal will retry.  */
+   changed on window's frame.  In that case, redisplay_internal will retry.
+
+   As one of the important parts of redisplaying a window, we need to
+   decide whether the previous window-start position (stored in the
+   window's w->start marker position) is still valid, and if it isn't,
+   recompute it.  Some details about that:
+
+    . The previous window-start could be in a continuation line, in
+      which case we need to recompute it when the window width
+      changes.  See compute_window_start_on_continuation_line and its
+      call below.
+
+    . The text that changed since last redisplay could include the
+      previous window-start position.  In that case, we try to salvage
+      what we can from the current glyph matrix by calling
+      try_scrolling, which see.
+
+    . Some Emacs command could force us to use a specific window-start
+      position by setting the window's force_start flag, or gently
+      propose doing that by setting the window's optional_new_start
+      flag.  In these cases, we try using the specified start point if
+      that succeeds (i.e. the window desired matrix is successfully
+      recomputed, and point location is within the window).  In case
+      of optional_new_start, we first check if the specified start
+      position is feasible, i.e. if it will allow point to be
+      displayed in the window.  If using the specified start point
+      fails, e.g., if new fonts are needed to be loaded, we abort the
+      redisplay cycle and leave it up to the next cycle to figure out
+      things.
+
+    . Note that the window's force_start flag is sometimes set by
+      redisplay itself, when it decides that the previous window start
+      point is fine and should be kept.  Search for "goto force_start"
+      below to see the details.  Like the values of window-start
+      specified outside of redisplay, these internally-deduced values
+      are tested for feasibility, and ignored if found to be
+      unfeasible.
+
+    . Note that the function try_window, used to completely redisplay
+      a window, accepts the window's start point as its argument.
+      This is used several times in the redisplay code to control
+      where the window start will be, according to user options such
+      as scroll-conservatively, and also to ensure the screen line
+      showing point will be fully (as opposed to partially) visible on
+      display.  */
 
 static void
 redisplay_window (Lisp_Object window, bool just_this_one_p)
@@ -15769,6 +15836,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   eassert (XMARKER (w->start)->buffer == buffer);
   eassert (XMARKER (w->pointm)->buffer == buffer);
 
+  /* We come here again if we need to run window-text-change-functions
+     below.  */
  restart:
   reconsider_clip_changes (w);
   frame_line_height = default_line_pixel_height (w);
@@ -15833,7 +15902,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
        && !current_buffer->prevent_redisplay_optimizations_p
        && !window_outdated (w));
 
-  /* Run the window-bottom-change-functions
+  /* Run the window-text-change-functions
      if it is possible that the text on the screen has changed
      (either due to modification of the text, or any other reason).  */
   if (!current_matrix_up_to_date_p
@@ -20667,6 +20736,10 @@ Value is the new character position of point.  */)
       && !b->clip_changed
       && !b->prevent_redisplay_optimizations_p
       && !window_outdated (w)
+      /* We rely below on the cursor coordinates to be up to date, but
+        we cannot trust them if some command moved point since the
+        last complete redisplay.  */
+      && w->last_point == BUF_PT (b)
       && w->cursor.vpos >= 0
       && w->cursor.vpos < w->current_matrix->nrows
       && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
@@ -21857,7 +21930,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
            if (CONSP (XCDR (elt)))
              {
                Lisp_Object spec;
-               spec = safe_eval (XCAR (XCDR (elt)));
+               spec = safe__eval (true, XCAR (XCDR (elt)));
                n += display_mode_element (it, depth, field_width - n,
                                           precision - n, spec, props,
                                           risky);
@@ -22770,10 +22843,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
 
     case '@':
       {
-       ptrdiff_t count = inhibit_garbage_collection ();
        Lisp_Object val = call1 (intern ("file-remote-p"),
                                 BVAR (current_buffer, directory));
-       unbind_to (count, Qnil);
 
        if (NILP (val))
          return "-";
@@ -23651,7 +23722,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
 #endif
     {
       eassert (face != NULL);
-      PREPARE_FACE_FOR_DISPLAY (f, face);
+      prepare_face_for_display (f, face);
     }
 
   return face;
@@ -23674,7 +23745,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 
   /* Make sure X resources of the face are allocated.  */
   eassert (face != NULL);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
+  prepare_face_for_display (f, face);
 
   if (two_byte_p)
     *two_byte_p = 0;
@@ -23991,7 +24062,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
   s->ybase += voffset;
 
   /* The case that face->gc == 0 is handled when drawing the glyph
-     string by calling PREPARE_FACE_FOR_DISPLAY.  */
+     string by calling prepare_face_for_display.  */
   eassert (s->face);
   return glyph - s->row->glyphs[s->area];
 }
@@ -24589,13 +24660,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
+         if (hl != overlap_hl)
+           clip_head = head;
          j = i;
          BUILD_GLYPH_STRINGS (j, start, h, t,
                               overlap_hl, dummy_x, last_x);
          start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
-         clip_head = head;
+         if (clip_head == NULL)
+           clip_head = head;
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -24616,7 +24690,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
-         clip_head = head;
+         if (hl == overlap_hl || clip_head == NULL)
+           clip_head = head;
          BUILD_GLYPH_STRINGS (i, start, h, t,
                               overlap_hl, dummy_x, last_x);
          for (s = h; s; s = s->next)
@@ -24640,13 +24715,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
+         if (hl != overlap_hl)
+           clip_tail = tail;
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
          /* Because BUILD_GLYPH_STRINGS updates the first argument,
             we don't have `end = i;' here.  */
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
-         clip_tail = tail;
+         if (clip_tail == NULL)
+           clip_tail = tail;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -24664,7 +24742,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
          else
            overlap_hl = DRAW_NORMAL_TEXT;
 
-         clip_tail = tail;
+         if (hl == overlap_hl || clip_tail == NULL)
+           clip_tail = tail;
          i++;                  /* We must include the Ith glyph.  */
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               overlap_hl, x, last_x);
@@ -24932,7 +25011,7 @@ produce_image_glyph (struct it *it)
   face = FACE_FROM_ID (it->f, it->face_id);
   eassert (face);
   /* Make sure X resources of the face is loaded.  */
-  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+  prepare_face_for_display (it->f, face);
 
   if (it->image_id < 0)
     {
@@ -25210,7 +25289,7 @@ produce_stretch_glyph (struct it *it)
     {
       struct face *face = FACE_FROM_ID (it->f, it->face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
-      PREPARE_FACE_FOR_DISPLAY (it->f, face);
+      prepare_face_for_display (it->f, face);
     }
 #endif
 
@@ -25674,7 +25753,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
 
       face = FACE_FROM_ID (it->f, face_id);
       font = face->font ? face->font : FRAME_FONT (it->f);
-      PREPARE_FACE_FOR_DISPLAY (it->f, face);
+      prepare_face_for_display (it->f, face);
 
       if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
        {
@@ -25690,7 +25769,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
          sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
          str = buf;
        }
-      for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
+      for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
        code[len] = font->driver->encode_char (font, str[len]);
       upper_len = (len + 1) / 2;
       font->driver->text_extents (font, code, upper_len,
@@ -27015,9 +27094,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
 
 /* Erase the image of a cursor of window W from the screen.  */
 
-#ifndef HAVE_NTGUI
-static
-#endif
 void
 erase_phys_cursor (struct window *w)
 {
@@ -30565,7 +30641,7 @@ init_xdisp (void)
     /* Allocate the buffer for frame titles.
        Also used for `format-mode-line'.  */
     int size = 100;
-    mode_line_noprop_buf = xmalloc (size);
+    mode_line_noprop_buf = xmalloc_atomic (size);
     mode_line_noprop_buf_end = mode_line_noprop_buf + size;
     mode_line_noprop_ptr = mode_line_noprop_buf;
     mode_line_target = MODE_LINE_DISPLAY;