changeset 20536:8f88438d9f61

(redisplay_internal): Use scan_newline. (try_window_id): Use scan_newline. (display_text_line): Use scan_newline. (pos_tab_indent): Moved from indent,c. Now static. Take POS in bytes and chars. Callers changed. (redisplay_window): Handle byte and char positions. (try_window): Don't move W->start if it's already at right place. (display_count_lines): Several changes in args. Do the work directly. (display_scan_buffer): Function deleted. (decode_mode_spec): Pass new arg. (message_log_check_duplicate): Take charpos and bytepos args. (message_dolog): Use markers to update old PT, BEGV, ZV. Use scan_newline. Handle positions in bytes and chars. (try_window): Pass bytepos to and from display_text_line. (try_window_id): Likewise. Use byte pos as well as charpos. (redisplay_internal): Handle bytepos for tlbufpos. (message): Cast last arg to doprnt.
author Richard M. Stallman <rms@gnu.org>
date Thu, 01 Jan 1998 02:27:27 +0000
parents 3094e3fd9764
children cc87b03bad13
files src/xdisp.c
diffstat 1 files changed, 372 insertions(+), 237 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Thu Jan 01 02:07:14 1998 +0000
+++ b/src/xdisp.c	Thu Jan 01 02:27:27 1998 +0000
@@ -262,6 +262,8 @@
 
 #define COERCE_MARKER(X)	\
   (MARKERP ((X)) ? Fmarker_position (X) : (X))
+
+static int pos_tab_offset P_ ((struct window *, int, int));
 
 /* Output a newline in the *Messages* buffer if "needs" one.  */
 
@@ -285,7 +287,7 @@
   if (!NILP (Vmessage_log_max))
     {
       struct buffer *oldbuf;
-      int oldpoint, oldbegv, oldzv;
+      Lisp_Object oldpoint, oldbegv, oldzv;
       int old_windows_or_buffers_changed = windows_or_buffers_changed;
       int point_at_end = 0;
       int zv_at_end = 0;
@@ -293,16 +295,21 @@
       oldbuf = current_buffer;
       Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
       current_buffer->undo_list = Qt;
-      oldpoint = PT;
-      oldbegv = BEGV;
-      oldzv = ZV;
-      BEGV = BEG;
-      ZV = Z;
+
+      oldpoint = Fpoint_marker ();
+      oldbegv = Fpoint_min_marker ();
+      oldzv = Fpoint_max_marker ();
+
       if (oldpoint == Z)
 	point_at_end = 1;
       if (oldzv == Z)
 	zv_at_end = 1;
-      TEMP_SET_PT (Z);
+
+      BEGV = BEG;
+      BEGV_BYTE = BEG_BYTE;
+      ZV = Z;
+      ZV_BYTE = Z_BYTE;
+      TEMP_SET_PT_BOTH (Z, Z_BYTE);
 
       /* Insert the string--maybe converting multibyte to single byte
 	 or vice versa, so that all the text fits the buffer.  */
@@ -339,27 +346,29 @@
 	    }
 	}
       else if (len)
-	insert_1 (m, len, 1, 0);
+	insert_1 (m, len, 1, 0, 0);
 
       if (nlflag)
 	{
-	  int this_bol, prev_bol, dup;
-	  insert_1 ("\n", 1, 1, 0);
-
-	  this_bol = scan_buffer ('\n', Z, 0, -2, 0, 0);
+	  int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
+	  insert_1 ("\n", 1, 1, 0, 0);
+
+	  scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
+	  this_bol = PT;
+	  this_bol_byte = PT_BYTE;
+
 	  if (this_bol > BEG)
 	    {
-	      prev_bol = scan_buffer ('\n', this_bol, 0, -2, 0, 0);
-	      dup = message_log_check_duplicate (prev_bol, this_bol);
+	      scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
+	      prev_bol = PT;
+	      prev_bol_byte = PT_BYTE;
+
+	      dup = message_log_check_duplicate (prev_bol, this_bol,
+						 prev_bol_byte, this_bol_byte);
 	      if (dup)
 		{
-		  if (oldpoint > prev_bol)
-		    oldpoint -= min (this_bol, oldpoint) - prev_bol;
-		  if (oldbegv > prev_bol)
-		    oldbegv -= min (this_bol, oldbegv) - prev_bol;
-		  if (oldzv > prev_bol)
-		    oldzv -= min (this_bol, oldzv) - prev_bol;
-		  del_range_1 (prev_bol, this_bol, 0);
+		  del_range_both (prev_bol, prev_bol_byte,
+				  this_bol, this_bol_byte, 0);
 		  if (dup > 1)
 		    {
 		      char dupstr[40];
@@ -369,35 +378,42 @@
 			 change message_log_check_duplicate.  */
 		      sprintf (dupstr, " [%d times]", dup);
 		      duplen = strlen (dupstr);
-		      TEMP_SET_PT (Z-1);
-		      if (oldpoint == Z)
-			oldpoint += duplen;
-		      if (oldzv == Z)
-			oldzv += duplen;
-		      insert_1 (dupstr, duplen, 1, 0);
+		      TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
+		      insert_1 (dupstr, duplen, 1, 0, 1);
 		    }
 		}
 	    }
 
 	  if (NATNUMP (Vmessage_log_max))
 	    {
-	      int pos = scan_buffer ('\n', Z, 0,
-				     -XFASTINT (Vmessage_log_max) - 1, 0, 0);
-	      oldpoint -= min (pos, oldpoint) - BEG;
-	      oldbegv -= min (pos, oldbegv) - BEG;
-	      oldzv -= min (pos, oldzv) - BEG;
-	      del_range_1 (BEG, pos, 0);
+	      scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
+			    -XFASTINT (Vmessage_log_max) - 1, 0);
+	      del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
 	    }
 	}
-      BEGV = oldbegv;
+      BEGV = XMARKER (oldbegv)->charpos;
+      BEGV_BYTE = marker_byte_position (oldbegv);
+
       if (zv_at_end)
