-        // copy non-matching bits:
-        newstring << pattern->Mid(lastpos, m_Matches[idx].rm_so - lastpos);
-        // copy replacement:
-        newstring << replacement;
-        // remember how far we got:
-        lastpos = m_Matches[idx].rm_eo;
-        replaced ++;
+        // 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(textstr + matchStart + start,
+                                            *wxConvCurrent, 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 wxNOT_FOUND;
+        }
+
+        // an insurance against implementations that don't grow exponentially
+        // to ensure building the result takes linear time
+        if (result.capacity() < result.length() + start + textNew.length())
+            result.reserve(2 * result.length());
+
+#ifndef WXREGEX_CONVERT_TO_MB
+        result.append(*text, matchStart, start);
+#else
+        result.append(wxString(textstr + matchStart, *wxConvCurrent, start));
+#endif
+        matchStart += start;
+        result.append(textNew);
+
+        countRepl++;
+
+        matchStart += len;