]> code.delx.au - gnu-emacs/blobdiff - src/search.c
(looking_at_1): Use bytepos to call re_search_2.
[gnu-emacs] / src / search.c
index f96e9e53bd91906de322bf65e2a85635679b44ad..82a64e900a9df5268395b114f998518426b1b2f0 100644 (file)
@@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA.  */
 #include "region-cache.h"
 #include "commands.h"
 #include "blockinput.h"
+#include "intervals.h"
 
 #include <sys/types.h>
 #include "regex.h"
@@ -121,7 +122,7 @@ compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
      int posix;
      int multibyte;
 {
-  CONST char *val;
+  char *val;
   reg_syntax_t old;
 
   cp->regexp = Qnil;
@@ -131,8 +132,8 @@ compile_pattern_1 (cp, pattern, translate, regp, posix, multibyte)
   BLOCK_INPUT;
   old = re_set_syntax (RE_SYNTAX_EMACS
                       | (posix ? 0 : RE_NO_POSIX_BACKTRACKING));
-  val = (CONST char *) re_compile_pattern ((char *) XSTRING (pattern)->data,
-                                          XSTRING (pattern)->size, &cp->buf);
+  val = (char *) re_compile_pattern ((char *) XSTRING (pattern)->data,
+                                    XSTRING (pattern)->size, &cp->buf);
   re_set_syntax (old);
   UNBLOCK_INPUT;
   if (val)
@@ -225,7 +226,7 @@ looking_at_1 (string, posix)
   CHECK_STRING (string, 0);
   bufp = compile_pattern (string, &search_regs,
                          (!NILP (current_buffer->case_fold_search)
-                          ? DOWNCASE_TABLE : 0),
+                          ? XCHAR_TABLE (DOWNCASE_TABLE)->contents : 0),
                          posix);
 
   immediate_quit = 1;
@@ -235,34 +236,39 @@ looking_at_1 (string, posix)
      that make up the visible portion of the buffer. */
 
   p1 = BEGV_ADDR;
-  s1 = GPT - BEGV;
+  s1 = GPT_BYTE - BEGV_BYTE;
   p2 = GAP_END_ADDR;
-  s2 = ZV - GPT;
+  s2 = ZV_BYTE - GPT_BYTE;
   if (s1 < 0)
     {
       p2 = p1;
-      s2 = ZV - BEGV;
+      s2 = ZV_BYTE - BEGV_BYTE;
       s1 = 0;
     }
   if (s2 < 0)
     {
-      s1 = ZV - BEGV;
+      s1 = ZV_BYTE - BEGV_BYTE;
       s2 = 0;
     }
+
+  re_match_object = Qnil;
   
   i = re_match_2 (bufp, (char *) p1, s1, (char *) p2, s2,
-                 PT - BEGV, &search_regs,
-                 ZV - BEGV);
+                 PT_BYTE - BEGV_BYTE, &search_regs,
+                 ZV_BYTE - BEGV_BYTE);
   if (i == -2)
     matcher_overflow ();
 
   val = (0 <= i ? Qt : Qnil);
-  for (i = 0; i < search_regs.num_regs; i++)
-    if (search_regs.start[i] >= 0)
-      {
-       search_regs.start[i] += BEGV;
-       search_regs.end[i] += BEGV;
-      }
+  if (i >= 0)
+    for (i = 0; i < search_regs.num_regs; i++)
+      if (search_regs.start[i] >= 0)
+       {
+         search_regs.start[i]
+           = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
+         search_regs.end[i]
+           = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
+       }
   XSETBUFFER (last_thing_searched, current_buffer);
   immediate_quit = 0;
   return val;
@@ -322,9 +328,11 @@ string_match_1 (regexp, string, start, posix)
 
   bufp = compile_pattern (regexp, &search_regs,
                          (!NILP (current_buffer->case_fold_search)
-                          ? DOWNCASE_TABLE : 0),
+                          ? XCHAR_TABLE (DOWNCASE_TABLE)->contents : 0),
                          posix);
   immediate_quit = 1;
+  re_match_object = string;
+  
   val = re_search (bufp, (char *) XSTRING (string)->data,
                   XSTRING (string)->size, s, XSTRING (string)->size - s,
                   &search_regs);
@@ -374,6 +382,8 @@ fast_string_match (regexp, string)
 
   bufp = compile_pattern (regexp, 0, 0, 0);
   immediate_quit = 1;
+  re_match_object = string;
+  
   val = re_search (bufp, (char *) XSTRING (string)->data,
                   XSTRING (string)->size, 0, XSTRING (string)->size,
                   0);
@@ -388,7 +398,7 @@ fast_string_match (regexp, string)
 extern Lisp_Object Vascii_downcase_table;
 
 int