-	ZV = Z;
+	{
+	  ZV = Z;
+	  ZV_BYTE = Z_BYTE;
+	}
       else
-	ZV = oldzv;
+	{
+	  ZV = XMARKER (oldzv)->charpos;
+	  ZV_BYTE = marker_byte_position (oldzv);
+	}
+
       if (point_at_end)
-	TEMP_SET_PT (Z);
+	TEMP_SET_PT_BOTH (Z, Z_BYTE);
       else
-	TEMP_SET_PT (oldpoint);
+	Fgoto_char (oldpoint);
+
+      free_marker (oldpoint);
+      free_marker (oldbegv);
+      free_marker (oldzv);
+
       set_buffer_internal (oldbuf);
       windows_or_buffers_changed = old_windows_or_buffers_changed;
       message_log_need_newline = !nlflag;
@@ -411,14 +427,15 @@
    value N > 1 if we should also append " [N times]".  */
 
 static int
-message_log_check_duplicate (prev_bol, this_bol)
+message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
      int prev_bol, this_bol;
+     int prev_bol_byte, this_bol_byte;
 {
   int i;
   int len = Z - 1 - this_bol;
   int seen_dots = 0;
-  unsigned char *p1 = BUF_CHAR_ADDRESS (current_buffer, prev_bol);
-  unsigned char *p2 = BUF_CHAR_ADDRESS (current_buffer, this_bol);
+  unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
+  unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
 
   for (i = 0; i < len; i++)
     {
@@ -619,7 +636,8 @@
 			    FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
 #else
 	      len = doprnt (FRAME_MESSAGE_BUF (f),
-			    FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, &a1);
+			    FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
+			    (char **) &a1);
 #endif /* NO_ARG_ARRAY */
 
 	      message2 (FRAME_MESSAGE_BUF (f), len);
@@ -1070,9 +1088,10 @@
 	      && end_unchanged >= tlendpos
 	      && Z - GPT >= tlendpos)))
     {
-      if (tlbufpos > BEGV && FETCH_BYTE (tlbufpos - 1) != '\n'
+      int tlbufpos_byte = CHAR_TO_BYTE (tlbufpos);
+      if (tlbufpos > BEGV && FETCH_BYTE (tlbufpos_byte - 1) != '\n'
 	  && (tlbufpos == ZV
-	      || FETCH_BYTE (tlbufpos) == '\n'))
+	      || FETCH_BYTE (tlbufpos_byte) == '\n'))
 	/* Former continuation line has disappeared by becoming empty */
 	goto cancel;
       else if (XFASTINT (w->last_modified) < MODIFF
@@ -1095,9 +1114,11 @@
 
 	  struct position val;
 	  int prevline;
-
-	  prevline = find_next_newline (tlbufpos, -1);
-	  val = *compute_motion (prevline, 0,
+	  int opoint = PT, opoint_byte = PT_BYTE;
+
+	  scan_newline (tlbufpos, tlbufpos_byte, BEGV, BEGV_BYTE, -1, 1);
+
+	  val = *compute_motion (PT, 0,
 				 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
 				 0,
 				 tlbufpos,
@@ -1105,14 +1126,16 @@
 				 1 << (BITS_PER_SHORT - 1),
 				 window_internal_width (w) - 1,
 				 XINT (w->hscroll), 0, w);
+	  SET_PT_BOTH (opoint, opoint_byte);
 	  if (val.hpos != this_line_start_hpos)
 	    goto cancel;
 
 	  cursor_vpos = -1;
 	  overlay_arrow_seen = 0;
 	  zv_strings_seen = 0;
-	  display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
-			     pos_tab_offset (w, tlbufpos), 0);
+	  display_text_line (w, tlbufpos, tlbufpos_byte,
+			     this_line_vpos, this_line_start_hpos,
+			     pos_tab_offset (w, tlbufpos, tlbufpos_byte), 0);
 	  /* If line contains point, is not continued,
 		 and ends at same distance from eob as before, we win */
 	  if (cursor_vpos >= 0 && this_line_bufpos
@@ -1177,7 +1200,8 @@
 				 PT, 2, - (1 << (BITS_PER_SHORT - 1)),
 				 window_internal_width (w) - 1,
 				 XINT (w->hscroll),
-				 pos_tab_offset (w, tlbufpos), w);
+				 pos_tab_offset (w, tlbufpos, tlbufpos_byte),
+				 w);
 	  if (pos.vpos < 1)
 	    {
 	      int width = window_internal_width (w) - 1;
@@ -1641,17 +1665,24 @@
   register struct window *w = XWINDOW (window);
   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
   int height;
-  register int lpoint = PT;
+  int lpoint = PT;
+  int lpoint_byte = PT_BYTE;
   struct buffer *old = current_buffer;
   register int width = window_internal_width (w) - 1;
-  register int startp;
+  register int startp, startp_byte;
   register int hscroll = XINT (w->hscroll);
   struct position pos;
   int opoint = PT;
+  int opoint_byte = PT_BYTE;
   int tem;
   int update_mode_line;
   struct Lisp_Char_Table *dp = window_display_table (w);
 
+  if (Z == Z_BYTE && lpoint != lpoint_byte)
+    abort ();
+  if (lpoint_byte < lpoint)
+    abort ();
+
   if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
 
   /* If this is a combination window, do its children; that's all.  */
@@ -1706,6 +1737,12 @@
     set_buffer_temp (XBUFFER (w->buffer));
 
   opoint = PT;
+  opoint_byte = PT_BYTE;
+
+  if (Z == Z_BYTE && opoint != opoint_byte)
+    abort ();
+  if (opoint_byte < opoint)
+    abort ();
 
   /* If %c is in mode line, update it if needed.  */
   if (!NILP (w->column_number_displayed)
@@ -1738,19 +1775,22 @@
 
   if (!EQ (window, selected_window))
     {
-      int new_pt = marker_position (w->pointm);
+      int new_pt = XMARKER (w->pointm)->charpos;
+      int new_pt_byte = marker_byte_position (w->pointm);
       if (new_pt < BEGV)
 	{
 	  new_pt = BEGV;
-	  Fset_marker (w->pointm, make_number (new_pt), Qnil);
+	  new_pt_byte = BEGV_BYTE;
+	  set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
 	}
       else if (new_pt > (ZV - 1))
 	{
 	  new_pt = ZV;
-	  Fset_marker (w->pointm, make_number (new_pt), Qnil);
+	  new_pt_byte = ZV_BYTE;
+	  set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
 	}
       /* We don't use SET_PT so that the point-motion hooks don't run.  */
-      BUF_PT (current_buffer) = new_pt;
+      TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
     }
 
   /* If any of the character widths specified in the display table
@@ -1777,6 +1817,7 @@
     goto recenter;
 
   startp = marker_position (w->start);
+  startp_byte = marker_byte_position (w->start);
 
   /* If someone specified a new starting point but did not insist,
      check whether it can be used.  */
@@ -1795,7 +1836,8 @@
 			     /* BUG FIX: See the comment of
                                 Fpos_visible_in_window_p (window.c).  */
 			     - (1 << (BITS_PER_SHORT - 1)),
-			     width, hscroll, pos_tab_offset (w, startp), w);
+			     width, hscroll,
+			     pos_tab_offset (w, startp, startp_byte), w);
       /* If PT does fit on the screen, we will use this start pos,
 	 so do so by setting force_start.  */
       if (pos.bufpos == PT)
