+
+    // the position where we start looking for the match
+    //
+    // NB: initial version had a nasty bug because it used a wxChar* instead of
+    //     an index but the problem is that replace() in the loop invalidates
+    //     all pointers into the string so we have to use indices instead
+    size_t matchStart = 0;
+
+    // number of replacement made: we won't make more than maxMatches of them
+    // (unless maxMatches is 0 which doesn't limit the number of replacements)
+    size_t countRepl = 0;
+
+    // note that "^" shouldn't match after the first call to Matches() so we
+    // use wxRE_NOTBOL to prevent it from happening
+    while ( (!maxMatches || countRepl < maxMatches) &&
+            Matches(text->c_str() + matchStart, countRepl ? wxRE_NOTBOL : 0) )
+    {
+        // the string possibly contains back references: we need to calculate
+        // the replacement text anew after each match
+        if ( mayHaveBackrefs )
+        {
+            mayHaveBackrefs = FALSE;
+            textNew.clear();
+            textNew.reserve(replacement.length());
+
+            for ( const wxChar *p = replacement.c_str(); *p; p++ )
+            {
+                size_t index = (size_t)-1;
+
+                if ( *p == _T('\\') )
+                {
+                    if ( wxIsdigit(*++p) )
+                    {
+                        // back reference
+                        wxChar *end;
+                        index = (size_t)wxStrtoul(p, &end, 10);
+                        p = end - 1; // -1 to compensate for p++ in the loop
+                    }
+                    //else: backslash used as escape character
+                }
+                else if ( *p == _T('&') )
+                {
+                    // treat this as "\0" for compatbility with ed and such
+                    index = 0;
+                }
+
+                // do we have a back reference?
+                if ( index != (size_t)-1 )
+                {
+                    // yes, get its text
+                    size_t start, len;
+                    if ( !GetMatch(&start, &len, index) )
+                    {
+                        wxFAIL_MSG( _T("invalid back reference") );
+
+                        // just eat it...
+                    }
+                    else
+                    {
+                        textNew += wxString(text->c_str() + matchStart + start,
+                                            len);
+
+                        mayHaveBackrefs = TRUE;
+                    }
+                }
+                else // ordinary character
+                {
+                    textNew += *p;
+                }
+            }
+        }
+
+        size_t start, len;
+        if ( !GetMatch(&start, &len) )
+        {
+            // we did have match as Matches() returned true above!
+            wxFAIL_MSG( _T("internal logic error in wxRegEx::Replace") );
+
+            return -1;
+        }
+
+        matchStart += start;
+        text->replace(matchStart, len, textNew);
+
+        countRepl++;
+
+        matchStart += textNew.length();
+    }
+
+    return countRepl;