-fast_string_match_ignore_case (regexp, string)
+fast_c_string_match_ignore_case (regexp, string)
      Lisp_Object regexp;
      char *string;
 {
@@ -396,6 +406,7 @@ fast_string_match_ignore_case (regexp, string)
   struct re_pattern_buffer *bufp;
   int len = strlen (string);
 
+  re_match_object = Qt;
   bufp = compile_pattern (regexp, 0,
                          XCHAR_TABLE (Vascii_downcase_table)->contents, 0);
   immediate_quit = 1;
@@ -506,7 +517,8 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
            the position of the last character before the next such
            obstacle --- the last character the dumb search loop should
            examine.  */
-        register int ceiling = end - 1;
+       int ceiling_byte = CHAR_TO_BYTE (end) - 1;
+       int start_byte = CHAR_TO_BYTE (start);
 
         /* If we're looking for a newline, consult the newline cache
            to see where we can avoid some scanning.  */
@@ -515,29 +527,31 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
             int next_change;
             immediate_quit = 0;
             while (region_cache_forward
-                   (current_buffer, newline_cache, start, &next_change))
-              start = next_change;
+                   (current_buffer, newline_cache, start_byte, &next_change))
+              start_byte = next_change;
             immediate_quit = allow_quit;
 
-            /* start should never be after end.  */
-            if (start >= end)
-              start = end - 1;
+            /* START should never be after END.  */
+            if (start_byte > ceiling_byte)
+              start_byte = ceiling_byte;
 
             /* Now the text after start is an unknown region, and
                next_change is the position of the next known region. */
-            ceiling = min (next_change - 1, ceiling);
+            ceiling_byte = min (next_change - 1, ceiling_byte);
           }
 
         /* The dumb loop can only scan text stored in contiguous
            bytes. BUFFER_CEILING_OF returns the last character
            position that is contiguous, so the ceiling is the
            position after that.  */
-        ceiling = min (BUFFER_CEILING_OF (start), ceiling);
+        ceiling_byte = min (BUFFER_CEILING_OF (start_byte), ceiling_byte);
 
         {
           /* The termination address of the dumb loop.  */ 
-          register unsigned char *ceiling_addr = POS_ADDR (ceiling) + 1;
-          register unsigned char *cursor = POS_ADDR (start);
+          register unsigned char *ceiling_addr
+           = BYTE_POS_ADDR (ceiling_byte) + 1;
+          register unsigned char *cursor
+           = BYTE_POS_ADDR (start_byte);
           unsigned char *base = cursor;
 
           while (cursor < ceiling_addr)
@@ -552,8 +566,8 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
                  the region from start to cursor is free of them. */
               if (target == '\n' && newline_cache)
                 know_region_cache (current_buffer, newline_cache,
-                                   start + scan_start - base,
-                                   start + cursor - base);
+                                   start_byte + scan_start - base,
+                                   start_byte + cursor - base);
 
               /* Did we find the target character?  */
               if (cursor < ceiling_addr)
@@ -561,20 +575,21 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
                   if (--count == 0)
                     {
                       immediate_quit = 0;
-                      return (start + cursor - base + 1);
+                      return BYTE_TO_CHAR (start_byte + cursor - base + 1);
                     }
                   cursor++;
                 }
             }
 
-          start += cursor - base;
+          start = BYTE_TO_CHAR (start_byte + cursor - base);
         }
       }
   else
     while (start > end)
       {
         /* The last character to check before the next obstacle.  */
-        register int ceiling = end;
+       int ceiling_byte = CHAR_TO_BYTE (end);
+       int start_byte = CHAR_TO_BYTE (start);
 
         /* Consult the newline cache, if appropriate.  */
         if (target == '\n' && newline_cache)
@@ -582,26 +597,26 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
             int next_change;
             immediate_quit = 0;
             while (region_cache_backward
-                   (current_buffer, newline_cache, start, &next_change))
-              start = next_change;
+                   (current_buffer, newline_cache, start_byte, &next_change))
+              start_byte = next_change;
             immediate_quit = allow_quit;
 
             /* Start should never be at or before end.  */
-            if (start <= end)
-              start = end + 1;
+            if (start_byte <= ceiling_byte)
+              start_byte = ceiling_byte + 1;
 
             /* Now the text before start is an unknown region, and
                next_change is the position of the next known region. */
-            ceiling = max (next_change, ceiling);
+            ceiling_byte = max (next_change, ceiling_byte);
           }
 
         /* Stop scanning before the gap.  */
-        ceiling = max (BUFFER_FLOOR_OF (start - 1), ceiling);
+        ceiling_byte = max (BUFFER_FLOOR_OF (start_byte - 1), ceiling_byte);
 
         {
           /* The termination address of the dumb loop.  */
-          register unsigned char *ceiling_addr = POS_ADDR (ceiling);
-          register unsigned char *cursor = POS_ADDR (start - 1);
+          register unsigned char *ceiling_addr = BYTE_POS_ADDR (ceiling_byte);
+          register unsigned char *cursor = BYTE_POS_ADDR (start_byte - 1);
           unsigned char *base = cursor;
 
           while (cursor >= ceiling_addr)
@@ -615,8 +630,8 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
                  the region from after the cursor to start is free of them.  */
               if (target == '\n' && newline_cache)
                 know_region_cache (current_buffer, newline_cache,
-                                   start + cursor - base,
-                                   start + scan_start - base);
+                                   start_byte + cursor - base,
+                                   start_byte + scan_start - base);
 
               /* Did we find the target character?  */
               if (cursor >= ceiling_addr)
