void CodeEditor::OnCharAdded(wxScintillaEvent &event) { char ch = event.GetKey(); int currentLine = GetCurrentLine(); int pos = GetCurrentPos(); if (ch == wxT('\n') && currentLine > 0) { BeginUndoAction(); wxString indent = GetLineIndentString(currentLine - 1); wxChar b = GetLastNonWhitespaceChar(); if(b == wxT('{')) { if(GetUseTabs()) indent << wxT("\t"); else indent << wxT(" "); } InsertText(pos, indent); GotoPos((int)(pos + indent.Length())); ChooseCaretX(); EndUndoAction(); } else if(ch == wxT('}')) { BeginUndoAction(); wxString line = GetLine(currentLine); line.Trim(false); line.Trim(true); if(line.Matches(wxT("}"))) { pos = GetCurrentPos() - 2; pos = FindBlockStart(pos, wxT('{'), wxT('}')); if(pos != -1) { wxString indent = GetLineIndentString(LineFromPosition(pos)); indent << wxT('}'); DelLineLeft(); DelLineRight(); pos = GetCurrentPos(); InsertText(pos, indent); GotoPos((int)(pos + indent.Length())); ChooseCaretX(); } } EndUndoAction(); } }
void ScintillaWrapper::forEachLine(PyObject* function) { if (PyCallable_Check(function)) { BeginUndoAction(); long lineCount = GetLineCount(); for(int line = 0; line < lineCount;) { boost::python::object result = boost::python::call<boost::python::object>(function, GetLine(line), line, lineCount); if (result.is_none() || !PyInt_Check(result.ptr())) { ++line; } else { line += PyInt_AsLong(result.ptr()); } lineCount = GetLineCount(); } EndUndoAction(); } }
void ScintillaWrapper::replace(boost::python::object searchStr, boost::python::object replaceStr, boost::python::object flags) { int start = 0; int end = GetLength(); int iFlags = 0; if (!flags.is_none()) { iFlags |= boost::python::extract<int>(flags); } const char *replaceChars = boost::python::extract<const char*>(replaceStr.attr("__str__")()); size_t replaceLength = strlen(replaceChars); Sci_TextToFind src; src.lpstrText = const_cast<char*>((const char *)boost::python::extract<const char *>(searchStr.attr("__str__")())); BeginUndoAction(); int result = 0; while(result != -1) { src.chrg.cpMin = start; src.chrg.cpMax = end; result = callScintilla(SCI_FINDTEXT, iFlags, reinterpret_cast<LPARAM>(&src)); // If nothing found, then just finish if (-1 == result) { return; } else { // Replace the location found with the replacement text SetTargetStart(src.chrgText.cpMin); SetTargetEnd(src.chrgText.cpMax); callScintilla(SCI_REPLACETARGET, replaceLength, reinterpret_cast<LPARAM>(replaceChars)); start = src.chrgText.cpMin + (int)replaceLength; end = end + ((int)replaceLength - (src.chrgText.cpMax - src.chrgText.cpMin)); } } EndUndoAction(); }
bool cbStyledTextCtrl::DoSelectionBraceCompletion(const wxChar& ch) { if (GetLastSelectedText().IsEmpty()) return false; // nothing changed const wxString braces(wxT("([{<'\")]}>'\"")); const int braceAIdx = braces.Find(ch, true); // from end (so caret is placed after quotes) if (braceAIdx == wxNOT_FOUND) return false; // nothing changed const int braceBIdx = (braceAIdx + (braces.Length() / 2)) % braces.Length(); BeginUndoAction(); DeleteBack(); if (braceAIdx < braceBIdx) InsertText(GetCurrentPos(), braces[braceAIdx] + GetLastSelectedText() + braces[braceBIdx]); else AddText(braces[braceBIdx] + GetLastSelectedText() + braces[braceAIdx]); EndUndoAction(); return true; // succeeded }
void ScintillaWrapper::pyreplace(boost::python::object searchExp, boost::python::object replaceStr, boost::python::object count, boost::python::object flags, boost::python::object startLine, boost::python::object endLine) { boost::python::object re_module( (boost::python::handle<>(PyImport_ImportModule("re"))) ); if (!re_module.is_none()) { BeginUndoAction(); const char *strCount = boost::python::extract<const char *>(count.attr("__str__")()); int iCount; int iFlags = 0; if (!flags.is_none()) { iFlags = boost::python::extract<int>(flags); } int start = 0; if (!startLine.is_none()) { start = boost::python::extract<int>(startLine); } int end = -1; if (!startLine.is_none()) { end = boost::python::extract<int>(endLine); } iCount = atoi(strCount); bool ignoreCount = (iCount == 0); bool includeLineEndings = (iFlags & RE_INCLUDELINEENDINGS) == RE_INCLUDELINEENDINGS; long lineCount = GetLineCount(); boost::python::object re = re_module.attr("compile")(searchExp, flags); size_t bufferLength = 0; Sci_TextRange range; range.chrg.cpMin = 0; range.lpstrText = NULL; boost::python::tuple result; idx_t currentStartPosition; int infiniteLoopCheck = 0; int previousLine = -1; for(int line = start; line < lineCount && (ignoreCount || iCount > 0) && (-1 == end || line <= end); ++line) { if (line == previousLine) { if (++infiniteLoopCheck >= 1000) { EndUndoAction(); PyErr_SetString(PyExc_SystemError, "Infinite loop detected in pyreplace"); if (range.lpstrText) { delete[] range.lpstrText; } throw boost::python::error_already_set(); } } previousLine = line; if (includeLineEndings) { result = boost::python::extract<boost::python::tuple>(re.attr("subn")(replaceStr, GetLine(line), ignoreCount ? 0 : iCount)); } else { range.chrg.cpMin = PositionFromLine(line); range.chrg.cpMax = GetLineEndPosition(line); if (bufferLength < (size_t)((range.chrg.cpMax - range.chrg.cpMin) + 1)) { if (range.lpstrText) delete [] range.lpstrText; bufferLength = (size_t)((range.chrg.cpMax - range.chrg.cpMin) + 1); range.lpstrText = new char[bufferLength + 1]; } callScintilla(SCI_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&range)); result = boost::python::extract<boost::python::tuple>(re.attr("subn")(replaceStr, const_cast<const char *>(range.lpstrText), ignoreCount ? 0 : iCount)); } int numSubs = boost::python::extract<int>(result[1]); if (numSubs != 0) { size_t resultLength = _len(result[0]); if (includeLineEndings) { currentStartPosition = (idx_t)PositionFromLine(line); replaceWholeLine(line, result[0]); } else { currentStartPosition = (idx_t)range.chrg.cpMin; replaceLine(line, result[0]); } int newLine = LineFromPosition((int)(currentStartPosition + resultLength)); // If the line number has moved on more than one // there must have been one or more new lines in the // replacement, or no newline, hence the lines have become less if ((newLine - line) != (includeLineEndings ? 1 : 0)) { line = newLine - (includeLineEndings ? 1 : 0); lineCount = GetLineCount(); } iCount -= numSubs; } } if (range.lpstrText) delete[] range.lpstrText; EndUndoAction(); } }
void ScintillaWrapper::pymlreplace(boost::python::object searchExp, boost::python::object replaceStr, boost::python::object count, boost::python::object flags, boost::python::object startPosition, boost::python::object endPosition) { boost::python::str contents; offset_t currentOffset = 0; if (startPosition.is_none() && endPosition.is_none()) { contents = GetCharacterPointer(); } else { Sci_TextRange range; if (!startPosition.is_none()) { range.chrg.cpMin = boost::python::extract<int>(startPosition); } else { range.chrg.cpMin = 0; } if (!endPosition.is_none()) { range.chrg.cpMax = boost::python::extract<int>(endPosition); } else { range.chrg.cpMax = GetLength(); } currentOffset = (offset_t)range.chrg.cpMin; range.lpstrText = new char[size_t((range.chrg.cpMax - range.chrg.cpMin) + 1)]; callScintilla(SCI_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&range)); contents = boost::python::str(const_cast<const char *>(range.lpstrText)); delete[] range.lpstrText; } boost::python::object re_module( (boost::python::handle<>(PyImport_ImportModule("re"))) ); int iFlags = 0; int iCount = 0; if (!flags.is_none()) { iFlags = boost::python::extract<int>(flags); } if (!count.is_none()) { iCount = boost::python::extract<int>(count); } if (0 == iCount) iCount = -1; boost::python::object re = re_module.attr("compile")(searchExp, iFlags | boost::python::extract<int>(re_module.attr("MULTILINE"))); if (!re_module.is_none()) { boost::python::object match; BeginUndoAction(); boost::python::object oreplacement; size_t replacementLength; idx_t matchStart, matchEnd; idx_t startPos = 0; do { match = re.attr("search")(contents, startPos); if (!match.is_none()) { // Get expanded replacement string oreplacement = match.attr("expand")(replaceStr); // Calculate offsets matchStart = (idx_t)boost::python::extract<int>(match.attr("start")()); matchEnd = (idx_t)boost::python::extract<int>(match.attr("end")()); // Extract text replacement const char *replacement = boost::python::extract<const char *>(oreplacement); replacementLength = _len(oreplacement); // Replace text in Scintilla callScintilla(SCI_SETTARGETSTART, static_cast<offset_t>(matchStart) + currentOffset); callScintilla(SCI_SETTARGETEND, static_cast<offset_t>(matchEnd) + currentOffset); callScintilla(SCI_REPLACETARGET, replacementLength, reinterpret_cast<LPARAM>(replacement)); // Calculate the difference between the old string, // and the new replacement, and add it to the currentOffset currentOffset += static_cast<offset_t>(replacementLength - (matchEnd - matchStart)); // Set startPos to the end of the last match - startPos is with the original document startPos = matchEnd; } } while(!match.is_none() && (iCount == -1 || --iCount > 0)); EndUndoAction(); } }