    Allow the replace_substring() macro built-in to take three parameters

    Avaliable as a patch:

    http://sourceforge.net/tracker/index.php?func=detail&aid=1494174&group_id=11005&atid=311005
	    [ 1494174 ] 3 argument version of replace_substring() macro built-in
	    ReplaceSubString.diff 2006-05-24 06:36

  This patch allows the macro programmer to drop the parameter providing the
  end position of the substring to replace. Normally replace_substring() is
  called as
	    result = replace_substring(string, start, end, replacement)

  This patch allows the call
	    result = replace_substring(string, start, replacement)
  to be the equivalent of
	    result = replace_substring(string, start, length(string), replacement)

  This patch also changes the behaviour of the function where negative values
  of start and end are provided, and where the start position is beyond the
  end position indicated. (These effects were never documented, so they can
  be assumed not to break well built macro programs.) The new handling matches
  that of changes made to the substring() built-in, checked in on 2005-02-11.

  Now, negative values of start and end are treated as relative to the end of
  the first string argument (before negative values were reset to zero). Also,
  if the indicated start position is greater than the end position, the end
  position used is set to the start position, and the zero-length substring at
  the start position is replaced with the replacement string; essentially an
  insertion. This has the nice effect of not requiring an insert position to
  be specified twice; just set end to zero; instead of
	    result = replace_substring(string, start, start, insert_piece)
  to insert a piece of string, use
	    result = replace_substring(string, start, 0, insert_piece)
  Previously, if the start position was greater than the end position, the two
  positions would be swapped.

  Finally, this patch corrects a small bug in the original code: if both string
  and replacement are provided to replace_substring() as integers, only the
  second would be used. For example, the call
	    result = replace_substring(12345, 2, 3, 9876)
  would give
	    result == "9898766"
  instead of
	    result == "12987645"
  which this patch produces.

diff -ur nedit_official nedit_mod
diff -ur nedit_official/doc/help.etx nedit_mod/doc/help.etx
--- nedit_official/doc/help.etx	2006-04-20 08:40:53.000000000 +0200
+++ nedit_mod/doc/help.etx	2006-05-24 11:26:13.843750000 +0200
@@ -2632,8 +2632,14 @@
 **replace_selection( string )**
   Replaces the primary-selection selected text in the current window.
 
-**replace_substring( string, start, end, replace_with )**
-  Replacing a substring between two positions in a string within another string.
+**replace_substring( string, start, [end,] replace_with )**
+  Replaces the substring of string between positions indicated by start and end
+  (or the end of string if no end argument is supplied) with the string
+  replace_with and returns the result.  Negative values of start and end are
+  converted to positions relative to the end of the string.  If the start
+  position is greater than the end position, the replace_with string will be
+  inserted at the start position in the returned result, replacing a
+  zero-length substring.
 
 **search( search_for, start [, search_type, wrap, direction] )**
   Searches silently in a window without dialogs, beeps, or changes to the
diff -ur nedit_official/source/macro.c nedit_mod/source/macro.c
--- nedit_official/source/macro.c	2006-04-20 08:40:47.000000000 +0200
+++ nedit_mod/source/macro.c	2006-05-24 11:24:07.359375000 +0200
@@ -2129,6 +2129,10 @@
 
 /*
 ** Built-in macro subroutine for replacing a substring within another string
+** Called as replace_substring(string, from, [to,] replacement)
+** If from or to are negative, they are treated as offsets from the end of the
+** string. If only three arguments are present, the last is replacement and to
+** is the length of the original string.
 */
 static int replaceSubstringMS(WindowInfo *window, DataValue *argList, int nArgs,
     	DataValue *result, char **errMsg)
@@ -2137,22 +2141,29 @@
     char stringStorage[2][TYPE_INT_STR_SIZE(int)], *string, *replStr;
     
     /* Validate arguments and convert to int */
-    if (nArgs != 4)
-    	return wrongNArgsErr(errMsg);
-    if (!readStringArg(argList[0], &string, stringStorage[1], errMsg))
-    	return False;
-    if (!readIntArg(argList[1], &from, errMsg))
-    	return False;
-    if (!readIntArg(argList[2], &to, errMsg))
-	return False;
-    if (!readStringArg(argList[3], &replStr, stringStorage[1], errMsg))
-    	return False;
+    if (nArgs != 3 && nArgs != 4)
+        return wrongNArgsErr(errMsg);
+    if (!readStringArg(*argList++, &string, stringStorage[0], errMsg))
+        return False;
+    if (!readIntArg(*argList++, &from, errMsg))
+        return False;
+    if (nArgs == 4) {
+        if (!readIntArg(*argList++, &to, errMsg))
+            return False;
+    }
+    if (!readStringArg(*argList++, &replStr, stringStorage[1], errMsg))
+        return False;
     length = strlen(string);
+    /* if to position not supplied, make it the end of the source string */
+    if (nArgs != 4)
+        to = length; /* no to position argument supplied */
+    if (from < 0) from += length;
     if (from < 0) from = 0;
     if (from > length) from = length;
+    if (to < 0) to += length;
     if (to < 0) to = 0;
     if (to > length) to = length;
-    if (from > to) {int temp = from; from = to; to = temp;}
+    if (from > to) to = from;
     
     /* Allocate a new string and do the replacement */
     replaceLen = strlen(replStr);