@@ -1834,8 +1876,8 @@
 	}
       XSETFASTINT (w->last_modified, 0);
       XSETFASTINT (w->last_overlay_modified, 0);
-      if (startp < BEGV) startp = BEGV;
-      if (startp > ZV)   startp = ZV;
+      if (startp < BEGV) startp = BEGV, startp_byte = BEGV_BYTE;
+      if (startp > ZV)   startp = ZV, startp = ZV_BYTE;
       try_window (window, startp);
       if (cursor_vpos < 0)
 	{
@@ -1848,14 +1890,19 @@
 				 0,
 				 ZV, height / 2,
 				 - (1 << (BITS_PER_SHORT - 1)),
-				 width, hscroll, pos_tab_offset (w, startp), w);
-	  BUF_PT (current_buffer) = pos.bufpos;
+				 width, hscroll,
+				 pos_tab_offset (w, startp, startp_byte),
+				 w);
+	  TEMP_SET_PT_BOTH (pos.bufpos, pos.bytepos);
 	  if (w != XWINDOW (selected_window))
-	    Fset_marker (w->pointm, make_number (PT), Qnil);
+	    set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
 	  else
 	    {
 	      if (current_buffer == old)
-		lpoint = PT;
+		{
+		  lpoint = PT;
+		  lpoint_byte = PT_BYTE;
+		}
 	      FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
 				    + minmax (0, pos.hpos, width));
 	      FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
@@ -1929,7 +1976,8 @@
 				    Fpos_visible_in_window_p (window.c).  */
 				 - (1 << (BITS_PER_SHORT - 1)),
 				 width, hscroll,
-				 pos_tab_offset (w, startp), w);
+				 pos_tab_offset (w, startp, startp_byte),
+				 w);
 	}
       else
 	{
@@ -1939,7 +1987,8 @@
 				    Fpos_visible_in_window_p (window.c).  */
 				 - (1 << (BITS_PER_SHORT - 1)),
 				 width, hscroll,
-				 pos_tab_offset (w, startp), w);
+				 pos_tab_offset (w, startp, startp_byte),
+				 w);
 	}
 
       /* Don't use a scroll margin that is negative or too large.  */
@@ -1983,7 +2032,7 @@
      but no longer is, find a new starting point.  */
   else if (!NILP (w->start_at_line_beg)
 	   && !(startp <= BEGV
-		|| FETCH_BYTE (startp - 1) == '\n'))
+		|| FETCH_BYTE (startp_byte - 1) == '\n'))
     {
       goto recenter;
     }
@@ -2088,7 +2137,8 @@
 	  pos = *compute_motion (scroll_margin_pos, 0, 0, 0,
 				 PT, XFASTINT (w->height), 0,
 				 XFASTINT (w->width), XFASTINT (w->hscroll),
-				 pos_tab_offset (w, startp), w);
+				 pos_tab_offset (w, startp, startp_byte),
+				 w);
 	  if (pos.vpos > scroll_conservatively)
 	    goto scroll_fail_1;
 
@@ -2096,7 +2146,7 @@
 
 	  if (! NILP (Vwindow_scroll_functions))
 	    {
-	      Fset_marker (w->start, make_number (pos.bufpos), Qnil);
+	      set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
 	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
 				    make_number (pos.bufpos));
 	      pos.bufpos = marker_position (w->start);
@@ -2126,7 +2176,8 @@
 	  pos = *compute_motion (PT, 0, 0, 0,
 				 scroll_margin_pos, XFASTINT (w->height), 0,
 				 XFASTINT (w->width), XFASTINT (w->hscroll),
-				 pos_tab_offset (w, startp), w);
+				 pos_tab_offset (w, startp, startp_byte),
+				 w);
 	  if (pos.vpos > scroll_conservatively)
 	    goto scroll_fail_1;
 
@@ -2134,7 +2185,7 @@
 
 	  if (! NILP (Vwindow_scroll_functions))
 	    {
-	      Fset_marker (w->start, make_number (pos.bufpos), Qnil);
+	      set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
 	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
 				    make_number (pos.bufpos));
 	      pos.bufpos = marker_position (w->start);