@@ -624,13 +639,13 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
                   if (++count >= 0)
                     {
                       immediate_quit = 0;
-                      return (start + cursor - base);
+                      return BYTE_TO_CHAR (start_byte + cursor - base);
                     }
                   cursor--;
                 }
             }
 
-          start += cursor - base;
+         start = BYTE_TO_CHAR (start_byte + cursor - base);
         }
       }
 
@@ -639,286 +654,146 @@ scan_buffer (target, start, end, count, shortage, allow_quit)
     *shortage = count * direction;
   return start;
 }
-
-int
-find_next_newline_no_quit (from, cnt)
-     register int from, cnt;
-{
-  return scan_buffer ('\n', from, 0, cnt, (int *) 0, 0);
-}
-
-int
-find_next_newline (from, cnt)
-     register int from, cnt;
-{
-  return scan_buffer ('\n', from, 0, cnt, (int *) 0, 1);
-}
-
-
-/* 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.  */
-int
-find_before_next_newline (from, to, cnt)
-     int from, to, cnt;
-{
-  int shortage;
-  int pos = scan_buffer ('\n', from, to, cnt, &shortage, 1);
-
-  if (shortage == 0)
-    pos--;
-  
-  return pos;
-}
 \f
-Lisp_Object skip_chars ();
-
-DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
-  "Move point forward, stopping before a char not in STRING, or at pos LIM.\n\
-STRING is like the inside of a `[...]' in a regular expression\n\
-except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
-Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
-With arg \"^a-zA-Z\", skips nonletters stopping before first letter.\n\
-Returns the distance traveled, either zero or positive.")
-  (string, lim)
-     Lisp_Object string, lim;
-{
-  return skip_chars (1, 0, string, lim);
-}
+/* 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.
 
-DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
-  "Move point backward, stopping after a char not in STRING, or at pos LIM.\n\
-See `skip-chars-forward' for details.\n\
-Returns the distance traveled, either zero or negative.")
-  (string, lim)
-     Lisp_Object string, lim;
-{
-  return skip_chars (0, 0, string, lim);
-}
+   We report the resulting position by calling TEMP_SET_PT_BOTH.
 
-DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
-  "Move point forward across chars in specified syntax classes.\n\
-SYNTAX is a string of syntax code characters.\n\
-Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\
-If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
-This function returns the distance traveled, either zero or positive.")
-  (syntax, lim)
-     Lisp_Object syntax, lim;
-{
-  return skip_chars (1, 1, syntax, lim);
-}
+   If we find COUNT instances. we position after (always after,
+   even if scanning backwards) the COUNTth match, and return 0.
 
-DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
-  "Move point backward across chars in specified syntax classes.\n\
-SYNTAX is a string of syntax code characters.\n\
-Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\
-If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
-This function returns the distance traveled, either zero or negative.")
-  (syntax, lim)
-     Lisp_Object syntax, lim;
-{
-  return skip_chars (0, 1, syntax, lim);
-}
+   If we don't find COUNT instances before reaching the end of the
+   buffer (or the beginning, if scanning backwards), we return
+   the number of line boundaries left unfound, and position at
+   the limit we bumped up against.
 
-Lisp_Object
-skip_chars (forwardp, syntaxp, string, lim)
-     int forwardp, syntaxp;
-     Lisp_Object string, lim;
+   If ALLOW_QUIT is non-zero, set immediate_quit.  That's good to do
+   except when inside redisplay.  */
+
+int
+scan_newline (start, start_byte, limit, limit_byte, count, allow_quit)
+     int start, start_byte;
+     int limit, limit_byte;
+     register int count;
+     int allow_quit;
 {
-  register unsigned char *p, *pend;
-  register unsigned char c;
-  register int ch;
-  unsigned char fastmap[0400];
-  /* If SYNTAXP is 0, STRING may contain multi-byte form of characters
-     of which codes don't fit in FASTMAP.  In that case, we set the
-     first byte of multibyte form (i.e. base leading-code) in FASTMAP
-     and set the actual ranges of characters in CHAR_RANGES.  In the
-     form "X-Y" of STRING, both X and Y must belong to the same
-     character set because a range striding across character sets is
-     meaningless.  */
-  int *char_ranges
-    = (int *) alloca (XSTRING (string)->size * (sizeof (int)) * 2);
-  int n_char_ranges = 0;
-  int negate = 0;
-  register int i;
+  int direction = ((count > 0) ? 1 : -1);
 
-  CHECK_STRING (string, 0);
+  register unsigned char *cursor;
+  unsigned char *base;
 
-  if (NILP (lim))
-    XSETINT (lim, forwardp ? ZV : BEGV);
-  else
-    CHECK_NUMBER_COERCE_MARKER (lim, 1);
+  register int ceiling;
+  register unsigned char *ceiling_addr;
 
-  /* In any case, don't allow scan outside bounds of buffer.  */
-  /* jla turned this off, for no known reason.
-     bfox turned the ZV part on, and rms turned the
-     BEGV part back on.  */
-  if (XINT (lim) > ZV)
-    XSETFASTINT (lim, ZV);
-  if (XINT (lim) < BEGV)
-    XSETFASTINT (lim, BEGV);
+  /* If we are not in selective display mode,
+     check only for newlines.  */
+  int selective_display = (!NILP (current_buffer->selective_display)
+                          && !INTEGERP (current_buffer->selective_display));
 
-  p = XSTRING (string)->data;
-  pend = p + XSTRING (string)->size;
-  bzero (fastmap, sizeof fastmap);
+  /* The code that follows is like scan_buffer
+     but checks for either newline or carriage return.  */
 
-  if (p != pend && *p == '^')
-    {
-      negate = 1; p++;
-    }
+  immediate_quit = allow_quit;
 
-  /* Find the characters specified and set their elements of fastmap.
-     If syntaxp, each character counts as itself.
-     Otherwise, handle backslashes and ranges specially.  */
+  start_byte = CHAR_TO_BYTE (start);
 
-  while (p != pend)
+  if (count > 0)
     {
-      c = *p;
-      ch = STRING_CHAR (p, pend - p);
-      p += BYTES_BY_CHAR_HEAD (*p);
-      if (syntaxp)
-       fastmap[syntax_spec_code[c]] = 1;
-      else
+      while (start_byte < limit_byte)
        {
-         if (c == '\\')
-           {
-             if (p == pend) break;
-             c = *p++;
-           }
-         if (p != pend && *p == '-')
+         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)
            {
-             unsigned int ch2;
+             while (*cursor != '\n' && ++cursor != ceiling_addr)
+               ;
 
-             p++;
-             if (p == pend) break;
-             if (SINGLE_BYTE_CHAR_P (ch))
-               while (c <= *p)
-                 {
-                   fastmap[c] = 1;
-                   c++;
-                 }
-             else
+             if (cursor != ceiling_addr)
                {
-                 fastmap[c] = 1; /* C is the base leading-code.  */
-                 ch2 = STRING_CHAR (p, pend - p);
-                 if (ch <= ch2)
-                   char_ranges[n_char_ranges++] = ch,
-                   char_ranges[n_char_ranges++] = ch2;
+                 if (--count == 0)
+                   {
+                     immediate_quit = 0;
+                     start_byte = start_byte + cursor - base + 1;
+                     start = BYTE_TO_CHAR (start_byte);
+                     TEMP_SET_PT_BOTH (start, start_byte);
+                     return 0;
+                   }
+                 else
+                   if (++cursor == ceiling_addr)
+                     break;
                }
-             p += BYTES_BY_CHAR_HEAD (*p);
+             else
+               break;
            }
-         else
+         start_byte += cursor - base;
+       }
+    }
+  else
+    {
+      int start_byte = CHAR_TO_BYTE (start);
+      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)
            {
-             fastmap[c] = 1;
-             if (!SINGLE_BYTE_CHAR_P (ch))
-               char_ranges[n_char_ranges++] = ch,
-               char_ranges[n_char_ranges++] = ch;
+             while (--cursor != ceiling_addr && *cursor != '\n')
+               ;
+
+             if (cursor != ceiling_addr)
+               {
+                 if (++count == 0)
+                   {
+                     immediate_quit = 0;
+                     /* Return the position AFTER the match we found.  */
+                     start_byte = start_byte + cursor - base + 1;
+                     start = BYTE_TO_CHAR (start_byte);
+                     TEMP_SET_PT_BOTH (start, start_byte);
+                     return 0;
+                   }
+               }
+             else
+               break;
            }
