Here is a candidate patch.
Index: src/plugins/contrib/SmartIndent/PythonSmartIndent.cpp
===================================================================
--- src/plugins/contrib/SmartIndent/PythonSmartIndent.cpp	(revision 8478)
+++ src/plugins/contrib/SmartIndent/PythonSmartIndent.cpp	(working copy)
@@ -69,4 +69,7 @@
             stc->EndUndoAction();
         }
     }
+
+    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
+        ed->DoSelectionBraceCompletion(stc, ch);
 }
Index: src/plugins/contrib/SmartIndent/LuaSmartIndent.cpp
===================================================================
--- src/plugins/contrib/SmartIndent/LuaSmartIndent.cpp	(revision 8478)
+++ src/plugins/contrib/SmartIndent/LuaSmartIndent.cpp	(working copy)
@@ -67,6 +67,9 @@
             stc->EndUndoAction();
         }
     }
+
+    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
+        ed->DoSelectionBraceCompletion(stc, ch);
 }
 
 bool LuaSmartIndent::BraceIndent(cbStyledTextCtrl *stc, wxString &indent)const
Index: src/plugins/contrib/SmartIndent/XMLSmartIndent.cpp
===================================================================
--- src/plugins/contrib/SmartIndent/XMLSmartIndent.cpp	(revision 8478)
+++ src/plugins/contrib/SmartIndent/XMLSmartIndent.cpp	(working copy)
@@ -47,16 +47,28 @@
 
     ed->AutoIndentDone(); // we are responsible
 
-    const int pos = stc->GetCurrentPos();
+    int pos = stc->GetCurrentPos();
     int currLine = stc->LineFromPosition(pos);
 
     const wxChar ch = event.GetKey();
     wxRegEx reTag(wxT("***:<[ \t]*?(|/)[ \t]*?([a-zA-Z][a-zA-Z0-9_-]*).*?(|/)[ \t]*?>"));
 
+    bool complQuote = true;
+    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
+    {
+        ed->DoSelectionBraceCompletion(stc, ch);
+        if (pos != stc->GetCurrentPos())
+        {
+            complQuote = false;
+            pos = stc->GetCurrentPos();
+            currLine = stc->LineFromPosition(pos);
+        }
+    }
+
     if (BraceCompletionEnabled())
     {
         // finish tag
-        if (ch == wxT('>'))
+        if ( ch == wxT('>') && !stc->IsString(stc->GetStyleAt(pos)) )
         {
             wxString tag;
             for (int i = pos - 2; i > 0; --i)
@@ -72,7 +84,7 @@
                 stc->InsertText(pos, wxT("</") + reTag.GetMatch(tag, 2) + wxT(">"));
         }
         // close string
-        else if (ch == wxT('"') || ch == wxT('\''))
+        else if (complQuote && (ch == wxT('"') || ch == wxT('\'')))
         {
             if (stc->GetCharAt(pos) == ch)
             {
@@ -113,14 +125,14 @@
         }
     }
     // indent
-    if ( (ch == wxT('\n')) || ( (stc->GetEOLMode() == wxSCI_EOL_CR) && (ch == wxT('\r')) ) )
+    if (   AutoIndentEnabled()
+        && ( (ch == wxT('\n')) || ((stc->GetEOLMode() == wxSCI_EOL_CR) && (ch == wxT('\r'))) ) )
     {
-        if (AutoIndentEnabled())
+        wxString indent = ed->GetLineIndentString(currLine - 1);
+        stc->BeginUndoAction();
+        if (SmartIndentEnabled()) // smart indent
         {
-            wxString indent = ed->GetLineIndentString(currLine - 1);
             int idx = stc->GetLine(currLine - 1).Find(wxT('>'), true);
-
-            stc->BeginUndoAction();
             if (idx != wxNOT_FOUND)
             {
                 wxString tag;
@@ -167,10 +179,10 @@
                     }
                 }
             }
-            stc->InsertText(pos, indent);
-            stc->GotoPos(pos + indent.Length());
-            stc->ChooseCaretX();
-            stc->EndUndoAction();
         }