@@ -2170,7 +2221,7 @@
 	{
 	  if (! NILP (Vwindow_scroll_functions))
 	    {
-	      Fset_marker (w->start, make_number (pos.bufpos), Qnil);
+	      set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
 	      run_hook_with_args_2 (Qwindow_scroll_functions, window,
 				    make_number (pos.bufpos));
 	      pos.bufpos = marker_position (w->start);
@@ -2208,12 +2259,12 @@
       && PT > BEGV + minibuffer_scroll_overlap
       /* If we scrolled to an actual line boundary,
 	 that's different; don't ignore line boundaries.  */
-      && FETCH_CHAR (pos.bufpos - 1) != '\n')
+      && FETCH_BYTE (pos.bufpos - 1) != '\n')
     pos.bufpos = PT - minibuffer_scroll_overlap;
     
   /* Set startp here explicitly in case that helps avoid an infinite loop
      in case the window-scroll-functions functions get errors.  */
-  Fset_marker (w->start, make_number (pos.bufpos), Qnil);
+  set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
   if (! NILP (Vwindow_scroll_functions))
     {
       run_hook_with_args_2 (Qwindow_scroll_functions, window,
@@ -2223,8 +2274,9 @@
   try_window (window, pos.bufpos);
 
   startp = marker_position (w->start);
+  startp_byte = marker_byte_position (w->start);
   w->start_at_line_beg
-    = (startp == BEGV || FETCH_BYTE (startp - 1) == '\n') ? Qt : Qnil;
+    = (startp == BEGV || FETCH_BYTE (startp_byte - 1) == '\n') ? Qt : Qnil;
 
 done:
   if ((update_mode_line
@@ -2291,12 +2343,12 @@
       (*redeem_scroll_bar_hook) (w);
     }
 
-  BUF_PT (current_buffer) = opoint;
+  TEMP_SET_PT_BOTH (opoint, opoint_byte);
   if (update_mode_line)
     set_buffer_internal_1 (old);
   else
     set_buffer_temp (old);
-  BUF_PT (current_buffer) = lpoint;
+  TEMP_SET_PT_BOTH (lpoint, lpoint_byte);
 }
 
 /* Do full redisplay on one window, starting at position `pos'. */
@@ -2319,17 +2371,21 @@
       || pos > XBUFFER (w->buffer)->zv)
     abort ();
 
-  Fset_marker (w->start, make_number (pos), Qnil);
+  if (XMARKER (w->start)->charpos != pos)
+    Fset_marker (w->start, make_number (pos), Qnil);
+
   cursor_vpos = -1;
   overlay_arrow_seen = 0;
   zv_strings_seen = 0;
   val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
   val.ovstring_chars_done = 0;
-  val.tab_offset = pos_tab_offset (w, pos);
+  val.bytepos = marker_byte_position (w->start);
+  val.tab_offset = pos_tab_offset (w, pos, val.bytepos);
 
   while (--height >= 0)
     {
-      val = *display_text_line (w, pos, vpos, val.hpos, val.tab_offset,
+      val = *display_text_line (w, pos, val.bytepos, vpos,
+				val.hpos, val.tab_offset,
 				val.ovstring_chars_done);
       /* The following code is omitted because we maintain tab_offset
          in VAL.  */
@@ -2350,7 +2406,7 @@
 	  last_text_vpos
 	    /* Next line, unless prev line ended in end of buffer with no cr */
 	    = vpos - (val.vpos
-		      && (FETCH_BYTE (val.bufpos - 1) != '\n' || invis));
+		      && (FETCH_BYTE (val.bytepos - 1) != '\n' || invis));
 	}
       pos = val.bufpos;
     }
@@ -2383,7 +2439,8 @@
 try_window_id (window)
      Lisp_Object window;
 {
-  int pos;
+  int pos, pos_byte;
+  int opoint, opoint_byte;
   register struct window *w = XWINDOW (window);
   register int height = window_internal_height (w);
   FRAME_PTR f = XFRAME (w->frame);
@@ -2406,6 +2463,8 @@
   int delta;
   int epto, old_tick;
 
+  int start_byte = marker_byte_position (w->start);
+
   if (GPT - BEG < beg_unchanged)
     beg_unchanged = GPT - BEG;
   if (Z - GPT < end_unchanged)
@@ -2418,9 +2477,11 @@
   bp = *compute_motion (start, 0, lmargin, 0,
 			min (ZV, beg_unchanged + BEG), height,
 			/* BUG FIX: See the comment of
-                           Fpos_visible_in_window_p() (window.c).  */
+                           Fpos_visible_in_window_p (window.c).  */
 			- (1 << (BITS_PER_SHORT - 1)),
-			width, hscroll, pos_tab_offset (w, start), w);
+			width, hscroll,
+			pos_tab_offset (w, start, start_byte),
+			w);
   if (bp.vpos >= height)
     {
       if (PT < bp.bufpos)
@@ -2434,7 +2495,8 @@
 				/* BUG FIX: See the comment of
                                    Fpos_visible_in_window_p() (window.c).  */
 				- (1 << (BITS_PER_SHORT - 1)),
-				width, hscroll, pos_tab_offset (w, start), w);
+				width, hscroll,
+				pos_tab_offset (w, start, start_byte), w);
 	  XSETFASTINT (w->window_end_vpos, height);
 	  XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
 	  goto findpoint;
@@ -2448,6 +2510,7 @@
   bp = *vmotion (bp.bufpos, 0, w);
 
   pos = bp.bufpos;
+  pos_byte = bp.bytepos;
   val.hpos = lmargin;
   if (pos < start)
     return -1;
@@ -2464,6 +2527,7 @@
       bp = *vmotion (bp.bufpos, -1, w);
       --vpos;
       pos = bp.bufpos;
+      pos_byte = bp.bytepos;
     }
   val.tab_offset = bp.tab_offset; /* Update tab offset.  */
 
@@ -2472,16 +2536,21 @@
       val.hpos = bp.prevhpos - width + lmargin;
       val.tab_offset = bp.tab_offset + bp.prevhpos - width;
       did_motion = 1;
-      DEC_POS (pos);
+      pos--;
+      DEC_POS (pos_byte);
     }
 
   bp.vpos = vpos;
 
   /* Find first visible newline after which no more is changed.  */
-  tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
+  opoint = PT, opoint_byte = PT_BYTE;
+  SET_PT (Z - max (end_unchanged, Z - ZV));
+  scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
   if (selective > 0)
