(VALBITS, GCTYPEBITS): Deleted; default is better.
[bpt/emacs.git] / src / xdisp.c
index 5a519b9..1b2324c 100644 (file)
@@ -122,7 +122,8 @@ int scroll_step;
  since the last redisplay that paused */
 static int blank_end_of_window;
 
-/* Number of windows showing the buffer of the selected window.
+/* Number of windows showing the buffer of the selected window
+   (or another buffer with the same base buffer).
    keyboard.c refers to this.  */
 int buffer_shared;
 
@@ -200,6 +201,9 @@ int windows_or_buffers_changed;
    and it displayed a line number.  */
 int line_number_displayed;
 
+/* Nonzero if display_mode_line needs to handle %c.  */
+int column_number_displayed;
+
 /* Maximum buffer size for which to display line numbers.  */
 int line_number_display_limit;
 \f
@@ -287,6 +291,7 @@ int message_buf_print;
 void
 message (m, a1, a2, a3)
      char *m;
+     EMACS_INT a1, a2, a3;
 {
   if (noninteractive)
     {
@@ -323,7 +328,7 @@ message (m, a1, a2, a3)
            {
              int len;
 #ifdef NO_ARG_ARRAY
-             int a[3];
+             EMACS_INT a[3];
              a[0] = a1;
              a[1] = a2;
              a[2] = a3;
@@ -347,6 +352,12 @@ message (m, a1, a2, a3)
     }
 }
 
+void
+update_echo_area ()
+{
+  message2 (echo_area_glyphs, echo_area_glyphs_length);
+}
+
 static void
 echo_area_display ()
 {
@@ -454,6 +465,7 @@ x_consider_frame_title (frame)
 }
 #else
 #define frame_title_ptr ((char *)0)
+#define store_frame_title(str, mincol, maxcol) 0
 #endif
 \f
 /* Prepare for redisplay by updating menu-bar item lists when appropriate.
@@ -537,6 +549,10 @@ prepare_menu_bars ()
 
 static int do_verify_charstarts;
 
+/* Counter is used to clear the face cache
+   no more than once ever 1000 redisplays.  */
+static int clear_face_cache_count;
+
 void
 redisplay ()
 {
@@ -571,12 +587,12 @@ redisplay ()
       frame_garbaged = 0;
     }
 
-  if (clip_changed || windows_or_buffers_changed)
+  if (clip_changed || windows_or_buffers_changed || column_number_displayed)
     update_mode_lines++;
 
   /* Detect case that we need to write a star in the mode line.  */
   if (XFASTINT (w->last_modified) < MODIFF
-      && XFASTINT (w->last_modified) <= current_buffer->save_modified)
+      && XFASTINT (w->last_modified) <= SAVE_MODIFF)
     {
       w->update_mode_line = Qt;
       if (buffer_shared > 1)
@@ -630,7 +646,7 @@ redisplay ()
              && GPT >= tlbufpos
              /* If selective display, can't optimize
                 if the changes start at the beginning of the line.  */
-             && ((XTYPE (current_buffer->selective_display) == Lisp_Int
+             && ((INTEGERP (current_buffer->selective_display)
                   && XINT (current_buffer->selective_display) > 0
                   ? (beg_unchanged >= tlbufpos
                      && GPT > tlbufpos)
@@ -724,14 +740,20 @@ redisplay ()
   this_line_bufpos = 0;
   all_windows |= buffer_shared > 1;
 
+  clear_face_cache_count++;
+
   if (all_windows)
     {
       Lisp_Object tail, frame;
 
-#ifdef HAVE_X_WINDOWS
-      /* Since we're doing a thorough redisplay, we might as well
-        recompute all our display faces.  */
-      clear_face_vector ();
+#ifdef HAVE_FACES
+      /* Clear the face cache, only when we do a full redisplay
+        and not too often either.  */
+      if (clear_face_cache_count > 1000)
+       {
+         clear_face_cache ();
+         clear_face_cache_count = 0;
+       }
 #endif
 
       /* Recompute # windows showing selected buffer.
@@ -782,7 +804,7 @@ update:
        {
          FRAME_PTR f;
 
-         if (XTYPE (XCONS (tail)->car) != Lisp_Frame)
+         if (!FRAMEP (XCONS (tail)->car))
            continue;
 
          f = XFRAME (XCONS (tail)->car);
@@ -849,16 +871,16 @@ update:
       beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
       end_unchanged = BUF_Z (b) - BUF_GPT (b);
 
-      XFASTINT (w->last_point) = BUF_PT (b);
-      XFASTINT (w->last_point_x) = FRAME_CURSOR_X (selected_frame);
-      XFASTINT (w->last_point_y) = FRAME_CURSOR_Y (selected_frame);
+      XSETFASTINT (w->last_point, BUF_PT (b));
+      XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
+      XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
 
       if (all_windows)
        mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
       else
        {
          w->update_mode_line = Qnil;
-         XFASTINT (w->last_modified) = BUF_MODIFF (b);
+         XSETFASTINT (w->last_modified, BUF_MODIFF (b));
          w->window_end_valid = w->buffer;
          last_arrow_position = Voverlay_arrow_position;
          last_arrow_string = Voverlay_arrow_string;
@@ -920,15 +942,13 @@ mark_window_display_accurate (window, flag)
 
   for (;!NILP (window); window = w->next)
     {
-      if (XTYPE (window) != Lisp_Window) abort ();
+      if (!WINDOWP (window)) abort ();
       w = XWINDOW (window);
 
       if (!NILP (w->buffer))
        {
-         XFASTINT (w->last_modified)
-           = !flag ? 0
-             : XBUFFER (w->buffer) == current_buffer
-               ? MODIFF : BUF_MODIFF (XBUFFER (w->buffer));
+         XSETFASTINT (w->last_modified,
+                      !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
 
          /* Record if we are showing a region, so can make sure to
             update it fully at next redisplay.  */
@@ -996,7 +1016,7 @@ update_menu_bar (f)
          || !NILP (w->update_mode_line)
          || (XFASTINT (w->last_modified) < MODIFF
              && (XFASTINT (w->last_modified)
-                 <= XBUFFER (w->buffer)->save_modified)))
+                 <= BUF_SAVE_MODIFF (XBUFFER (w->buffer)))))
        {
          struct buffer *prev = current_buffer;
          call1 (Vrun_hooks, Qmenu_bar_update_hook);
@@ -1091,14 +1111,24 @@ redisplay_window (window, just_this_one)
 
   /* Otherwise set up data on this window; select its buffer and point value */
 
-  current_buffer = XBUFFER (w->buffer);
+  set_buffer_temp (XBUFFER (w->buffer));
   opoint = PT;
 
-  /* Count number of windows showing the selected buffer.  */
+  /* Count number of windows showing the selected buffer.
+     An indirect buffer counts as its base buffer.  */
 
-  if (!just_this_one
-      && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer))
-    buffer_shared++;
+  if (!just_this_one)
+    {
+      struct buffer *current_base, *window_base;
+      current_base = current_buffer;
+      window_base = XBUFFER (XWINDOW (selected_window)->buffer);
+      if (current_base->base_buffer)
+       current_base = current_base->base_buffer;
+      if (window_base->base_buffer)
+       window_base = window_base->base_buffer;
+      if (current_base == window_base)
+       buffer_shared++;
+    }
 
   /* POINT refers normally to the selected window.
      For any other window, set up appropriate value.  */
@@ -1120,6 +1150,25 @@ redisplay_window (window, just_this_one)
       BUF_PT (current_buffer) = new_pt;
     }
 
+  /* If any of the character widths specified in the display table
+     have changed, invalidate the width run cache.  It's true that this
+     may be a bit late to catch such changes, but the rest of
+     redisplay goes (non-fatally) haywire when the display table is
+     changed, so why should we worry about doing any better?  */
+  if (current_buffer->width_run_cache)
+    {
+      struct Lisp_Vector *disptab = buffer_display_table ();
+
+      if (! disptab_matches_widthtab (disptab,
+                                      XVECTOR (current_buffer->width_table)))
+        {
+          invalidate_region_cache (current_buffer,
+                                   current_buffer->width_run_cache,
+                                   BEG, Z);
+          recompute_width_table (current_buffer, disptab);
+        }
+    }
+
   /* If window-start is screwed up, choose a new one.  */
   if (XMARKER (w->start)->buffer != current_buffer)
     goto recenter;
@@ -1134,13 +1183,12 @@ redisplay_window (window, just_this_one)
       w->base_line_number = Qnil;
       w->update_mode_line = Qt;
       w->force_start = Qnil;
-      XFASTINT (w->last_modified) = 0;
+      XSETFASTINT (w->last_modified, 0);
       if (startp < BEGV) startp = BEGV;
       if (startp > ZV)   startp = ZV;
       try_window (window, startp);
       if (cursor_vpos < 0)
        {
-         /* ??? What should happen here if highlighting a region?  */
          /* If point does not appear, move point so it does appear */
          pos = *compute_motion (startp, 0,
                                ((EQ (window, minibuf_window) && startp == 1)
@@ -1160,6 +1208,14 @@ redisplay_window (window, just_this_one)
              FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left);
              FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
            }
+         /* If we are highlighting the region,
+            then we just changed the region, so redisplay to show it.  */
+         if (!NILP (Vtransient_mark_mode)
+             && !NILP (current_buffer->mark_active))
+           {
+             cancel_my_columns (XWINDOW (window));
+             try_window (window, startp);
+           }
        }
       goto done;
     }