+         /* 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 ^ was the first character, complement the fastmap.  In
-     addition, as all multibyte characters have possibility of
-     matching, set all entries for base leading codes, which is
-     harmless even if SYNTAXP is 1.  */
+  TEMP_SET_PT_BOTH (limit, limit_byte);
 
-  if (negate)
-    for (i = 0; i < sizeof fastmap; i++)
-      {
-       if (!BASE_LEADING_CODE_P (i))
-         fastmap[i] ^= 1;
-       else
-         fastmap[i] = 1;
-      }
+  return count * direction;
+}
 
-  {
-    int start_point = PT;
-    int pos = PT;
+int
+find_next_newline_no_quit (from, cnt)
+     register int from, cnt;
+{
+  return scan_buffer ('\n', from, 0, cnt, (int *) 0, 0);
+}
 
-    immediate_quit = 1;
-    if (syntaxp)
-      {
-       if (forwardp)
-         {
-           while (pos < XINT (lim)
-                  && fastmap[(int) SYNTAX (FETCH_CHAR (pos))])
-             INC_POS (pos);
-         }
-       else
-         {
-           while (pos > XINT (lim))
-             {
-               DEC_POS (pos);
-               if (!fastmap[(int) SYNTAX (FETCH_CHAR (pos))])
-                 {
-                   INC_POS (pos);
-                   break;
-                 }
-             }
-         }
-      }
-    else
-      {
-       if (forwardp)
-         {
-           while (pos < XINT (lim) && fastmap[(c = FETCH_BYTE (pos))])
-             {
-               if (!BASE_LEADING_CODE_P (c))
-                 pos++;
-               else if (n_char_ranges)
-                 {
-                   /* We much check CHAR_RANGES for a multibyte
-                       character.  */
-                   ch = FETCH_MULTIBYTE_CHAR (pos);
-                   for (i = 0; i < n_char_ranges; i += 2)
-                     if ((ch >= char_ranges[i] && ch <= char_ranges[i + 1]))
-                       break;
-                   if (!(negate ^ (i < n_char_ranges)))
-                     break;
+/* 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.  */
 
-                   INC_POS (pos);
-                 }
-               else
-                 {
-                   if (!negate) break;
-                   INC_POS (pos);
-                 }
-             }
-         }
-       else
-         {
-           while (pos > XINT (lim))
-             {
-               DEC_POS (pos);
-               if (fastmap[(c = FETCH_BYTE (pos))])
-                 {
-                   if (!BASE_LEADING_CODE_P (c))
-                     ;
-                   else if (n_char_ranges)
-                     {
-                       /* We much check CHAR_RANGES for a multibyte
-                           character.  */
-                       ch = FETCH_MULTIBYTE_CHAR (pos);
-                       for (i = 0; i < n_char_ranges; i += 2)
-                         if (ch >= char_ranges[i] && ch <= char_ranges[i + 1])
-                           break;
-                       if (!(negate ^ (i < n_char_ranges)))
-                         break;
-                     }
-                   else
-                     if (!negate)
-                       break;
-                 }
-               else
-                 break;
-             }
-         }
-      }
-    SET_PT (pos);
-    immediate_quit = 0;
+int
+find_before_next_newline (from, to, cnt)
+     int from, to, cnt;
+{
+  int shortage;
+  int pos = scan_buffer ('\n', from, to, cnt, &shortage, 1);
 
-    return make_number (PT - start_point);
-  }
+  if (shortage == 0)
+    pos--;
+  
+  return pos;
 }
 \f
 /* Subroutines of Lisp buffer search functions. */