-    while (tem < ZV - 1 && (indented_beyond_p (tem, selective)))
-      tem = find_next_newline (tem, 1);
+    while (PT < ZV - 1 && indented_beyond_p (PT, PT_BYTE, selective))
+      scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
+  tem = PT;
+  SET_PT_BOTH (opoint, opoint_byte);
 
   /* Compute the cursor position after that newline.  */
   ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
@@ -2658,12 +2727,14 @@
   if (vpos == 0 && pos < marker_position (w->start))
     Fset_marker (w->start, make_number (pos), Qnil);
 
+  val.bytepos = pos_byte;
+
   /* Redisplay the lines where the text was changed */
   last_text_vpos = vpos;
   /* The following code is omitted because we maintain tab offset in
      val.tab_offset.  */
 #if 0
-  tab_offset = pos_tab_offset (w, pos);
+  tab_offset = pos_tab_offset (w, pos, pos_byte);
   /* If we are starting display in mid-character, correct tab_offset
      to account for passing the line that that character really starts in.  */
   if (val.hpos < lmargin)
@@ -2672,7 +2743,8 @@
   old_tick = MODIFF;
   while (vpos < stop_vpos)
     {
-      val = *display_text_line (w, pos, top + vpos++, val.hpos, val.tab_offset,
+      val = *display_text_line (w, pos, val.bytepos, top + vpos++,
+				val.hpos, val.tab_offset,
 				val.ovstring_chars_done);
       /* If display_text_line ran a hook and changed some text,
 	 redisplay all the way to bottom of buffer
@@ -2715,6 +2787,7 @@
       FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
       vpos = xp.vpos;
       pos = xp.bufpos;
+      pos_byte = xp.bytepos;
       val.hpos = xp.hpos;
       val.tab_offset = xp.tab_offset;
       if (pos == ZV)
@@ -2727,22 +2800,25 @@
 	{
 	  val.hpos = xp.prevhpos - width + lmargin;
 	  val.tab_offset = xp.tab_offset + bp.prevhpos - width;
-	  DEC_POS (pos);
+	  pos--;
+	  DEC_POS (pos_byte);
 	}
 
       blank_end_of_window = 1;
       /* The following code is omitted because we maintain tab offset
 	 in val.tab_offset.  */
 #if 0
-      tab_offset = pos_tab_offset (w, pos);
+      tab_offset = pos_tab_offset (w, pos, pos_byte);
       /* If we are starting display in mid-character, correct tab_offset
 	 to account for passing the line that that character starts in.  */
       if (val.hpos < lmargin)
 	tab_offset += width;
 #endif
+      val.bytepos = pos;
       while (vpos < height)
 	{
-	  val = *display_text_line (w, pos, top + vpos++, val.hpos,
+	  val = *display_text_line (w, pos, val.bytepos,
+				    top + vpos++, val.hpos,
 				    val.tab_offset, val.ovstring_chars_done);
 	  /* The following code is omitted because we maintain tab
 	     offset in val.tab_offset.  */
@@ -2791,7 +2867,9 @@
 			     1 << (BITS_PER_SHORT - 1),
 			     /* ... nor HPOS.  */
 			     1 << (BITS_PER_SHORT - 1),
-			     width, hscroll, pos_tab_offset (w, start), w);
+			     width, hscroll,
+			     pos_tab_offset (w, start, start_byte),
+			     w);
       /* Admit failure if point is off frame now */
       if (val.vpos >= height)
 	{
@@ -2810,7 +2888,9 @@
     {
       val = *compute_motion (start, 0, lmargin, 0, ZV,
 			     height, - (1 << (BITS_PER_SHORT - 1)),
-			     width, hscroll, pos_tab_offset (w, start), w);
+			     width, hscroll,
+			     pos_tab_offset (w, start, start_byte),
+			     w);
       if (val.vpos != XFASTINT (w->window_end_vpos))
 	abort ();
       if (XFASTINT (w->window_end_pos)
@@ -2902,7 +2982,36 @@
   return glyph;
 }
 
-/* Display one line of window W, starting at position START in W's buffer.
+/* Return the column of position POS / POS_BYTE in window W's buffer.
+   The result is rounded down to a multiple of the internal width of W.
+   This is the amount of indentation of position POS
+   that is not visible in its horizontal position in the window.  */
+
+static int
+pos_tab_offset (w, pos, pos_byte)
+     struct window *w;
+     register int pos, pos_byte;
+{
+  int opoint = PT;
+  int opoint_byte = PT_BYTE;
+  int col;
+  int width = window_internal_width (w) - 1;
+
+  if (pos == BEGV)
+    return MINI_WINDOW_P (w) ? -minibuf_prompt_width : 0;
+
+  if (FETCH_BYTE (pos_byte - 1) == '\n')
+    return 0;
+
+  TEMP_SET_PT_BOTH (pos, pos_byte);
+  col = current_column ();
+  TEMP_SET_PT_BOTH (opoint, opoint_byte);
+
+  return col;
+}
+
+/* Display one line of window W, starting at char position START in W's buffer.
+   START_BYTE is the corresponding byte position.
 
    Display starting at horizontal position HPOS, expressed relative to
    W's left edge.  In situations where the text at START shouldn't
@@ -2927,7 +3036,7 @@
 struct position val_display_text_line;
 
 static struct position *
-display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
+display_text_line (w, start, start_byte, vpos, hpos, taboffset, ovstr_done)
      struct window *w;
      int start;
      int vpos;
@@ -2936,22 +3045,23 @@
      int ovstr_done;
 {
   register int pos = start;
+  int pos_byte = start_byte;
   register int c;
   register GLYPH *p1;
-  register int pause;
+  int pause, limit_byte;
   register unsigned char *p;
   GLYPH *endp;
   register GLYPH *leftmargin;
   register GLYPH *p1prev;
   register GLYPH *p1start;
-  int prevpos;
+  int prevpos, prevpos_byte;
   int *charstart;
   FRAME_PTR f = XFRAME (w->frame);
   int tab_width = XINT (current_buffer->tab_width);
   int ctl_arrow = !NILP (current_buffer->ctl_arrow);
   int width = window_internal_width (w) - 1;
   struct position val;
-  int lastpos;
+  int lastpos, lastpos_byte;
   int invis;
   int last_invis_skip = 0;
   Lisp_Object last_invis_prop;
@@ -3101,11 +3211,13 @@
 	  /* Since this should not be a valid multibyte character, we
              can decrease POS by 1.  */
 	  pos--;
+	  pos_byte = left_edge->bytepos - 1;
           hpos = left_edge->prevhpos;
         }
       else
         {
           pos = left_edge->bufpos;
+	  pos_byte = left_edge->bytepos;
           hpos = left_edge->hpos;
         }
     }
@@ -3133,10 +3245,12 @@
      if reach or pass continuation column,
      or at face change.  */
   pause = pos;
+  limit_byte = pos_byte;
   next_face_change = pos;
   next_boundary = pos;
   p1prev = p1;
   prevpos = pos;
+  prevpos_byte = pos_byte;
 
   /* If the window is hscrolled and point is in the invisible part of the
      current line beyond the left margin we can record the cursor location
@@ -3225,8 +3339,6 @@
 	      if (XFASTINT (limit) > pos + 50)
 		{
 		  int limitpos = pos + 50;
-		  if (limitpos < Z)
-		    INC_POS (limitpos); /* Adjust to character boundary.  */
 		  XSETFASTINT (limit, limitpos);
 		}
 	      limit = Fnext_single_property_change (position, Qinvisible,
@@ -3312,8 +3424,6 @@
 	    {
 	      int limit = pos + 50;
 
-	      if (limit < Z && !CHAR_HEAD_P (POS_ADDR (limit)))
-		INC_POS (limit); /* Adjust to character boundary.  */
 	      current_face = compute_char_face (f, w, pos,
 						region_beg, region_end,
 						&next_face_change, limit, 0);
@@ -3340,7 +3450,17 @@
 	  if (pos < GPT && GPT < pause)
 	    pause = GPT;
 
-	  p = POS_ADDR (pos);
+	  /* LIMIT_BYTE is not the same place in the buffer as PAUSE.
+	     It is a limit on valid characters.
+	     We use it to bound STRING_CHAR_AND_LENGTH.  */
+	  limit_byte = ZV_BYTE;
+	  if (pos < GPT && GPT_BYTE < limit_byte)
+	    limit_byte = GPT_BYTE;
+
+	  {
+	    int temp = CHAR_TO_BYTE (pos);
+	    p = BYTE_POS_ADDR (temp);
+	  }
 	}
 
       if (p1 >= endp)
@@ -3349,8 +3469,7 @@
       p1prev = p1;
 
       if (multibyte)
-	/* PAUSE is surely at character boundary.  */
-	c = STRING_CHAR_AND_LENGTH (p, pause - pos, len), p += len;
+	c = STRING_CHAR_AND_LENGTH (p, limit_byte - pos_byte, len), p += len;
       else
 	c = *p++, len = 1;
       /* Let a display table override all standard display methods.  */
@@ -3381,12 +3500,22 @@
 	    invis = 1;
 	  while (pos + 1 < ZV
 		 && selective > 0
-		 && indented_beyond_p (pos + 1, selective))
+		 && indented_beyond_p (pos + 1, pos_byte + 1, selective))
 	    {
+	      int opoint = PT, opoint_byte = PT_BYTE;
+
 	      invis = 1;
-	      pos = find_next_newline (pos + 1, 1);
-	      if (FETCH_BYTE (pos - 1) == '\n')
-		pos--;
+	      if (! NILP (current_buffer->enable_multibyte_characters))
+		INC_BOTH (pos, pos_byte);
+	      else
+		pos++, pos_byte++;
+	      scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
+	      if (FETCH_BYTE (pos_byte - 1) == '\n')
+		{
+		  pos--;
+		  pos_byte--;
+		}
+	      SET_PT_BOTH (opoint, opoint_byte);
 	    }
 	  if (invis && selective_rlen > 0 && p1 >= leftmargin)
 	    {
@@ -3459,9 +3588,13 @@
 	}
       else if (c == Ctl ('M') && selective == -1)
 	{
-	  pos = find_next_newline (pos, 1);
-	  if (FETCH_BYTE (pos - 1) == '\n')
-	    pos--;
+	  int opoint = PT, opoint_byte = PT_BYTE;
+	  scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
+	  pos = PT, pos_byte = PT_BYTE;
+	  SET_PT_BOTH (opoint, opoint_byte);
+
+	  if (FETCH_BYTE (pos_byte - 1) == '\n')
+	    pos--, pos_byte--;
 	  if (selective_rlen > 0)
 	    {
 	      p1 += selective_rlen;
@@ -3555,7 +3688,9 @@
 	}
 
       prevpos = pos;
-      pos += len;
+      prevpos_byte = pos_byte;
+      pos++;
+      pos_byte += len;
 
       /* Update charstarts for the character just output.  */
 
@@ -3587,6 +3722,7 @@
   val.vpos = 1;
 
   lastpos = pos;
+  lastpos_byte = pos_byte;
 
   /* Store 0 in this charstart line for the positions where
      there is no character.  But do leave what was recorded
@@ -3612,6 +3748,7 @@
              character code is C and the length of multi-byte form is
              LEN.  */
 	  pos = prevpos;
+	  pos_byte = prevpos_byte;
 
 	  if (len == 1)
 	    /* C is not a multi-byte character.  We can break it and
@@ -3636,6 +3773,7 @@
 	      }
 	      /* If POINT is at POS, cursor should not on this line.  */
 	      lastpos = pos;
+	      lastpos_byte = pos_byte;
 	      if (PT == pos)
 		cursor_vpos = -1;
 	    }