+        stc->InsertText(pos, indent);
+        stc->GotoPos(pos + indent.Length());
+        stc->ChooseCaretX();
+        stc->EndUndoAction();
     }
 }
Index: src/plugins/contrib/SmartIndent/PascalSmartIndent.cpp
===================================================================
--- src/plugins/contrib/SmartIndent/PascalSmartIndent.cpp	(revision 8478)
+++ src/plugins/contrib/SmartIndent/PascalSmartIndent.cpp	(working copy)
@@ -44,6 +44,9 @@
         DoIndent(ed, langname);   // indent because \n added
     else if ( ch != wxT(' ') )
         DoUnIndent(ed, langname); // un-indent because not a newline added
+
+    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
+        ed->DoSelectionBraceCompletion(stc, ch);
 }
 
 void PascalSmartIndent::DoIndent(cbEditor* ed, const wxString& WXUNUSED(langname)) const
Index: src/plugins/contrib/SmartIndent/HDLSmartIndent.cpp
===================================================================
--- src/plugins/contrib/SmartIndent/HDLSmartIndent.cpp	(revision 8478)
+++ src/plugins/contrib/SmartIndent/HDLSmartIndent.cpp	(working copy)
@@ -49,6 +49,9 @@
         DoIndent(ed, langname);   // indent because \n added
     else if ( ch != wxT(' ') )
         DoUnIndent(ed, langname); // un-indent because not a newline added
+
+    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
+        ed->DoSelectionBraceCompletion(stc, ch);
 }
 
 int HDLSmartIndent::FindBlockStartVHDL(cbEditor* ed, int position, wxString block) const
Index: src/plugins/contrib/SmartIndent/FortranSmartIndent.cpp
===================================================================
--- src/plugins/contrib/SmartIndent/FortranSmartIndent.cpp	(revision 8478)
+++ src/plugins/contrib/SmartIndent/FortranSmartIndent.cpp	(working copy)
@@ -103,4 +103,7 @@
 
         stc->EndUndoAction();
     }
+
+    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
+        ed->DoSelectionBraceCompletion(stc, ch);
 }
Index: src/include/cbeditor.h
===================================================================
--- src/include/cbeditor.h	(revision 8478)
+++ src/include/cbeditor.h	(working copy)
@@ -301,6 +301,7 @@
         static void ApplyStyles(cbStyledTextCtrl* control);
 
         void AutoIndentDone();
+        void DoSelectionBraceCompletion(cbStyledTextCtrl* control, const wxChar& ch) const;
     private:
         cbEditor(const cbEditor& /*rhs*/); // prevent copy construction
 
Index: src/sdk/cbeditor.cpp
===================================================================
--- src/sdk/cbeditor.cpp	(revision 8478)
+++ src/sdk/cbeditor.cpp	(working copy)
@@ -3095,12 +3095,33 @@
                 control->EndUndoAction();
             }
         }
+        if(   Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/brace_completion"), true)
+           || control->IsBraceShortcutActive())
+            DoSelectionBraceCompletion(control, ch);
     }
 }
 void cbEditor::AutoIndentDone()
 {
     m_autoIndentDone = true;
 }
+void cbEditor::DoSelectionBraceCompletion(cbStyledTextCtrl* control, const wxChar& ch) const
+{
+    if (control->GetLastSelectedText().IsEmpty())
+        return;
+    const wxString braces(wxT("([{<'\")]}>'\""));
+    const int braceAIdx = braces.Find(ch, true); // from end (so caret ends after quotes)
+    if (braceAIdx == wxNOT_FOUND)
+        return;
+    const int braceBIdx = (braceAIdx + (braces.Length() / 2)) % braces.Length();
+    control->BeginUndoAction();
+    control->DeleteBack();
+    if (braceAIdx < braceBIdx)
+        control->InsertText(control->GetCurrentPos(),
+                            braces[braceAIdx] + control->GetLastSelectedText() + braces[braceBIdx]);
+    else
+        control->AddText(braces[braceBIdx] + control->GetLastSelectedText() + braces[braceAIdx]);
+    control->EndUndoAction();
+}
 
 void cbEditor::OnEditorDwellStart(wxScintillaEvent& event)
 {