@@ -990,6 +865,8 @@ search_command (string, bound, noerror, count, direction, RE, posix)
   return make_number (np);
 }
 \f
+/* Return 1 if REGEXP it matches just one constant string.  */
+
 static int
 trivial_regexp_p (regexp)
      Lisp_Object regexp;
@@ -1088,20 +965,22 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
         that make up the visible portion of the buffer. */
 
       p1 = BEGV_ADDR;
-      s1 = GPT - BEGV;
+      s1 = GPT_BYTE - BEGV_BYTE;
       p2 = GAP_END_ADDR;
-      s2 = ZV - GPT;
+      s2 = ZV_BYTE - GPT_BYTE;
       if (s1 < 0)
        {
          p2 = p1;
-         s2 = ZV - BEGV;
+         s2 = ZV_BYTE - BEGV_BYTE;
          s1 = 0;
        }
       if (s2 < 0)
        {
-         s1 = ZV - BEGV;
+         s1 = ZV_BYTE - BEGV_BYTE;
          s2 = 0;
        }
+      re_match_object = Qnil;
+  
       while (n < 0)
        {
          int val;
@@ -1115,12 +994,13 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
            }
          if (val >= 0)
            {
-             j = BEGV;
              for (i = 0; i < search_regs.num_regs; i++)
                if (search_regs.start[i] >= 0)
                  {
-                   search_regs.start[i] += j;
-                   search_regs.end[i] += j;
+                   search_regs.start[i]
+                     = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
+                   search_regs.end[i]
+                     = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
                  }
              XSETBUFFER (last_thing_searched, current_buffer);
              /* Set pos to the new position. */
@@ -1145,12 +1025,13 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
            }
          if (val >= 0)
            {
-             j = BEGV;
              for (i = 0; i < search_regs.num_regs; i++)
                if (search_regs.start[i] >= 0)
                  {
-                   search_regs.start[i] += j;
-                   search_regs.end[i] += j;
+                   search_regs.start[i]
+                     = BYTE_TO_CHAR (search_regs.start[i] + BEGV_BYTE);
+                   search_regs.end[i]
+                     = BYTE_TO_CHAR (search_regs.end[i] + BEGV_BYTE);
                  }
              XSETBUFFER (last_thing_searched, current_buffer);
              pos = search_regs.end[0];
@@ -1167,6 +1048,8 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
     }
   else                         /* non-RE case */
     {
+      int pos_byte = CHAR_TO_BYTE (pos);
+      int lim_byte = CHAR_TO_BYTE (lim);
 #ifdef C_ALLOCA
       int BM_tab_space[0400];
       BM_tab = &BM_tab_space[0];
@@ -1186,7 +1069,7 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                len--;
                base_pat++;
              }