@@ -1262,7 +1318,7 @@ redisplay_window (window, just_this_one)
        cancel_my_columns (w);
     }
 
-  XFASTINT (w->last_modified) = 0;
+  XSETFASTINT (w->last_modified, 0);
   w->update_mode_line = Qt;
 
   /* Try to scroll by specified few lines */
@@ -1314,7 +1370,7 @@ done:
        /* If window not full width, must redo its mode line
          if the window to its side is being redone */
        || (!just_this_one && width < FRAME_WIDTH (f) - 1)
-       || INTEGERP (w->base_line_pos))
+       || INTEGERP (w->base_line_pos) || column_number_displayed)
       && height != XFASTINT (w->height))
     display_mode_line (w);
   if (! line_number_displayed
@@ -1370,7 +1426,7 @@ done:
     }
 
   BUF_PT (current_buffer) = opoint;
-  current_buffer = old;
+  set_buffer_temp (old);
   BUF_PT (current_buffer) = lpoint;
 }
 \f
@@ -1425,8 +1481,8 @@ try_window (window, pos)
     w->update_mode_line = Qt;
 
   /* Say where last char on frame will be, once redisplay is finished.  */
-  XFASTINT (w->window_end_pos) = Z - pos;
-  XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
+  XSETFASTINT (w->window_end_pos, Z - pos);
+  XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
   /* But that is not valid info until redisplay finishes.  */
   w->window_end_valid = Qnil;
 }