@@ -3652,33 +3790,45 @@
 
   if (pos < ZV)
     {
-      if (FETCH_BYTE (pos) == '\n')
+      if (FETCH_BYTE (pos_byte) == '\n')
 	{
+	  int opoint = PT, opoint_byte = PT_BYTE;
+
 	  /* If stopped due to a newline, start next line after it */
-	  pos++;
+	  SET_PT_BOTH (pos + 1, pos_byte + 1);
+
 	  val.tab_offset = 0;
 	  /* Check again for hidden lines, in case the newline occurred exactly
 	     at the right margin.  */
-	  while (pos < ZV && selective > 0
-		 && indented_beyond_p (pos, selective))
-	    pos = find_next_newline (pos, 1);
+	  while (PT < ZV && selective > 0
+		 && indented_beyond_p (PT, PT_BYTE, selective))
+	    scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
+
+	  pos = PT, pos_byte = PT_BYTE;
+	  SET_PT_BOTH (opoint, opoint_byte);
 	}
       else
 	/* Stopped due to right margin of window */
 	{
 	  if (truncate)
 	    {
+	      int opoint = PT, opoint_byte = PT_BYTE;
+
+	      SET_PT_BOTH (pos, pos_byte);
 	      *p1++ = fix_glyph (f, truncator, 0);
 	      /* Truncating => start next line after next newline,
 		 and point is on this line if it is before the newline,
 		 and skip none of first char of next line */
 	      do
-		pos = find_next_newline (pos, 1);
-	      while (pos < ZV && selective > 0
-		     && indented_beyond_p (pos, selective));
+		scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
+	      while (PT < ZV && selective > 0
+		     && indented_beyond_p (PT, PT_BYTE, selective));
+	      pos = PT, pos_byte = PT_BYTE;
 	      val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
-
-	      lastpos = pos - (FETCH_BYTE (pos - 1) == '\n');
+	      SET_PT_BOTH (opoint, opoint_byte);
+
+	      lastpos = pos - (FETCH_BYTE (pos_byte - 1) == '\n');
+	      lastpos_byte = CHAR_TO_BYTE (lastpos);
 	      val.tab_offset = 0;
 	    }
 	  else
@@ -3686,6 +3836,7 @@
 	      *p1++ = fix_glyph (f, continuer, 0);
 	      val.vpos = 0;
 	      lastpos--;
+	      DEC_POS (lastpos_byte);
 	      val.tab_offset = taboffset + width;
 	    }
 	}