-           *pat++ = (trt ? trt[*base_pat++] : *base_pat++);
+           *pat++ = (trt ? XINT (trt[*base_pat++]) : *base_pat++);
          }
        len = pat - patbuf;
        pat = base_pat = patbuf;
@@ -1219,7 +1102,7 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
       /* it entirely if there is none. */  
 
       dirlen = len * direction;
-      infinity = dirlen - (lim + pos + len + len) * direction;
+      infinity = dirlen - (lim_byte + pos_byte + len + len) * direction;
       if (direction < 0)
        pat = (base_pat += len - 1);
       BM_tab_base = BM_tab;
@@ -1241,13 +1124,13 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
          if (i == dirlen) i = infinity;
          if (trt != 0)
            {
-             k = (j = trt[j]);
+             k = (j = XINT (trt[j]));
              if (i == infinity)
                stride_for_teases = BM_tab[j];
              BM_tab[j] = dirlen - i;
              /* A translation table is accompanied by its inverse -- see */
              /* comment following downcase_table for details */ 
-             while ((j = (unsigned char) inverse_trt[j]) != k)
+             while ((j = (unsigned char) XINT (inverse_trt[j])) != k)
                BM_tab[j] = dirlen - i;
            }
          else
@@ -1263,32 +1146,33 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
          /* different. */
        }
       infinity = dirlen - infinity;