@@ -1455,10 +1511,9 @@ try_window_id (window)
   register int i, tem;
   int last_text_vpos = 0;
   int stop_vpos;
-  int selective
-    = XTYPE (current_buffer->selective_display) == Lisp_Int
-      ? XINT (current_buffer->selective_display)
-       : !NILP (current_buffer->selective_display) ? -1 : 0;
+  int selective = (INTEGERP (current_buffer->selective_display)
+                  ? XINT (current_buffer->selective_display)
+                  : !NILP (current_buffer->selective_display) ? -1 : 0);
 
   struct position val, bp, ep, xp, pp;
   int scroll_amount = 0;
@@ -1488,8 +1543,8 @@ try_window_id (window)
          bp = *compute_motion (start, 0, lmargin,
                                Z, height, 0,
                                width, hscroll, pos_tab_offset (w, start), w);
-         XFASTINT (w->window_end_vpos) = height;
-         XFASTINT (w->window_end_pos) = Z - bp.bufpos;
+         XSETFASTINT (w->window_end_vpos, height);
+         XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
          return 1;
        }
       return 0;
@@ -1580,7 +1635,8 @@ try_window_id (window)
       if (i == xp.bufpos)
        return -2;
 
-      XFASTINT (w->window_end_vpos) += scroll_amount;
+      XSETFASTINT (w->window_end_vpos,
+                  XFASTINT (w->window_end_vpos) + scroll_amount);
 
       /* Before doing any scrolling, verify that point will be on frame. */
       if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.bufpos < height))
@@ -1726,8 +1782,8 @@ try_window_id (window)
         include the split character in the text considered on the frame */
       if (val.hpos < lmargin)
        val.bufpos++;
