* search.c (find_newline): Accept start and end byte positions
[bpt/emacs.git] / src / search.c
index d450800..8bcf556 100644 (file)
@@ -621,7 +621,7 @@ newline_cache_on_off (struct buffer *buf)
 }
 
 \f
-/* Search for COUNT newlines between START and END.
+/* Search for COUNT newlines between START/START_BYTE and END/END_BYTE.
 
    If COUNT is positive, search forwards; END must be >= START.
    If COUNT is negative, search backwards for the -COUNTth instance;
@@ -638,15 +638,18 @@ newline_cache_on_off (struct buffer *buf)
    If we don't find COUNT instances before reaching END, set *SHORTAGE
    to the number of newlines left unfound, and return END.
 
+   If BYTEPOS is not NULL, set *BYTEPOS to the byte position corresponding
+   to the returned character position.
+
    If ALLOW_QUIT, set immediate_quit.  That's good to do
    except when inside redisplay.  */
 
 ptrdiff_t
-find_newline (ptrdiff_t start, ptrdiff_t end,
-             ptrdiff_t count, ptrdiff_t *shortage, bool allow_quit)
+find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
+             ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *shortage,
+             ptrdiff_t *bytepos, bool allow_quit)
 {
   struct region_cache *newline_cache;
-  ptrdiff_t end_byte = -1;
   int direction;
 
   if (count > 0)
@@ -680,9 +683,7 @@ find_newline (ptrdiff_t start, ptrdiff_t end,
            the position of the last character before the next such
            obstacle --- the last character the dumb search loop should
            examine.  */
-       ptrdiff_t ceiling_byte = end_byte - 1;
-       ptrdiff_t start_byte;
-       ptrdiff_t tem;
+       ptrdiff_t tem, ceiling_byte = end_byte - 1;
 
         /* If we're looking for a newline, consult the newline cache
            to see where we can avoid some scanning.  */
@@ -705,7 +706,7 @@ find_newline (ptrdiff_t start, ptrdiff_t end,
                next_change is the position of the next known region. */
             ceiling_byte = min (CHAR_TO_BYTE (next_change) - 1, ceiling_byte);
           }
-       else
+       else if (start_byte == -1)
          start_byte = CHAR_TO_BYTE (start);
 
         /* The dumb loop can only scan text stored in contiguous
@@ -745,21 +746,22 @@ find_newline (ptrdiff_t start, ptrdiff_t end,
              if (--count == 0)
                {
                  immediate_quit = 0;
+                 if (bytepos)
+                   *bytepos = nl + 1 - base + start_byte;
                  return BYTE_TO_CHAR (nl + 1 - base + start_byte);
                }
              cursor = nl + 1;
             }
 
-          start = BYTE_TO_CHAR (ceiling_addr - base + start_byte);
+         start_byte += ceiling_addr - base;
+         start = BYTE_TO_CHAR (start_byte);
         }
       }
   else
     while (start > end)
       {
         /* The last character to check before the next obstacle.  */
-       ptrdiff_t ceiling_byte = end_byte;
-       ptrdiff_t start_byte;
-       ptrdiff_t tem;
+       ptrdiff_t tem, ceiling_byte = end_byte;
 
         /* Consult the newline cache, if appropriate.  */
         if (newline_cache)
@@ -781,7 +783,7 @@ find_newline (ptrdiff_t start, ptrdiff_t end,
                next_change is the position of the next known region. */
             ceiling_byte = max (CHAR_TO_BYTE (next_change), ceiling_byte);
           }
-       else
+       else if (start_byte == -1)
          start_byte = CHAR_TO_BYTE (start);
 
         /* Stop scanning before the gap.  */
@@ -816,18 +818,26 @@ find_newline (ptrdiff_t start, ptrdiff_t end,
              if (++count >= 0)
                {
                  immediate_quit = 0;
+                 if (bytepos)
+                   *bytepos = nl - base + start_byte;
                  return BYTE_TO_CHAR (nl - base + start_byte);
                }
              cursor = nl - 1;
             }
 
-         start = BYTE_TO_CHAR (ceiling_addr - 1 - base + start_byte);
+         start_byte += ceiling_addr - 1 - base;
+         start = BYTE_TO_CHAR (start_byte);
         }
       }
 
   immediate_quit = 0;
-  if (shortage != 0)
+  if (shortage)
     *shortage = count * direction;
+  if (bytepos)
+    {
+      *bytepos = start_byte == -1 ? CHAR_TO_BYTE (start) : start_byte;
+      eassert (*bytepos == CHAR_TO_BYTE (start));
+    }
   return start;
 }
 \f
@@ -931,25 +941,33 @@ scan_newline (ptrdiff_t start, ptrdiff_t start_byte,
   return count * direction;
 }
 
+/* Like find_newline, but doesn't allow QUITting and doesn't return
+   SHORTAGE.  */
 ptrdiff_t
-find_next_newline_no_quit (ptrdiff_t from, ptrdiff_t cnt)
+find_newline_no_quit (ptrdiff_t from, ptrdiff_t frombyte,
+                     ptrdiff_t cnt, ptrdiff_t *bytepos)
 {
-  return find_newline (from, 0, cnt, (ptrdiff_t *) 0, 0);
+  return find_newline (from, frombyte, 0, -1, cnt, NULL, bytepos, 0);
 }
 
-/* Like find_next_newline, but returns position before the newline,
-   not after, and only search up to TO.  This isn't just
-   find_next_newline (...)-1, because you might hit TO.  */
+/* Like find_newline, but returns position before the newline, not
+   after, and only search up to TO.
+   This isn't just find_newline_no_quit (...)-1, because you might hit TO.  */
 
 ptrdiff_t
-find_before_next_newline (ptrdiff_t from, ptrdiff_t to, ptrdiff_t cnt)
+find_before_next_newline (ptrdiff_t from, ptrdiff_t to,
+                         ptrdiff_t cnt, ptrdiff_t *bytepos)
 {
   ptrdiff_t shortage;
-  ptrdiff_t pos = find_newline (from, to, cnt, &shortage, 1);
+  ptrdiff_t pos = find_newline (from, -1, to, -1, cnt, &shortage, bytepos, 1);
 
   if (shortage == 0)
-    pos--;
-
+    {
+      if (bytepos)
+       DEC_BOTH (pos, *bytepos);
+      else
+       pos--;
+    }
   return pos;
 }
 \f