@@ -3824,6 +3975,7 @@
     }
 
   val.bufpos = pos;
+  val.bytepos = pos_byte;
   val.ovstring_chars_done = ovstr_done;
   val_display_text_line = val;
   return &val_display_text_line;
@@ -4413,8 +4565,9 @@
 
     case 'l':
       {
-	int startpos = marker_position (w->start);
-	int line, linepos, topline;
+	int startpos = XMARKER (w->start)->charpos;
+	int startpos_byte = marker_byte_position (w->start);
+	int line, linepos, linepos_byte, topline;
 	int nlines, junk;
 	Lisp_Object tem;
 	int height = XFASTINT (w->height);
@@ -4437,19 +4590,23 @@
 
 	if (!NILP (w->base_line_number)
 	    && !NILP (w->base_line_pos)
-	    && XFASTINT (w->base_line_pos) <= marker_position (w->start))
+	    && XFASTINT (w->base_line_pos) <= startpos)
 	  {
 	    line = XFASTINT (w->base_line_number);
 	    linepos = XFASTINT (w->base_line_pos);
+	    linepos_byte = buf_charpos_to_bytepos (b, linepos);
 	  }
 	else
 	  {
 	    line = 1;
 	    linepos = BUF_BEGV (b);
+	    linepos_byte = BUF_BEGV_BYTE (b);
 	  }
 
 	/* Count lines from base line to window start position.  */
-	nlines = display_count_lines (linepos, startpos, startpos, &junk);
+	nlines = display_count_lines (linepos, linepos_byte,
+				      startpos_byte,
+				      startpos, &junk);
 
 	topline = nlines + line;
 
@@ -4466,19 +4623,24 @@
 		 || linepos == BUF_BEGV (b))
 	  {
 	    int limit = BUF_BEGV (b);
+	    int limit_byte = BUF_BEGV_BYTE (b);
 	    int position;
 	    int distance = (height * 2 + 30) * 200;
 
 	    if (startpos - distance > limit)
-	      limit = startpos - distance;
-
-	    nlines = display_count_lines (startpos, limit,
-					  -(height * 2 + 30),
+	      {
+		limit = startpos - distance;
+		limit_byte = CHAR_TO_BYTE (limit);
+	      }
+
+	    nlines = display_count_lines (startpos, startpos_byte,
+					  limit_byte,
+					  - (height * 2 + 30),
 					  &position);
 	    /* If we couldn't find the lines we wanted within 
 	       200 chars per line,
 	       give up on line numbers for this window.  */
-	    if (position == startpos - distance)
+	    if (position == limit_byte && limit == startpos - distance)
 	      {
 		w->base_line_pos = w->buffer;
 		w->base_line_number = Qnil;
@@ -4486,11 +4648,12 @@
 	      }
 
 	    XSETFASTINT (w->base_line_number, topline - nlines);
-	    XSETFASTINT (w->base_line_pos, position);
+	    XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
 	  }
 
 	/* Now count lines from the start pos to point.  */
-	nlines = display_count_lines (startpos, PT, PT, &junk);
+	nlines = display_count_lines (startpos, startpos_byte,
+				      PT_BYTE, PT, &junk);
 
 	/* Record that we did display the line number.  */
 	line_number_displayed = 1;
@@ -4638,137 +4801,109 @@
     return "";
 }
 