-      XFASTINT (w->window_end_vpos) = last_text_vpos;
-      XFASTINT (w->window_end_pos) = Z - val.bufpos;
+      XSETFASTINT (w->window_end_vpos, last_text_vpos);
+      XSETFASTINT (w->window_end_pos, Z - val.bufpos);
     }
 
   /* If scrolling made blank lines at window bottom,
@@ -1785,8 +1841,9 @@ try_window_id (window)
        {
          val = *vmotion (Z - XFASTINT (w->window_end_pos),
                          delta, width, hscroll, window);
-         XFASTINT (w->window_end_pos) = Z - val.bufpos;
-         XFASTINT (w->window_end_vpos) += val.vpos;
+         XSETFASTINT (w->window_end_pos, Z - val.bufpos);
+         XSETFASTINT (w->window_end_vpos,
+                      XFASTINT (w->window_end_vpos) + val.vpos);
        }
     }
 
@@ -1886,9 +1943,9 @@ redisplay_region (buf, start, end)
     }
 
   /* Increment the buffer's time stamp, but also increment the save
-     and autosave timestamps, so as not to screw up that timekeeping. */
-  if (BUF_MODIFF (buf) == buf->save_modified)
-    buf->save_modified++;
+     and autosave timestamps, so as not to screw up that timekeeping.  */
+  if (BUF_MODIFF (buf) == BUF_SAVE_MODIFF (buf))
+    BUF_SAVE_MODIFF (buf)++;
   if (BUF_MODIFF (buf) == buf->auto_save_modified)
     buf->auto_save_modified++;
 
