Add 2009 to copyright years.
[bpt/emacs.git] / src / xdisp.c
index 82c9e82..cea8616 100644 (file)
@@ -1,7 +1,7 @@
 /* Display generation from window structure and buffer text.
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1997, 1998, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1323,7 +1323,7 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
   int visible_p = 0;
   struct buffer *old_buffer = NULL;
 
-  if (noninteractive)
+  if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
     return visible_p;
 
   if (XBUFFER (w->buffer) != current_buffer)
@@ -2999,25 +2999,6 @@ init_from_display_pos (it, w, pos)
       it->method = GET_FROM_STRING;
     }
 
-#if 0 /* This is bogus because POS not having an overlay string
-        position does not mean it's after the string.  Example: A
-        line starting with a before-string and initialization of IT
-        to the previous row's end position.  */
-  else if (it->current.overlay_string_index >= 0)
-    {
-      /* If POS says we're already after an overlay string ending at
-        POS, make sure to pop the iterator because it will be in
-        front of that overlay string.  When POS is ZV, we've thereby
-        also ``processed'' overlay strings at ZV.  */
-      while (it->sp)
-       pop_it (it);
-      xassert (it->current.overlay_string_index == -1);
-      xassert (it->method == GET_FROM_BUFFER);
-      if (CHARPOS (pos->pos) == ZV)
-       it->overlay_strings_at_end_processed_p = 1;
-    }
-#endif /* 0 */
-
   if (CHARPOS (pos->string_pos) >= 0)
     {
       /* Recorded position is not in an overlay string, but in another
@@ -3133,11 +3114,23 @@ handle_stop (it)
                {
                  if (it->ellipsis_p)
                    setup_for_ellipsis (it, 0);
+                 /* When handling a display spec, we might load an
+                    empty string.  In that case, discard it here.  We
+                    used to discard it in handle_single_display_spec,
+                    but that causes get_overlay_strings_1, above, to
+                    ignore overlay strings that we must check.  */
+                 if (STRINGP (it->string) && !SCHARS (it->string))
+                   pop_it (it);
                  return;
                }
-             it->ignore_overlay_strings_at_pos_p = 1;
-             it->string_from_display_prop_p = 0;
-             handle_overlay_change_p = 0;
+             else if (STRINGP (it->string) && !SCHARS (it->string))
+               pop_it (it);
+             else
+               {
+                 it->ignore_overlay_strings_at_pos_p = 1;
+                 it->string_from_display_prop_p = 0;
+                 handle_overlay_change_p = 0;
+               }
              handled = HANDLED_RECOMPUTE_PROPS;
              break;
            }
@@ -4002,11 +3995,8 @@ handle_display_prop (it)
     }
   else
     {
-      int ret = handle_single_display_spec (it, prop, object, overlay,
-                                           position, 0);
-      if (ret < 0)  /* Replaced by "", i.e. nothing. */
-       return HANDLED_RECOMPUTE_PROPS;
-      if (ret)
+      if (handle_single_display_spec (it, prop, object, overlay,
+                                     position, 0))
        display_replaced_p = 1;
     }
 
@@ -4053,8 +4043,7 @@ display_prop_end (it, object, start_pos)
    property ends.
 
    Value is non-zero if something was found which replaces the display
