boost::python::str ScintillaWrapper::getWord(boost::python::object position, boost::python::object useOnlyWordChars /* = true */) { int pos; if (position.is_none()) { pos = callScintilla(SCI_GETCURRENTPOS); } else { pos = boost::python::extract<int>(position); } bool wordChars; if (useOnlyWordChars.is_none()) { wordChars = true; } else { wordChars = boost::python::extract<bool>(useOnlyWordChars); } int startPos = callScintilla(SCI_WORDSTARTPOSITION, pos, wordChars); int endPos = callScintilla(SCI_WORDENDPOSITION, pos, wordChars); Sci_TextRange tr; tr.chrg.cpMin = startPos; tr.chrg.cpMax = endPos; tr.lpstrText = new char[size_t((endPos - startPos) + 1)]; callScintilla(SCI_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr)); boost::python::str retVal(const_cast<const char *>(tr.lpstrText)); delete[] tr.lpstrText; return retVal; }
void ConsoleDialog::writeError(size_t length, const char *text) { size_t docLength = (size_t)callScintilla(SCI_GETLENGTH); size_t realLength = length; callScintilla(SCI_SETREADONLY, 0); for (idx_t i = 0; i < length; ++i) { if (text[i] == '\r') { if (i) { callScintilla(SCI_APPENDTEXT, i, reinterpret_cast<LPARAM>(text)); } text += i + 1; length -= i + 1; realLength--; i = 0; } } if (length > 0) { callScintilla(SCI_APPENDTEXT, length, reinterpret_cast<LPARAM>(text)); } callScintilla(SCI_SETREADONLY, 1); callScintilla(SCI_STARTSTYLING, docLength, 0x01); callScintilla(SCI_SETSTYLING, realLength, 1); callScintilla(SCI_COLOURISE, docLength, -1); callScintilla(SCI_GOTOPOS, docLength + realLength); }
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(); }
void ConsoleDialog::onHotspotClick(SCNotification* notification) { assert(m_console != NULL); if (m_console) { idx_t lineNumber = callScintilla(SCI_LINEFROMPOSITION, static_cast<WPARAM>(notification->position)); LineDetails lineDetails; lineDetails.lineLength = (size_t)callScintilla(SCI_GETLINE, lineNumber); if (lineDetails.lineLength != SIZE_MAX) { lineDetails.line = new char[lineDetails.lineLength + 1]; callScintilla(SCI_GETLINE, lineNumber, reinterpret_cast<LPARAM>(lineDetails.line)); lineDetails.line[lineDetails.lineLength] = '\0'; if (parseLine(&lineDetails)) { lineDetails.line[lineDetails.filenameEnd] = '\0'; m_console->openFile(lineDetails.line + lineDetails.filenameStart, lineDetails.errorLineNo); } } } }
void ConsoleDialog::doDialog() { if (!isCreated()) { create(m_data); assert(m_data); if (m_data) { // define the default docking behaviour m_data->uMask = DWS_DF_CONT_BOTTOM | DWS_ICONTAB; m_data->pszName = new TCHAR[20]; _tcscpy_s(m_data->pszName, 20, _T("Python")); RECT rc; rc.bottom = 0; rc.top = 0; rc.left = 0; rc.right = 0; m_hTabIcon = (HICON)::LoadImage(_hInst, MAKEINTRESOURCE(IDI_PYTHON8), IMAGE_ICON, 16, 16, LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT); m_data->hIconTab = m_hTabIcon; m_data->pszModuleName = _T("Python Script"); m_data->dlgID = -1; /* IDD_CONSOLE */ m_data->pszAddInfo = NULL; //_pExProp->szCurrentPath; m_data->iPrevCont = -1; m_data->hClient = _hSelf; m_data->rcFloat = rc; ::SendMessage(_hParent, NPPM_DMMREGASDCKDLG, 0, reinterpret_cast<LPARAM>(m_data)); // Parse the whole doc, in case we've had errors that haven't been parsed yet callScintilla(SCI_COLOURISE, 0, -1); } } display(true); }
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(); } }
boost::python::str ScintillaWrapper::GetCharacterPointer() { return boost::python::str(reinterpret_cast<const char*>(callScintilla(SCI_GETCHARACTERPOINTER))); }
void ConsoleDialog::onStyleNeeded(SCNotification* notification) { idx_t startPos = (idx_t)callScintilla(SCI_GETENDSTYLED); idx_t startLine = (idx_t)callScintilla(SCI_LINEFROMPOSITION, startPos); idx_t endPos = (idx_t)notification->position; idx_t endLine = (idx_t)callScintilla(SCI_LINEFROMPOSITION, endPos); LineDetails lineDetails; for(idx_t lineNumber = startLine; lineNumber <= endLine; ++lineNumber) { lineDetails.lineLength = (size_t)callScintilla(SCI_GETLINE, lineNumber); if (lineDetails.lineLength > 0) { lineDetails.line = new char[lineDetails.lineLength + 1]; callScintilla(SCI_GETLINE, lineNumber, reinterpret_cast<LPARAM>(lineDetails.line)); lineDetails.line[lineDetails.lineLength] = '\0'; lineDetails.errorLevel = EL_UNSET; if (parseLine(&lineDetails)) { startPos = (idx_t)callScintilla(SCI_POSITIONFROMLINE, lineNumber); // Check that it's not just a file called '<console>' if (strncmp(lineDetails.line + lineDetails.filenameStart, "<console>", lineDetails.filenameEnd - lineDetails.filenameStart)) { int mask, style; switch(lineDetails.errorLevel) { case EL_WARNING: mask = 0x04; style = 0x04; break; case EL_ERROR: mask = 0x01; style = 0x01; break; case EL_UNSET: case EL_INFO: default: mask = 0x00; style = 0x00; break; } if (lineDetails.filenameStart > 0) { callScintilla(SCI_STARTSTYLING, startPos, mask); callScintilla(SCI_SETSTYLING, lineDetails.filenameStart, style); } callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameStart, mask | 0x02); callScintilla(SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart, style | 0x02); if (lineDetails.lineLength > lineDetails.filenameEnd) { callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameEnd, mask); callScintilla(SCI_SETSTYLING, lineDetails.lineLength - lineDetails.filenameEnd, style); } } } delete[] lineDetails.line; } } // ensure that everything is set as styled (just move the endStyled variable on to the requested position) callScintilla(SCI_STARTSTYLING, static_cast<WPARAM>(notification->position), 0x0); }
void ConsoleDialog::createOutputWindow(HWND hParentWindow) { m_scintilla = (HWND)::SendMessage(_hParent, NPPM_CREATESCINTILLAHANDLE, 0, reinterpret_cast<LPARAM>(hParentWindow)); callScintilla(SCI_SETREADONLY, 1, 0); /* Style bits * LSB 0 - stderr = 1 * 1 - hotspot * 2 - warning * ... to be continued */ // Set the codepage to UTF-8 callScintilla(SCI_SETCODEPAGE, 65001); // 0 is stdout, black text callScintilla(SCI_STYLESETSIZE, 0 /* = style number */, 8 /* = size in points */); // 1 is stderr, red text callScintilla(SCI_STYLESETSIZE, 1 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 1, RGB(250, 0, 0)); // 2 is stdout, black text, underline hotspot callScintilla(SCI_STYLESETSIZE, 2 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETUNDERLINE, 2 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 2, 1); // 3 is stderr, red text, underline hotspot callScintilla(SCI_STYLESETSIZE, 3 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 3, RGB(250, 0, 0)); callScintilla(SCI_STYLESETUNDERLINE, 3 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 3, 1); // 4 stdout warning without hotspot callScintilla(SCI_STYLESETSIZE, 4 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 4, RGB(199, 175, 7)); // mucky yellow // 5 stderr warning without hotspot callScintilla(SCI_STYLESETSIZE, 5 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 5, RGB(255, 128, 64)); // orange // 6 is hotspot, stdout, warning callScintilla(SCI_STYLESETSIZE, 6 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 6, RGB(199, 175, 7)); // mucky yellow callScintilla(SCI_STYLESETUNDERLINE, 6 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 6, 1); // 7 is hotspot, stderr, warning callScintilla(SCI_STYLESETSIZE, 7 /* = style number */, 8 /* = size in points */); callScintilla(SCI_STYLESETFORE, 7, RGB(255, 128, 64)); // orange callScintilla(SCI_STYLESETUNDERLINE, 7 /* = style number */, 1 /* = underline */); callScintilla(SCI_STYLESETHOTSPOT, 7, 1); callScintilla(SCI_USEPOPUP, 0); callScintilla(SCI_SETLEXER, SCLEX_CONTAINER); }
BOOL CALLBACK ConsoleDialog::run_dlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_INITDIALOG: { SetParent(m_scintilla, hWnd); ShowWindow(m_scintilla, SW_SHOW); m_hInput = ::GetDlgItem(_hSelf, IDC_INPUT); HFONT hCourier = CreateFont(14,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, FIXED_PITCH, _T("Courier New")); if (hCourier != NULL) { SendMessage(m_hInput, WM_SETFONT, reinterpret_cast<WPARAM>(hCourier), TRUE); SendMessage(::GetDlgItem(_hSelf, IDC_PROMPT), WM_SETFONT, reinterpret_cast<WPARAM>(hCourier), TRUE); } // Subclass the Input box ::SetWindowLongPtr(::GetDlgItem(_hSelf, IDC_INPUT), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); m_originalInputWndProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(::GetDlgItem(_hSelf, IDC_INPUT), GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ConsoleDialog::inputWndProc))); return TRUE; } case WM_SIZE: MoveWindow(m_scintilla, 0, 0, LOWORD(lParam), HIWORD(lParam)-30, TRUE); MoveWindow(::GetDlgItem(_hSelf, IDC_PROMPT), 0, HIWORD(lParam)-25, 30, 25, TRUE); MoveWindow(m_hInput, 30, HIWORD(lParam)-30, LOWORD(lParam) - 85, 25, TRUE); MoveWindow(::GetDlgItem(_hSelf, IDC_RUN), LOWORD(lParam) - 50, HIWORD(lParam) - 30, 50, 25, TRUE); // ::SendMessage(m_scintilla, WM_SIZE, 0, MAKEWORD(LOWORD(lParam) - 10, HIWORD(lParam) - 30)); return FALSE; case WM_CONTEXTMENU: { MENUITEMINFO mi; mi.cbSize = sizeof(mi); mi.fMask = MIIM_STATE; if (0 == (callScintilla(SCI_GETSELECTIONSTART) - callScintilla(SCI_GETSELECTIONEND))) { mi.fState = MFS_DISABLED; } else { mi.fState = MFS_ENABLED; } SetMenuItemInfo(m_hContext, 2, FALSE, &mi); // Thanks MS for corrupting the value of BOOL. :-/ // From the documentation (http://msdn.microsoft.com/en-us/library/ms648002.aspx): // // If you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item // identifier of the item that the user selected. If the user cancels the menu without making // a selection, or if an error occurs, then the return value is zero. INT cmdID = (INT)TrackPopupMenu(m_hContext, TPM_RETURNCMD, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, _hSelf, NULL); switch(cmdID) { case 1: // Select All callScintilla(SCI_SELECTALL); break; case 2: // Copy callScintilla(SCI_COPY); break; case 3: // Clear clearText(); break; default: break; } } break; case WM_COMMAND: if (LOWORD(wParam) == IDC_RUN) { if (m_runButtonIsRun) { runStatement(); } else { assert(m_console != NULL); if (m_console) { m_console->stopStatement(); } } //MessageBox(NULL, _T("Command") , _T("Python Command"), 0); return FALSE; } break; case WM_NOTIFY: { LPNMHDR nmhdr = reinterpret_cast<LPNMHDR>(lParam); if (m_scintilla == nmhdr->hwndFrom) { switch(nmhdr->code) { case SCN_STYLENEEDED: onStyleNeeded(reinterpret_cast<SCNotification*>(lParam)); return FALSE; case SCN_HOTSPOTCLICK: onHotspotClick(reinterpret_cast<SCNotification*>(lParam)); return FALSE; default: break; } } break; } default: break; } return DockingDlgInterface::run_dlgProc(message, wParam, lParam); }