@@ -1916,7 +1973,7 @@ copy_part_of_rope (f, to, s, from, len, face)
   int last_code = -1;
   int last_merged = 0;
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
   if (! FRAME_TERMCAP_P (f))
     while (n--)
       {
@@ -1961,7 +2018,7 @@ fix_glyph (f, glyph, cface)
      GLYPH glyph;
      int cface;
 {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
   if (! FRAME_TERMCAP_P (f))
     {
       if (FAST_GLYPH_FACE (glyph) != 0)
@@ -1972,15 +2029,20 @@ fix_glyph (f, glyph, cface)
   return glyph;
 }
 \f
-/* Display one line of window w, starting at position START in W's buffer.
-   Display starting at horizontal position HPOS, which is normally zero
-   or negative.  A negative value causes output up to hpos = 0 to be discarded.
-   This is done for negative hscroll, or when this is a continuation line
-   and the continuation occurred in the middle of a multi-column character.
+/* Display one line of window W, starting at position START in W's buffer.
+
+   Display starting at horizontal position HPOS, expressed relative to
+   W's left edge.  In situations where the text at START shouldn't
+   start at the left margin (i.e. when the window is hscrolled, or
+   we're continuing a line which left off in the midst of a
+   multi-column character), HPOS should be negative; we throw away
+   characters up 'til hpos = 0.  So, HPOS must take hscrolling into
+   account.
 
    TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
 
-   Display on position VPOS on the frame.  (origin 0).
+   Display on position VPOS on the frame.  It is origin 0, relative to
+   the top of the frame, not W.
 
    Returns a STRUCT POSITION giving character to start next line with
    and where to display it, including a zero or negative hpos.
@@ -2025,10 +2087,9 @@ display_text_line (w, start, vpos, hpos, taboffset)
     = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active);
   int region_beg, region_end;
 
-  int selective
-    = XTYPE (current_buffer->selective_display) == Lisp_Int
-      ? XINT (current_buffer->selective_display)
-       : !NILP (current_buffer->selective_display) ? -1 : 0;
+  int selective = (INTEGERP (current_buffer->selective_display)
+                  ? XINT (current_buffer->selective_display)
+                  : !NILP (current_buffer->selective_display) ? -1 : 0);
   register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
   register struct Lisp_Vector *dp = window_display_table (w);
 
@@ -2036,20 +2097,20 @@ display_text_line (w, start, vpos, hpos, taboffset)
   /* Nonzero means display something where there are invisible lines.
      The precise value is the number of glyphs to display.  */
   int selective_rlen
-    = (selective && dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
+    = (selective && dp && VECTORP (DISP_INVIS_VECTOR (dp))
        ? XVECTOR (DISP_INVIS_VECTOR (dp))->size
        : selective && !NILP (current_buffer->selective_display_ellipses)
        ? 3 : 0);
   /* This is the sequence of Lisp objects to display
      when there are invisible lines.  */
   Lisp_Object *invis_vector_contents
-    = (dp && XTYPE (DISP_INVIS_VECTOR (dp)) == Lisp_Vector
+    = (dp && VECTORP (DISP_INVIS_VECTOR (dp))
        ? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
        : default_invis_vector);
 
-  GLYPH truncator = (dp == 0 || XTYPE (DISP_TRUNC_GLYPH (dp)) != Lisp_Int
+  GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
                     ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
-  GLYPH continuer = (dp == 0 || XTYPE (DISP_CONTINUE_GLYPH (dp)) != Lisp_Int
+  GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
                     ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
 
   /* The next buffer location at which the face should change, due
@@ -2065,7 +2126,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
   int current_face = 0;
   int i;
 
-  XFASTINT (default_invis_vector[2]) = '.';
+  XSETFASTINT (default_invis_vector[2], '.');
   default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
 
   hpos += XFASTINT (w->left);
@@ -2091,7 +2152,8 @@ display_text_line (w, start, vpos, hpos, taboffset)
   else
     region_beg = region_end = -1;
 
-  if (MINI_WINDOW_P (w) && start == 1
+  if (MINI_WINDOW_P (w)
+      && start == 1
       && vpos == XFASTINT (w->top))
     {
       if (! NILP (minibuf_prompt))
@@ -2099,8 +2161,13 @@ display_text_line (w, start, vpos, hpos, taboffset)
          minibuf_prompt_width
            = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
                               XSTRING (minibuf_prompt)->size, hpos,
-                              (!truncate ? continuer : truncator),
-                              1, -1, -1)
+                              /* Display a space if we truncate.  */
+                              ' ',
+                              1, -1,
+                              /* Truncate the prompt a little before the
+                                 margin, so user input can at least start
+                                 on the first line.  */
+                              w->width > 10 ? w->width - 4 : -1)
               - hpos);
          hpos += minibuf_prompt_width;
        }
@@ -2108,13 +2175,45 @@ display_text_line (w, start, vpos, hpos, taboffset)
        minibuf_prompt_width = 0;
     }
 
-  desired_glyphs->bufp[vpos] = pos;
+  end = ZV;
+
+  /* If we're hscrolled at all, use compute_motion to skip over any
+     text off the left edge of the window.  compute_motion may know
+     tricks to do this faster than we can.  */
+  if (hpos < 0)
+    {
+      struct position *left_edge
+        = compute_motion (pos, vpos, hpos,
+                          end, vpos, 0,
+                          width, hscroll, taboffset, w);
+
+      /* Retrieve the buffer position and column provided by
+         compute_motion.  We can't assume that the column will be
+         zero, because you may have multi-column characters crossing
+         the left margin.  
+
+         compute_motion may have moved us past the screen position we
+         requested, if we hit a multi-column character, or the end of
+         the line.  If so, back up.  */
+      if (left_edge->vpos > vpos
+          || left_edge->hpos > 0)
+        {
+          pos = left_edge->bufpos - 1;
+          hpos = left_edge->prevhpos;
+        }
+      else
+        {
+          pos = left_edge->bufpos;
+          hpos = left_edge->hpos;
+        }
+    }
+
+  desired_glyphs->bufp[vpos] = start;
   p1 = desired_glyphs->glyphs[vpos] + hpos;
   p1start = p1;
   charstart = desired_glyphs->charstarts[vpos] + hpos;
   /* In case we don't ever write anything into it...  */
   desired_glyphs->charstarts[vpos][XFASTINT (w->left)] = -1;
-  end = ZV;
   leftmargin = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
   endp = leftmargin + width;
 
@@ -2165,14 +2264,14 @@ display_text_line (w, start, vpos, hpos, taboffset)
          while (pos == next_invisible && pos < end)
            {
              Lisp_Object position, limit, endpos, prop, ww;
-             XFASTINT (position) = pos;
-             XSET (ww, Lisp_Window, w);
+             XSETFASTINT (position, pos);
+             XSETWINDOW (ww, w);
              prop = Fget_char_property (position, Qinvisible, ww);
              /* This is just an estimate to give reasonable
                 performance; nothing should go wrong if it is too small.  */
              limit = Fnext_overlay_change (position);
              if (XFASTINT (limit) > pos + 50)
-               XFASTINT (limit) = pos + 50;
+               XSETFASTINT (limit, pos + 50);
              endpos = Fnext_single_property_change (position, Qinvisible,
                                                Fcurrent_buffer (), limit);
              if (INTEGERP (endpos))
@@ -2193,7 +2292,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
            break;
 #endif
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
          /* Did we hit a face change?  Figure out what face we should
             use now.  We also hit this the first time through the
             loop, to see what face we should start with.  */
@@ -2223,7 +2322,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
        }
       c = *p++;
       if (c >= 040 && c < 0177
-         && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
+         && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
        {
          if (p1 >= leftmargin)
            *p1 = MAKE_GLYPH (f, c, current_face);
@@ -2249,7 +2348,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
              copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
                                 (p1 - p1prev), current_face);
            }
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
          /* Draw the face of the newline character as extending all the 
             way to the end of the frame line.  */
          if (current_face)
@@ -2286,7 +2385,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
              copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
                                 (p1 - p1prev), current_face);
            }
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
          /* Draw the face of the newline character as extending all the 
             way to the end of the frame line.  */
          if (current_face)