-      pos += dirlen - ((direction > 0) ? direction : 0);
-      /* loop invariant - pos points at where last char (first char if reverse)
-        of pattern would align in a possible match.  */
+      pos_byte += dirlen - ((direction > 0) ? direction : 0);
+      /* loop invariant - POS_BYTE points at where last char (first
+        char if reverse) of pattern would align in a possible match.  */
       while (n != 0)
        {
          /* It's been reported that some (broken) compiler thinks that
             Boolean expressions in an arithmetic context are unsigned.
             Using an explicit ?1:0 prevents this.  */
-         if ((lim - pos - ((direction > 0) ? 1 : 0)) * direction < 0)
+         if ((lim_byte - pos_byte - ((direction > 0) ? 1 : 0)) * direction
+             < 0)
            return (n * (0 - direction));
          /* First we do the part we can by pointers (maybe nothing) */
          QUIT;
          pat = base_pat;
-         limit = pos - dirlen + direction;
+         limit = pos_byte - dirlen + direction;
          limit = ((direction > 0)
                   ? BUFFER_CEILING_OF (limit)
                   : BUFFER_FLOOR_OF (limit));
-         /* LIMIT is now the last (not beyond-last!) value
-            POS can take on without hitting edge of buffer or the gap.  */
+         /* LIMIT is now the last (not beyond-last!) value POS_BYTE
+            can take on without hitting edge of buffer or the gap.  */
          limit = ((direction > 0)
-                  ? min (lim - 1, min (limit, pos + 20000))
-                  : max (lim, max (limit, pos - 20000)));
-         if ((limit - pos) * direction > 20)
+                  ? min (lim_byte - 1, min (limit, pos_byte + 20000))
+                  : max (lim_byte, max (limit, pos_byte - 20000)));
+         if ((limit - pos_byte) * direction > 20)
            {
-             p_limit = POS_ADDR (limit);
-             p2 = (cursor = POS_ADDR (pos));
+             p_limit = BYTE_POS_ADDR (limit);
+             p2 = (cursor = BYTE_POS_ADDR (pos_byte));
              /* In this loop, pos + cursor - p2 is the surrogate for pos */
              while (1)         /* use one cursor setting as long as i can */
                {
@@ -1330,7 +1214,7 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                  if (trt != 0)
                    {
                      while ((i -= direction) + direction != 0)
-                       if (pat[i] != trt[*(cursor -= direction)])
+                       if (pat[i] != XINT (trt[*(cursor -= direction)]))
                          break;
                    }
                  else
@@ -1344,7 +1228,7 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                    {
                      cursor -= direction;
 
-                     set_search_regs (pos + cursor - p2 + ((direction > 0)
+                     set_search_regs (pos_byte + cursor - p2 + ((direction > 0)
                                                            ? 1 - len : 0),
                                       len);
 
@@ -1357,19 +1241,19 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                  else
                    cursor += stride_for_teases; /* <sigh> we lose -  */
                }
-             pos += cursor - p2;
+             pos_byte += cursor - p2;
            }
          else
            /* Now we'll pick up a clump that has to be done the hard */
            /* way because it covers a discontinuity */
            {
              limit = ((direction > 0)
-                      ? BUFFER_CEILING_OF (pos - dirlen + 1)
-                      : BUFFER_FLOOR_OF (pos - dirlen - 1));
+                      ? BUFFER_CEILING_OF (pos_byte - dirlen + 1)
+                      : BUFFER_FLOOR_OF (pos_byte - dirlen - 1));
              limit = ((direction > 0)
-                      ? min (limit + len, lim - 1)
-                      : max (limit - len, lim));
-             /* LIMIT is now the last value POS can have
+                      ? min (limit + len, lim_byte - 1)
+                      : max (limit - len, lim_byte));
+             /* LIMIT is now the last value POS_BYTE can have
                 and still be valid for a possible match.  */
              while (1)
                {
@@ -1377,59 +1261,59 @@ search_buffer (string, pos, lim, n, RE, trt, inverse_trt, posix)
                  /* speed because it will usually run only once. */
                  /* (the reach is at most len + 21, and typically */
                  /* does not exceed len) */    
-                 while ((limit - pos) * direction >= 0)
-                   pos += BM_tab[FETCH_BYTE (pos)];
+                 while ((limit - pos_byte) * direction >= 0)
+                   pos_byte += BM_tab[FETCH_BYTE (pos_byte)];
                  /* now run the same tests to distinguish going off the */
                  /* end, a match or a phony match. */
-                 if ((pos - limit) * direction <= len)
+                 if ((pos_byte - limit) * direction <= len)
                    break;      /* ran off the end */
                  /* Found what might be a match.
-                    Set POS back to last (first if reverse) char pos.  */
-                 pos -= infinity;
+                    Set POS_BYTE back to last (first if reverse) pos.  */
+                 pos_byte -= infinity;
                  i = dirlen - direction;
                  while ((i -= direction) + direction != 0)
                    {
-                     pos -= direction;
+                     pos_byte -= direction;
                      if (pat[i] != (trt != 0
-                                    ? trt[FETCH_BYTE (pos)]
-                                    : FETCH_BYTE (pos)))
+                                    ? XINT (trt[FETCH_BYTE (pos_byte)])
+                                    : FETCH_BYTE (pos_byte)))
                        break;
                    }
-                 /* Above loop has moved POS part or all the way
-                    back to the first char pos (last char pos if reverse).
+                 /* Above loop has moved POS_BYTE part or all the way
+                    back to the first pos (last pos if reverse).
                     Set it once again at the last (first if reverse) char.  */
-                 pos += dirlen - i- direction;
+                 pos_byte += dirlen - i- direction;
                  if (i + direction == 0)
                    {
-                     pos -= direction;
+                     pos_byte -= direction;
 
-                     set_search_regs (pos + ((direction > 0) ? 1 - len : 0),
+                     set_search_regs (pos_byte + ((direction > 0) ? 1 - len : 0),
                                       len);
 
                      if ((n -= direction) != 0)
-                       pos += dirlen; /* to resume search */
+                       pos_byte += dirlen; /* to resume search */
                      else
                        return ((direction > 0)
                                ? search_regs.end[0] : search_regs.start[0]);
                    }
                  else
-                   pos += stride_for_teases;
+                   pos_byte += stride_for_teases;
                }
              }
          /* We have done one clump.  Can we continue? */
-         if ((lim - pos) * direction < 0)
+         if ((lim_byte - pos_byte) * direction < 0)
            return ((0 - n) * direction);
        }
-      return pos;
+      return BYTE_TO_CHAR (pos_byte);
     }
 }
 
-/* Record beginning BEG and end BEG + LEN
+/* Record beginning BEG_BYTE and end BEG_BYTE + NBYTES
    for a match just found in the current buffer.  */
 
 static void
-set_search_regs (beg, len)
-     int beg, len;
+set_search_regs (beg_byte, nbytes)
+     int beg_byte, nbytes;
 {
   /* Make sure we have registers in which to store
      the match position.  */
@@ -1440,8 +1324,8 @@ set_search_regs (beg, len)
       search_regs.num_regs = 2;
     }
 
-  search_regs.start[0] = beg;
-  search_regs.end[0] = beg + len;
+  search_regs.start[0] = BYTE_TO_CHAR (beg_byte);
+  search_regs.end[0] = BYTE_TO_CHAR (beg_byte + nbytes);
   XSETBUFFER (last_thing_searched, current_buffer);
 }
 \f
@@ -1495,7 +1379,7 @@ wordify (string)
 }
 \f
 DEFUN ("search-backward", Fsearch_backward, Ssearch_backward, 1, 4,
-  "sSearch backward: ",
+  "MSearch backward: ",
   "Search backward from point for STRING.\n\
 Set point to the beginning of the occurrence found, and return point.\n\
 An optional second argument bounds the search; it is a buffer position.\n\
@@ -1510,7 +1394,7 @@ See also the functions `match-beginning', `match-end' and `replace-match'.")
   return search_command (string, bound, noerror, count, -1, 0, 0);
 }
 