-   of buffer or string text.  Specifically, the value is -1 if that
-   "something" is "nothing". */
+   of buffer or string text.  */
 
 static int
 handle_single_display_spec (it, spec, object, overlay, position,
@@ -4379,11 +4368,6 @@ handle_single_display_spec (it, spec, object, overlay, position,
 
       if (STRINGP (value))
        {
-         if (SCHARS (value) == 0)
-           {
-             pop_it (it);
-             return -1;  /* Replaced by "", i.e. nothing.  */
-           }
          it->string = value;
          it->multibyte_p = STRING_MULTIBYTE (it->string);
          it->current.overlay_string_index = -1;
@@ -4679,6 +4663,7 @@ handle_composition_prop (it)
 
       if (it->cmp_it.id >= 0)
        {
+         it->cmp_it.ch = -1;
          it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
          it->cmp_it.nglyphs = -1;
        }
@@ -5031,7 +5016,11 @@ get_overlay_strings_1 (it, charpos, compute_stop_p)
       /* Save IT's settings.  They are restored after all overlay
         strings have been processed.  */
       xassert (!compute_stop_p || it->sp == 0);
-      push_it (it);
+
+      /* When called from handle_stop, there might be an empty display
+         string loaded.  In that case, don't bother saving it.  */
+      if (!STRINGP (it->string) || SCHARS (it->string))
+       push_it (it);
 
       /* Set up IT to deliver display elements from the first overlay
         string.  */
@@ -5939,14 +5928,51 @@ get_next_display_element (it)
   if (it->face_box_p
       && it->s == NULL)
     {
-      int face_id;
-      struct face *face;
+      if (it->method == GET_FROM_STRING && it->sp)
+       {
+         int face_id = underlying_face_id (it);
+         struct face *face = FACE_FROM_ID (it->f, face_id);
 
-      it->end_of_box_run_p
-       = ((face_id = face_after_it_pos (it),
-           face_id != it->face_id)
-          && (face = FACE_FROM_ID (it->f, face_id),
-              face->box == FACE_NO_BOX));
+         if (face)
+           {
+             if (face->box == FACE_NO_BOX)
+               {
+                 /* If the box comes from face properties in a
+                    display string, check faces in that string.  */
+                 int string_face_id = face_after_it_pos (it);
+                 it->end_of_box_run_p
+                   = (FACE_FROM_ID (it->f, string_face_id)->box
+                      == FACE_NO_BOX);
+               }
+             /* Otherwise, the box comes from the underlying face.
+                If this is the last string character displayed, check
+                the next buffer location.  */
+             else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
+                      && (it->current.overlay_string_index
+                          == it->n_overlay_strings - 1))
+               {
+                 EMACS_INT ignore;
+                 int next_face_id;
+                 struct text_pos pos = it->current.pos;
+                 INC_TEXT_POS (pos, it->multibyte_p);
+
+                 next_face_id = face_at_buffer_position
+                   (it->w, CHARPOS (pos), it->region_beg_charpos,
+                    it->region_end_charpos, &ignore,
+                    (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), 0);
+                 it->end_of_box_run_p
+                   = (FACE_FROM_ID (it->f, next_face_id)->box
+                      == FACE_NO_BOX);
+               }
+           }
+       }
+      else
+       {
+         int face_id = face_after_it_pos (it);
+         it->end_of_box_run_p
+           = (face_id != it->face_id
+              && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX);
+       }
     }
 
   /* Value is 0 if end of buffer or string reached.  */
@@ -6406,10 +6432,7 @@ next_element_from_buffer (it)
 {
   int success_p = 1;
 
-  /* Check this assumption, otherwise, we would never enter the
-     if-statement, below.  */
-  xassert (IT_CHARPOS (*it) >= BEGV
-          && IT_CHARPOS (*it) <= it->stop_charpos);
+  xassert (IT_CHARPOS (*it) >= BEGV);
 
   if (IT_CHARPOS (*it) >= it->stop_charpos)
     {
@@ -6572,7 +6595,7 @@ next_element_from_composition (it)
       it->object = it->w->buffer;
       it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
                                     IT_BYTEPOS (*it), Qnil);
-    }    
+    }
   return 1;
 }
 
@@ -7183,7 +7206,8 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
            break;
        }
       else if (BUFFERP (it->object)
-              && it->method == GET_FROM_BUFFER
+              && (it->method == GET_FROM_BUFFER
+                  || it->method == GET_FROM_STRETCH)
               && IT_CHARPOS (*it) >= to_charpos)
        skip = MOVE_POS_MATCH_OR_ZV;
       else
@@ -7216,8 +7240,19 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
             associated with the tab are displayed on the current
             line.  Since it->current_x does not include these glyphs,
             we use it->last_visible_x instead.  */
