diff src/search.c @ 9029:f0d89b62dd27

(Freplace_match): New 4th arg OBJECT can specify string to replace in.
author Richard M. Stallman <rms@gnu.org>
date Fri, 23 Sep 1994 22:18:59 +0000
parents 68ad2f08d735
children 766b6288e0f2
line wrap: on
line diff
--- a/src/search.c	Fri Sep 23 22:14:46 1994 +0000
+++ b/src/search.c	Fri Sep 23 22:18:59 1994 +0000
@@ -1186,7 +1186,7 @@
   return search_command (regexp, bound, noerror, count, 1, 1);
 }
 
-DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 3, 0,
+DEFUN ("replace-match", Freplace_match, Sreplace_match, 1, 4, 0,
   "Replace text matched by last search with NEWTEXT.\n\
 If second arg FIXEDCASE is non-nil, do not alter case of replacement text.\n\
 Otherwise maybe capitalize the whole text, or maybe just word initials,\n\
@@ -1202,9 +1202,13 @@
        If Nth parens didn't match, substitute nothing.\n\
   `\\\\' means insert one `\\'.\n\
 FIXEDCASE and LITERAL are optional arguments.\n\
-Leaves point at end of replacement text.")
-  (newtext, fixedcase, literal)
-     Lisp_Object newtext, fixedcase, literal;
+Leaves point at end of replacement text.\n\
+\n\
+The optional fourth argument STRING can be a string to modify.\n\
+In that case, this function creates and returns a new string\n\
+which is made by replacing the part of STRING that was matched.")
+  (newtext, fixedcase, literal, string)
+     Lisp_Object newtext, fixedcase, literal, string;
 {
   enum { nochange, all_caps, cap_initial } case_action;
   register int pos, last;
@@ -1217,17 +1221,31 @@
 
   CHECK_STRING (newtext, 0);
 
+  if (! NILP (string))
+    CHECK_STRING (string, 4);
+
   case_action = nochange;	/* We tried an initialization */
 				/* but some C compilers blew it */
 
   if (search_regs.num_regs <= 0)
     error ("replace-match called before any match found");
 
-  if (search_regs.start[0] < BEGV
-      || search_regs.start[0] > search_regs.end[0]
-      || search_regs.end[0] > ZV)
-    args_out_of_range (make_number (search_regs.start[0]),
-		       make_number (search_regs.end[0]));
+  if (NILP (string))
+    {
+      if (search_regs.start[0] < BEGV
+	  || search_regs.start[0] > search_regs.end[0]
+	  || search_regs.end[0] > ZV)
+	args_out_of_range (make_number (search_regs.start[0]),
+			   make_number (search_regs.end[0]));
+    }
+  else
+    {
+      if (search_regs.start[0] < 0
+	  || search_regs.start[0] > search_regs.end[0]
+	  || search_regs.end[0] > XSTRING (string)->size)
+	args_out_of_range (make_number (search_regs.start[0]),
+			   make_number (search_regs.end[0]));
+    }
 
   if (NILP (fixedcase))
     {
@@ -1246,7 +1264,11 @@
 
       for (pos = search_regs.start[0]; pos < last; pos++)
 	{
-	  c = FETCH_CHAR (pos);
+	  if (NILP (string))
+	    c = FETCH_CHAR (pos);
+	  else
+	    c = XSTRING (string)->data[pos];
+
 	  if (LOWERCASEP (c))
 	    {
 	      /* Cannot be all caps if any original char is lower case */
@@ -1291,6 +1313,77 @@
 	case_action = nochange;
     }
 
+  /* Do replacement in a string.  */
+  if (!NILP (string))
+    {
+      Lisp_Object before, after;
+
+      before = Fsubstring (string, make_number (0),
+			   make_number (search_regs.start[0]));
+      after = Fsubstring (string, make_number (search_regs.end[0]), Qnil);
+
+      /* Do case substitution into NEWTEXT if desired.  */
+      if (NILP (literal))
+	{
+	  int lastpos = -1;
+	  /* We build up the substituted string in ACCUM.  */
+	  Lisp_Object accum;
+	  Lisp_Object middle;
+
+	  accum = Qnil;
+
+	  for (pos = 0; pos < XSTRING (newtext)->size; pos++)
+	    {
+	      int substart = -1;
+	      int subend;
+
+	      c = XSTRING (newtext)->data[pos];
+	      if (c == '\\')
+		{
+		  c = XSTRING (newtext)->data[++pos];
+		  if (c == '&')
+		    {
+		      substart = search_regs.start[0];
+		      subend = search_regs.end[0];
+		    }
+		  else if (c >= '1' && c <= '9' && c <= search_regs.num_regs + '0')
+		    {
+		      if (search_regs.start[c - '0'] >= 1)
+			{
+			  substart = search_regs.start[c - '0'];
+			  subend = search_regs.end[c - '0'];
+			}
+		    }
+		}
+	      if (substart >= 0)
+		{
+		  if (pos - 1 != lastpos + 1)
+		    middle = Fsubstring (newtext, lastpos + 1, pos - 1);
+		  else
+		    middle = Qnil;
+		  accum = concat3 (accum, middle,
+				   Fsubstring (string, make_number (substart),
+					       make_number (subend)));
+		  lastpos = pos;
+		}
+	    }
+
+	  if (pos != lastpos + 1)
+	    middle = Fsubstring (newtext, lastpos + 1, pos);
+	  else
+	    middle = Qnil;
+
+	  newtext = concat2 (accum, middle);
+	}
+
+      if (case_action == all_caps)
+	newtext = Fupcase (newtext);
+      else if (case_action == cap_initial)
+	newtext = upcase_initials (newtext);
+
+      return concat3 (before, newtext, after);
+    }
+
   /* 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