@@ -2299,7 +2398,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
 #endif
          break;
        }
-      else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
+      else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
        {
          p1 = copy_part_of_rope (f, p1, leftmargin,
                                  XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
@@ -2309,7 +2408,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
       else if (c < 0200 && ctl_arrow)
        {
          if (p1 >= leftmargin)
-           *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
+           *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
                                 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
                             current_face);
          p1++;
@@ -2320,7 +2419,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
       else
        {
          if (p1 >= leftmargin)
-           *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
+           *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
                                 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
                             current_face);
          p1++;
@@ -2502,7 +2601,10 @@ display_text_line (w, start, vpos, hpos, taboffset)
          them when the scroll bar windows are flickering around to be
          reconfigured.  */
       *p1++ = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-              ? ' ' : '|');
+              ? ' '
+              : (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
+                 ? DISP_BORDER_GLYPH (dp)
+                 : '|'));
     }
   desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
                                   p1 - desired_glyphs->glyphs[vpos]);
@@ -2511,10 +2613,10 @@ display_text_line (w, start, vpos, hpos, taboffset)
   /* If the start of this line is the overlay arrow-position,
      then put the arrow string into the display-line.  */
 
-  if (XTYPE (Voverlay_arrow_position) == Lisp_Marker
+  if (MARKERP (Voverlay_arrow_position)
       && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
       && start == marker_position (Voverlay_arrow_position)
-      && XTYPE (Voverlay_arrow_string) == Lisp_String
+      && STRINGP (Voverlay_arrow_string)
       && ! overlay_arrow_seen)
     {
       unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
@@ -2524,7 +2626,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
 
       if (len > width)
        len = width;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
       if (!NULL_INTERVAL_P (XSTRING (Voverlay_arrow_string)->intervals))
        {
          /* If the arrow string has text props, obey them when displaying.  */
@@ -2534,14 +2636,14 @@ display_text_line (w, start, vpos, hpos, taboffset)
              Lisp_Object face, ilisp;
              int newface;
 
-             XFASTINT (ilisp) = i;
+             XSETFASTINT (ilisp, i);
              face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
              newface = compute_glyph_face_1 (f, face, 0);
              leftmargin[i] = FAST_MAKE_GLYPH (c, newface);
            }
        }
       else
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_FACES */
        {
          for (i = 0; i < len; i++)
            leftmargin[i] = p[i];
@@ -2587,7 +2689,7 @@ display_menu_bar (w)
       if (NILP (string))
        break;
 
-      XFASTINT (XVECTOR (items)->contents[i + 2]) = hpos;
+      XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos);
 
       if (hpos < maxendcol)
        hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
@@ -2629,6 +2731,7 @@ display_mode_line (w)
   register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
 
   line_number_displayed = 0;
+  column_number_displayed = 0;
 
   get_display_line (f, vpos, left);
   display_mode_element (w, vpos, left, 0, right, right,
@@ -2644,7 +2747,7 @@ display_mode_line (w)
   if (XFASTINT (w->width) == FRAME_WIDTH (f)
       || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f))
     FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_FACES
   else if (! FRAME_TERMCAP_P (f))
     {
       /* For a partial width window, explicitly set face of each glyph. */
@@ -2771,7 +2874,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
            tem = Fsymbol_value (elt);
            /* If value is a string, output that string literally:
               don't check for % within it.  */
-           if (XTYPE (tem) == Lisp_String)
+           if (STRINGP (tem))
              {
                if (frame_title_ptr)
                  hpos = store_frame_title (XSTRING (tem)->data,
@@ -2801,11 +2904,11 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
           If first element is a symbol, process the cadr or caddr recursively
           according to whether the symbol's value is non-nil or nil.  */
        car = XCONS (elt)->car;
-       if (XTYPE (car) == Lisp_Symbol)
+       if (SYMBOLP (car))
          {
            tem = Fboundp (car);
            elt = XCONS (elt)->cdr;
-           if (XTYPE (elt) != Lisp_Cons)
+           if (!CONSP (elt))
              goto invalid;
            /* elt is now the cdr, and we know it is a cons cell.
               Use its car if CAR has a non-nil value.  */
@@ -2821,12 +2924,12 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
            elt = XCONS (elt)->cdr;
            if (NILP (elt))
              break;
-           else if (XTYPE (elt) != Lisp_Cons)
+           else if (!CONSP (elt))
              goto invalid;
            elt = XCONS (elt)->car;
            goto tail_recurse;
          }
-       else if (XTYPE (car) == Lisp_Int)
+       else if (INTEGERP (car))
          {
            register int lim = XINT (car);
            elt = XCONS (elt)->cdr;
@@ -2851,11 +2954,11 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
              }
            goto tail_recurse;
          }
-       else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons)
+       else if (STRINGP (car) || CONSP (car))
          {
            register int limit = 50;
            /* LIMIT is to protect against circular lists.  */
-           while (XTYPE (elt) == Lisp_Cons && --limit > 0
+           while (CONSP (elt) && --limit > 0
                   && hpos < maxendcol)
              {
                hpos = display_mode_element (w, vpos, hpos, depth,
@@ -2925,7 +3028,7 @@ decode_mode_spec (w, c, maxwidth)
 #if 0
       if (NILP (obj))
        return "[none]";
-      else if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth)
+      else if (STRINGP (obj) && XSTRING (obj)->size > maxwidth)
        {
          bcopy ("...", decode_mode_spec_buf, 3);
          bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3,
@@ -2935,6 +3038,11 @@ decode_mode_spec (w, c, maxwidth)
 #endif
       break;
 
+    case 'c':
+      column_number_displayed = 1;
+      sprintf (decode_mode_spec_buf, "%d", current_column ());
+      return decode_mode_spec_buf;
+
     case 'l':
       {
        int startpos = marker_position (w->start);
@@ -2980,8 +3088,8 @@ decode_mode_spec (w, c, maxwidth)
           go back past it.  */
        if (startpos == BUF_BEGV (b))
          {
-           XFASTINT (w->base_line_number) = topline;
-           XFASTINT (w->base_line_pos) = BUF_BEGV (b);
+           XSETFASTINT (w->base_line_number, topline);
+           XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
          }
        else if (nlines < height + 25 || nlines > height * 3 + 50
                 || linepos == BUF_BEGV (b))
@@ -3006,8 +3114,8 @@ decode_mode_spec (w, c, maxwidth)
                return "??";
              }
 
-           XFASTINT (w->base_line_number) = topline - nlines;
-           XFASTINT (w->base_line_pos) = position;
+           XSETFASTINT (w->base_line_number, topline - nlines);
+           XSETFASTINT (w->base_line_pos, position);
          }
 
        /* Now count lines from the start pos to point.  */
@@ -3034,13 +3142,13 @@ decode_mode_spec (w, c, maxwidth)
     case '*':
       if (!NILP (b->read_only))
        return "%";
-      if (BUF_MODIFF (b) > b->save_modified)
+      if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
        return "*";
       return "-";
 
     case '+':
       /* This differs from %* only for a modified read-only buffer.  */
-      if (BUF_MODIFF (b) > b->save_modified)
+      if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
        return "*";
       if (!NILP (b->read_only))
        return "%";
@@ -3048,7 +3156,7 @@ decode_mode_spec (w, c, maxwidth)
 
     case '&':
       /* This differs from %* in ignoring read-only-ness.  */
-      if (BUF_MODIFF (b) > b->save_modified)
+      if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
        return "*";
       return "-";
 
@@ -3063,11 +3171,11 @@ decode_mode_spec (w, c, maxwidth)
       break;
 
     case 't':                  /* indicate TEXT or BINARY */
-#ifdef MSDOS
-      return NILP (b->buffer_file_type) ? "T" : "B";
-#else /* not MSDOS */
+#ifdef MODE_LINE_BINARY_TEXT
+      return MODE_LINE_BINARY_TEXT (b);
+#else
       return "T";
-#endif /* not MSDOS */
+#endif
 
     case 'p':
       {
@@ -3172,7 +3280,7 @@ decode_mode_spec (w, c, maxwidth)
       }
     }
 
-  if (XTYPE (obj) == Lisp_String)
+  if (STRINGP (obj))
     return (char *) XSTRING (obj)->data;
   else
     return "";
@@ -3209,7 +3317,7 @@ display_scan_buffer (start, count, shortage)
      check only for newlines.  */
   if (! (!NILP (current_buffer->selective_display)
         && !INTEGERP (current_buffer->selective_display)))
-    return scan_buffer ('\n', start, count, shortage, 0);
+    return scan_buffer ('\n', start, 0, count, shortage, 0);
 
   /* The code that follows is like scan_buffer
      but checks for either newline or carriage return.  */
@@ -3358,7 +3466,7 @@ display_string (w, vpos, string, length, hpos, truncate,
   register struct Lisp_Vector *dp = 0;
   int i;
 
-  if (XTYPE (Vstandard_display_table) == Lisp_Vector
+  if (VECTORP (Vstandard_display_table)
       && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
     dp = XVECTOR (Vstandard_display_table);
 
@@ -3377,7 +3485,7 @@ display_string (w, vpos, string, length, hpos, truncate,
            {
              int i;
 
-             for (i = 0; i < VERTICAL_SCROLL_BAR_WIDTH; i++)
+             for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
                *end-- = ' ';
            }
          else
@@ -3409,7 +3517,7 @@ display_string (w, vpos, string, length, hpos, truncate,
        break;
 
       if (c >= 040 && c < 0177
-         && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
+         && (dp == 0 || !VECTORP (DISP_CHAR_VECTOR (dp, c))))
        {
          if (p1 >= start)
            *p1 = c;
@@ -3425,7 +3533,7 @@ display_string (w, vpos, string, length, hpos, truncate,
            }
          while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
        }
-      else if (dp != 0 && XTYPE (DISP_CHAR_VECTOR (dp, c)) == Lisp_Vector)
+      else if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
        {
          p1 = copy_part_of_rope (f, p1, start,
                                  XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
@@ -3435,7 +3543,7 @@ display_string (w, vpos, string, length, hpos, truncate,
       else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
        {
          if (p1 >= start)
-           *p1 = fix_glyph (f, (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int
+           *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
                                 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
                             0);
          p1++;
@@ -3446,7 +3554,7 @@ display_string (w, vpos, string, length, hpos, truncate,
       else
        {
          if (p1 >= start)
-           *p1 = fix_glyph (f, (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int
+           *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
                                 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
                             0);
          p1++;
@@ -3582,12 +3690,12 @@ init_xdisp ()
   if (!noninteractive)
     {
       FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
-      XFASTINT (XWINDOW (root_window)->top) = 0;
+      XSETFASTINT (XWINDOW (root_window)->top, 0);
       set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
-      XFASTINT (mini_w->top) = FRAME_HEIGHT (f) - 1;
+      XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
       set_window_height (minibuf_window, 1, 0);
 
-      XFASTINT (XWINDOW (root_window)->width) = FRAME_WIDTH (f);
-      XFASTINT (mini_w->width) = FRAME_WIDTH (f);
+      XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
+      XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
     }
 }