-DEFUN ("search-forward", Fsearch_forward, Ssearch_forward, 1, 4, "sSearch: ",
+DEFUN ("search-forward", Fsearch_forward, Ssearch_forward, 1, 4, "MSearch: ",
   "Search forward from point for STRING.\n\
 Set point to the end of the occurrence found, and return point.\n\
 An optional second argument bounds the search; it is a buffer position.\n\
@@ -1664,6 +1548,7 @@ since only regular expressions have distinguished subexpressions.")
   register int c, prevc;
   int inslen;
   int sub;
+  int opoint, newpoint;
 
   CHECK_STRING (newtext, 0);
 
@@ -1705,9 +1590,19 @@ since only regular expressions have distinguished subexpressions.")
 
   if (NILP (fixedcase))
     {
+      int beg;
       /* Decide how to casify by examining the matched text. */
 
-      last = search_regs.end[sub];
+      if (NILP (string))
+       last = CHAR_TO_BYTE (search_regs.end[sub]);
+      else
+       last = search_regs.end[sub];
+
+      if (NILP (string))
+       beg = CHAR_TO_BYTE (search_regs.start[sub]);
+      else
+       beg = search_regs.start[sub];
+
       prevc = '\n';
       case_action = all_caps;
 
@@ -1718,7 +1613,7 @@ since only regular expressions have distinguished subexpressions.")
       some_nonuppercase_initial = 0;
       some_uppercase = 0;
 
-      for (pos = search_regs.start[sub]; pos < last; pos++)
+      for (pos = beg; pos < last; pos++)
        {
          if (NILP (string))
            c = FETCH_BYTE (pos);
@@ -1778,7 +1673,8 @@ since only regular expressions have distinguished subexpressions.")
                           make_number (search_regs.start[sub]));
       after = Fsubstring (string, make_number (search_regs.end[sub]), Qnil);
 
-      /* Do case substitution into NEWTEXT if desired.  */
+      /* Substitute parts of the match into NEWTEXT
+        if desired.  */
       if (NILP (literal))
        {
          int lastpos = -1;
@@ -1813,6 +1709,8 @@ since only regular expressions have distinguished subexpressions.")
                    }
                  else if (c == '\\')
                    delbackslash = 1;
+                 else
+                   error ("Invalid use of `\\' in replacement text");
                }
              if (substart >= 0)
                {
@@ -1845,6 +1743,7 @@ since only regular expressions have distinguished subexpressions.")
          newtext = concat2 (accum, middle);
        }
 
+      /* Do case substitution in NEWTEXT if desired.  */
       if (case_action == all_caps)
        newtext = Fupcase (newtext);
       else if (case_action == cap_initial)
@@ -1853,11 +1752,18 @@ since only regular expressions have distinguished subexpressions.")
       return concat3 (before, newtext, after);
     }
 
+  /* Record point, the move (quietly) to the start of the match.  */
+  if (PT > search_regs.start[sub])
+    opoint = PT - ZV;
+  else
+    opoint = PT;
+
+  TEMP_SET_PT (search_regs.start[sub]);
+
   /* We insert the replacement text before the old text, and then
      delete the original text.  This means that markers at the
      beginning or end of the original will float to the corresponding
      position in the replacement.  */
-  SET_PT (search_regs.start[sub]);
   if (!NILP (literal))
     Finsert_and_inherit (1, &newtext);
   else
@@ -1886,8 +1792,10 @@ since only regular expressions have distinguished subexpressions.")
                       make_number (search_regs.start[c - '0'] + offset),
                       make_number (search_regs.end[c - '0'] + offset));
                }
-             else
+             else if (c == '\\')
                insert_char (c);
+             else
+               error ("Invalid use of `\\' in replacement text");
            }
          else
            insert_char (c);
@@ -1902,6 +1810,18 @@ since only regular expressions have distinguished subexpressions.")
     Fupcase_region (make_number (PT - inslen), make_number (PT));
   else if (case_action == cap_initial)
     Fupcase_initials_region (make_number (PT - inslen), make_number (PT));
+
+  newpoint = PT;
+
+  /* Put point back where it was in the text.  */
+  if (opoint <= 0)
+    TEMP_SET_PT (opoint + ZV);
+  else
+    TEMP_SET_PT (opoint);
+
+  /* Now move point "officially" to the start of the inserted replacement.  */
+  move_if_not_intangible (newpoint);
+  
   return Qnil;
 }
 \f
@@ -2224,10 +2144,6 @@ syms_of_search ()
   defsubr (&Sposix_looking_at);
   defsubr (&Sstring_match);
   defsubr (&Sposix_string_match);
-  defsubr (&Sskip_chars_forward);
-  defsubr (&Sskip_chars_backward);
-  defsubr (&Sskip_syntax_forward);
-  defsubr (&Sskip_syntax_backward);
   defsubr (&Ssearch_forward);
   defsubr (&Ssearch_backward);
   defsubr (&Sword_search_forward);