-         it->continuation_lines_width +=
-           (it->c == '\t') ? it->last_visible_x : it->current_x;
+         if (it->c == '\t')
+           {
+             it->continuation_lines_width += it->last_visible_x;
+             /* When moving by vpos, ensure that the iterator really
+                advances to the next line (bug#847, bug#969).  Fixme:
+                do we need to do this in other circumstances?  */
+             if (it->current_x != it->last_visible_x
+                 && (op & MOVE_TO_VPOS)
+                 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
+               set_iterator_to_next (it, 0);
+           }
+         else
+           it->continuation_lines_width += it->current_x;
          break;
 
        default:
@@ -7857,7 +7892,7 @@ message2_nolog (m, nbytes, multibyte)
   struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
 
-  if (noninteractive)
+  if (FRAME_INITIAL_P (sf))
     {
       if (noninteractive_need_newline)
        putc ('\n', stderr);
@@ -7956,7 +7991,7 @@ message3_nolog (m, nbytes, multibyte)
   struct frame *sf = SELECTED_FRAME ();
   message_enable_multibyte = multibyte;
 
-  if (noninteractive)
+  if (FRAME_INITIAL_P (sf))
     {
       if (noninteractive_need_newline)
        putc ('\n', stderr);
@@ -8054,7 +8089,7 @@ message_with_string (m, string, log)
            putc ('\n', stderr);
          noninteractive_need_newline = 0;
          fprintf (stderr, m, SDATA (string));
-         if (cursor_in_echo_area == 0)
+         if (!cursor_in_echo_area)
            fprintf (stderr, "\n");
          fflush (stderr);
        }
@@ -8225,7 +8260,7 @@ ensure_echo_area_buffers ()
        sprintf (name, " *Echo Area %d*", i);
        echo_buffer[i] = Fget_buffer_create (build_string (name));
        XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
-       /* to force word wrap in echo area - 
+       /* to force word wrap in echo area -
           it was decided to postpone this*/
        /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
 
@@ -11266,7 +11301,7 @@ redisplay_internal (preserve_echo_area)
   /* No redisplay if running in batch mode or frame is not yet fully
      initialized, or redisplay is explicitly turned off by setting
      Vinhibit_redisplay.  */
-  if (noninteractive
+  if (FRAME_INITIAL_P (SELECTED_FRAME ())
       || !NILP (Vinhibit_redisplay))
     return;
 
@@ -11345,7 +11380,7 @@ redisplay_internal (preserve_echo_area)
   if (face_change_count)
     ++windows_or_buffers_changed;
 
-  if (FRAME_TERMCAP_P (sf)
+  if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
       && FRAME_TTY (sf)->previous_frame != sf)
     {
       /* Since frames on a single ASCII terminal share the same
@@ -12602,17 +12637,15 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   /* Compute scroll margin height in pixels.  We scroll when point is
      within this distance from the top or bottom of the window.  */
   if (scroll_margin > 0)
-    {
-      this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
-      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
-    }
+    this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+      * FRAME_LINE_HEIGHT (f);
   else
     this_scroll_margin = 0;
 
   /* Force scroll_conservatively to have a reasonable value, to avoid
-     overflow while computing how much to scroll.  Note that it's
-     fairly common for users to supply scroll-conservatively equal to
-     `most-positive-fixnum', which can be larger than INT_MAX.  */
+     overflow while computing how much to scroll.  Note that the user
+     can supply scroll-conservatively equal to `most-positive-fixnum',
+     which can be larger than INT_MAX.  */
   if (scroll_conservatively > scroll_limit)
     {
       scroll_conservatively = scroll_limit;
@@ -12634,7 +12667,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
  too_near_end:
 
-  /* Decide whether we have to scroll down.  */
+  /* Decide whether to scroll down.  */
   if (PT > CHARPOS (startp))
     {
       int scroll_margin_y;
@@ -12649,17 +12682,17 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
       if (PT > CHARPOS (it.current.pos))
        {
-         /* Point is in the scroll margin at the bottom of the
-            window, or below.  Compute the distance from the scroll
-            margin to PT, and give up if the distance is greater than
-            scroll_max.  */
-         move_it_to (&it, PT, -1, it.last_visible_y - 1, -1,
-                     MOVE_TO_POS | MOVE_TO_Y);
+         int y0 = line_bottom_y (&it);
 
-         /* To make point visible, we must move the window start down
-            so that the cursor line is visible, which means we have
-            to add in the height of the cursor line.  */
-         dy = line_bottom_y (&it) - scroll_margin_y;
+         /* Compute the distance from the scroll margin to PT
+            (including the height of the cursor line).  Moving the
+            iterator unconditionally to PT can be slow if PT is far
+            away, so stop 10 lines past the window bottom (is there a
+            way to do the right thing quickly?).  */
+         move_it_to (&it, PT, -1,
+                     it.last_visible_y + 10 * FRAME_LINE_HEIGHT (f),
+                     -1, MOVE_TO_POS | MOVE_TO_Y);
+         dy = line_bottom_y (&it) - y0;
 
          if (dy > scroll_max)
            return SCROLLING_FAILED;
@@ -12670,14 +12703,11 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
   if (scroll_down_p)
     {
-      /* Move the window start down.  If scrolling conservatively,
-        move it just enough down to make point visible.  If
-        scroll_step is set, move it down by scroll_step.  */
-      start_display (&it, w, startp);
-
+      /* Point is in or below the bottom scroll margin, so move the
+        window start down.  If scrolling conservatively, move it just
+        enough down to make point visible.  If scroll_step is set,
+        move it down by scroll_step.  */
       if (scroll_conservatively)
-       /* Set AMOUNT_TO_SCROLL to at least one line,
-          and at most scroll_conservatively lines.  */
        amount_to_scroll
          = min (max (dy, FRAME_LINE_HEIGHT (f)),
                 FRAME_LINE_HEIGHT (f) * scroll_conservatively);
@@ -12699,10 +12729,10 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       if (amount_to_scroll <= 0)
        return SCROLLING_FAILED;
 
-      /* If moving by amount_to_scroll leaves STARTP unchanged,
-        move it down one screen line.  */
-
+      start_display (&it, w, startp);
       move_it_vertically (&it, amount_to_scroll);
+
+      /* If STARTP is unchanged, move it down another screen line.  */
       if (CHARPOS (it.current.pos) == CHARPOS (startp))
        move_it_by_lines (&it, 1, 1);
       startp = it.current.pos;
@@ -14364,13 +14394,6 @@ try_window_reusing_current_matrix (w)
        if (display_line (&it))
          last_text_row = it.glyph_row - 1;
 
-      /* Give up If point isn't in a row displayed or reused.  */
-      if (w->cursor.vpos < 0)
-       {
-         clear_glyph_matrix (w->desired_matrix);
-         return 0;
-       }
-
       /* If point is in a reused row, adjust y and vpos of the cursor
         position.  */
       if (pt_row)
@@ -14379,6 +14402,16 @@ try_window_reusing_current_matrix (w)
          w->cursor.y -= first_reusable_row->y - start_row->y;
        }
 
+      /* Give up if point isn't in a row displayed or reused.  (This
+        also handles the case where w->cursor.vpos < nrows_scrolled
+        after the calls to display_line, which can happen with scroll
+        margins.  See bug#1295.)  */
+      if (w->cursor.vpos < 0)
+       {
+         clear_glyph_matrix (w->desired_matrix);
+         return 0;
+       }
+
       /* Scroll the display.  */
       run.current_y = first_reusable_row->y;
       run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
@@ -19665,7 +19698,7 @@ fill_glyph_string (s, face_id, start, end, overlaps)
   xassert (s->nchars == 0);
   xassert (start >= 0 && end > start);
 
-  s->for_overlaps = overlaps,
+  s->for_overlaps = overlaps;
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
@@ -20454,6 +20487,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
   for (s = head; s; s = s->next)
     FRAME_RIF (f)->draw_glyph_string (s);
 
+#ifndef HAVE_NS
+  /* When focus a sole frame and move horizontally, this sets on_p to 0
+     causing a failure to erase prev cursor position. */
   if (area == TEXT_AREA
       && !row->full_width_p
       /* When drawing overlapping rows, only the glyph strings'
@@ -20470,6 +20506,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps)
       notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
                                 row->y, MATRIX_ROW_BOTTOM_Y (row));
     }
+#endif
 
   /* Value is the x-position up to which drawn, relative to AREA of W.
      This doesn't include parts drawn because of overhangs.  */
@@ -25026,9 +25063,10 @@ all the functions in the list are called, with the frame as argument.  */);
 
   DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
     doc: /* List of functions to call before redisplaying a window with scrolling.
-Each function is called with two arguments, the window
-and its new display-start position.  Note that the value of `window-end'
-is not valid when these functions are called.  */);
+Each function is called with two arguments, the window and its new
+display-start position.  Note that these functions are also called by
+`set-window-buffer'.  Also note that the value of `window-end' is not
+valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
 
   DEFVAR_LISP ("window-text-change-functions",