-/* Search for COUNT instances of a line boundary, which means either a
-   newline or (if selective display enabled) a carriage return.
-   Start at START.  If COUNT is negative, search backwards.
-
-   If we find COUNT instances, set *SHORTAGE to zero, and return the
-   position after the COUNTth match.  Note that for reverse motion
-   this is not the same as the usual convention for Emacs motion commands.
-
-   If we don't find COUNT instances before reaching the end of the
-   buffer (or the beginning, if scanning backwards), set *SHORTAGE to
-   the number of line boundaries left unfound, and return the end of the
-   buffer we bumped up against.  */
+/* Count up to COUNT lines starting from START / START_BYTE.
+   But don't go beyond LIMIT_BYTE.
+   Return the number of lines thus found (always nonnegative).
+
+   Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT.  */
 
 static int
-display_scan_buffer (start, count, shortage)
-     int *shortage, start;
-     register int count;
+display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
+     int start, start_byte, limit_byte, count;
+     int *byte_pos_ptr;
 {
-  int limit = ((count > 0) ? ZV - 1 : BEGV);
-  int direction = ((count > 0) ? 1 : -1);
-
   register unsigned char *cursor;
   unsigned char *base;
 
   register int ceiling;
   register unsigned char *ceiling_addr;
+  int orig_count = count;
 
   /* If we are not in selective display mode,
      check only for newlines.  */
-  if (! (!NILP (current_buffer->selective_display)
-	 && !INTEGERP (current_buffer->selective_display)))
-    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.  */
-
-  if (shortage != 0)
-    *shortage = 0;
+  int selective_display = (!NILP (current_buffer->selective_display)
+			   && !INTEGERP (current_buffer->selective_display));
 
   if (count > 0)
-    while (start != limit + 1)
-      {
-	ceiling =  BUFFER_CEILING_OF (start);
-	ceiling = min (limit, ceiling);
-	ceiling_addr = POS_ADDR (ceiling) + 1;
-	base = (cursor = POS_ADDR (start));
-	while (1)
-	  {
-	    while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
-	      ;
-	    if (cursor != ceiling_addr)
-	      {
-		if (--count == 0)
-		  {
-		    immediate_quit = 0;
-		    return (start + cursor - base + 1);
-		  }
-		else
-		  if (++cursor == ceiling_addr)
-		    break;
-	      }
-	    else
-	      break;
-	  }
-	start += cursor - base;
-      }
+    {
+      while (start_byte < limit_byte)
+	{
+	  ceiling =  BUFFER_CEILING_OF (start_byte);
+	  ceiling = min (limit_byte - 1, ceiling);
+	  ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
+	  base = (cursor = BYTE_POS_ADDR (start_byte));
+	  while (1)
+	    {
+	      if (selective_display)
+		while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
+		  ;
+	      else
+		while (*cursor != '\n' && ++cursor != ceiling_addr)
+		  ;
+
+	      if (cursor != ceiling_addr)
+		{
+		  if (--count == 0)
+		    {
+		      start_byte += cursor - base + 1;
+		      *byte_pos_ptr = start_byte;
+		      return orig_count;
+		    }
+		  else
+		    if (++cursor == ceiling_addr)
+		      break;
+		}
+	      else
+		break;
+	    }
+	  start_byte += cursor - base;
+	}
+    }
   else
     {
-      start--;			/* first character we scan */
-      while (start > limit - 1)
-	{			/* we WILL scan under start */
-	  ceiling =  BUFFER_FLOOR_OF (start);
-	  ceiling = max (limit, ceiling);
-	  ceiling_addr = POS_ADDR (ceiling) - 1;
-	  base = (cursor = POS_ADDR (start));
-	  cursor++;
+      while (start_byte > limit_byte)
+	{
+	  ceiling = BUFFER_FLOOR_OF (start_byte - 1);
+	  ceiling = max (limit_byte, ceiling);
+	  ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
+	  base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
 	  while (1)
 	    {
-	      while (--cursor != ceiling_addr
-		     && *cursor != '\n' && *cursor != 015)
-		;
+	      if (selective_display)
+		while (--cursor != ceiling_addr
+		       && *cursor != '\n' && *cursor != 015)
+		  ;
+	      else
+		while (--cursor != ceiling_addr && *cursor != '\n')
+		  ;
+
 	      if (cursor != ceiling_addr)
 		{
 		  if (++count == 0)
 		    {
-		      immediate_quit = 0;
-		      return (start + cursor - base + 1);
+		      start_byte += cursor - base + 1;
+		      *byte_pos_ptr = start_byte;
+		      /* When scanning backwards, we should
+			 not count the newline posterior to which we stop.  */
+		      return - orig_count - 1;
 		    }
 		}
 	      else
 		break;
 	    }
-	  start += cursor - base;
+	  /* Here we add 1 to compensate for the last decrement
+	     of CURSOR, which took it past the valid range.  */
+	  start_byte += cursor - base + 1;
 	}
     }
 
-  if (shortage != 0)
-    *shortage = count * direction;
-  return (start + ((direction == 1 ? 0 : 1)));
+  *byte_pos_ptr = limit_byte;
+
+  if (count < 0)
+    return - orig_count + count;
+  return orig_count - count;
+
 }
-
-/* Count up to N lines starting from FROM.
-   But don't go beyond LIMIT.
-   Return the number of lines thus found (always positive).
-   Store the position after what was found into *POS_PTR.  */
-
-static int
-display_count_lines (from, limit, n, pos_ptr)
-     int from, limit, n;
-     int *pos_ptr;
-{
-  int oldbegv = BEGV;
-  int oldzv = ZV;
-  int shortage = 0;
-  
-  if (limit < from)
-    BEGV = limit;
-  else
-    ZV = limit;
-
-  *pos_ptr = display_scan_buffer (from, n, &shortage);
-
-  ZV = oldzv;
-  BEGV = oldbegv;
-
-  if (n < 0)
-    /* When scanning backwards, scan_buffer stops *after* the last newline
-       it finds, but does count it.  Compensate for that.  */
-    return - n - shortage - (*pos_ptr != limit);
-  return n - shortage;
-}  
 
 /* Display STRING on one line of window W, starting at HPOS.
    Display at position VPOS.  Caller should have done get_display_line.