From 7e0ed0ebf3fe1d401cf2a44958b0b5390f4713c0 Mon Sep 17 00:00:00 2001 From: Don Ho Date: Mon, 13 Feb 2012 01:45:05 +0000 Subject: [PATCH] [NEW_FEATURE] (Author: Dave Brotherstone) Add PCRE (Perl Compatible Regular Expressions) support. git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@863 f5eea248-9336-0410-98b8-ebc06183d4e3 --- PowerEditor/src/Parameters.cpp | 5 + PowerEditor/src/Parameters.h | 4 +- .../src/ScitillaComponent/FindReplaceDlg.cpp | 41 ++- .../src/ScitillaComponent/FindReplaceDlg.h | 9 +- .../src/ScitillaComponent/FindReplaceDlg.rc | 5 +- .../src/ScitillaComponent/FindReplaceDlg_rc.h | 4 +- .../xmlMatchedTagsHighlighter.cpp | 20 +- .../xmlMatchedTagsHighlighter.h | 2 +- PowerEditor/visual.net/notepadPlus.vcproj | 2 +- scintilla/boostregex/AnsiDocumentIterator.h | 94 +++++ scintilla/boostregex/BoostRegExSearch.cxx | 323 ++++++++++++++++++ scintilla/boostregex/BuildBoost.bat | 88 +++++ scintilla/boostregex/UTF8DocumentIterator.cxx | 57 ++++ scintilla/boostregex/UTF8DocumentIterator.h | 149 ++++++++ scintilla/boostregex/nppSpecifics.mak | 44 +++ scintilla/win32/scintilla.mak | 2 + 16 files changed, 817 insertions(+), 32 deletions(-) create mode 100644 scintilla/boostregex/AnsiDocumentIterator.h create mode 100644 scintilla/boostregex/BoostRegExSearch.cxx create mode 100644 scintilla/boostregex/BuildBoost.bat create mode 100644 scintilla/boostregex/UTF8DocumentIterator.cxx create mode 100644 scintilla/boostregex/UTF8DocumentIterator.h create mode 100644 scintilla/boostregex/nppSpecifics.mak diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index d957a64d4..d0fa6c3f3 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -1864,6 +1864,10 @@ void NppParameters::feedFindHistoryParameters(TiXmlNode *node) (findHistoryRoot->ToElement())->Attribute(TEXT("transparency"), &_findHistory._transparency); if (_findHistory._transparency <= 0 || _findHistory._transparency > 200) _findHistory._transparency = 150; + + boolStr = (findHistoryRoot->ToElement())->Attribute(TEXT("dotMatchesNewline")); + if (boolStr) + _findHistory._dotMatchesNewline = !lstrcmp(TEXT("yes"), boolStr); } void NppParameters::feedShortcut(TiXmlNode *node) @@ -4633,6 +4637,7 @@ bool NppParameters::writeFindHistory() (findHistoryRoot->ToElement())->SetAttribute(TEXT("searchMode"), _findHistory._searchMode); (findHistoryRoot->ToElement())->SetAttribute(TEXT("transparencyMode"), _findHistory._transparencyMode); (findHistoryRoot->ToElement())->SetAttribute(TEXT("transparency"), _findHistory._transparency); + (findHistoryRoot->ToElement())->SetAttribute(TEXT("dotMatchesNewline"), _findHistory._dotMatchesNewline?TEXT("yes"):TEXT("no")); TiXmlElement hist_element(TEXT("")); diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 75db0c6cc..a4a63099f 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -961,7 +961,8 @@ struct FindHistory { _isMatchWord(false), _isMatchCase(false),_isWrap(true),_isDirectionDown(true),\ _isFifRecuisive(true), _isFifInHiddenFolder(false), _isDlgAlwaysVisible(false),\ _isFilterFollowDoc(false), _isFolderFollowDoc(false),\ - _searchMode(normal), _transparencyMode(onLossingFocus), _transparency(150) + _searchMode(normal), _transparencyMode(onLossingFocus), _transparency(150), + _dotMatchesNewline(false) {}; int _nbMaxFindHistoryPath; @@ -978,6 +979,7 @@ struct FindHistory { bool _isMatchCase; bool _isWrap; bool _isDirectionDown; + bool _dotMatchesNewline; bool _isFifRecuisive; bool _isFifInHiddenFolder; diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp index 2f6317b4b..e71825198 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp @@ -343,16 +343,12 @@ void FindReplaceDlg::fillFindHistory() ::SendDlgItemMessage(_hSelf, IDNORMAL, BM_SETCHECK, findHistory._searchMode == FindHistory::normal, 0); ::SendDlgItemMessage(_hSelf, IDEXTENDED, BM_SETCHECK, findHistory._searchMode == FindHistory::extended, 0); ::SendDlgItemMessage(_hSelf, IDREGEXP, BM_SETCHECK, findHistory._searchMode == FindHistory::regExpr, 0); + ::SendDlgItemMessage(_hSelf, IDREDOTMATCHNL, BM_SETCHECK, findHistory._dotMatchesNewline, 0); if (findHistory._searchMode == FindHistory::regExpr) { //regex doesnt allow wholeword ::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, BST_UNCHECKED, 0); ::EnableWindow(::GetDlgItem(_hSelf, IDWHOLEWORD), (BOOL)false); - - //regex doesnt allow upward search - ::SendDlgItemMessage(_hSelf, IDDIRECTIONDOWN, BM_SETCHECK, BST_CHECKED, 0); - ::SendDlgItemMessage(_hSelf, IDDIRECTIONUP, BM_SETCHECK, BST_UNCHECKED, 0); - ::EnableWindow(::GetDlgItem(_hSelf, IDDIRECTIONUP), (BOOL)false); } if (nppParams->isTransparentAvailable()) @@ -993,6 +989,10 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP } return TRUE; //Option actions + case IDREDOTMATCHNL: + findHistory._dotMatchesNewline = _options._dotMatchesNewline = isCheckedOrNot(IDREDOTMATCHNL); + return TRUE; + case IDWHOLEWORD : findHistory._isMatchWord = _options._isWholeWord = isCheckedOrNot(IDWHOLEWORD); return TRUE; @@ -1008,16 +1008,19 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP { _options._searchType = FindRegex; findHistory._searchMode = FindHistory::regExpr; + ::EnableWindow(GetDlgItem(_hSelf, IDREDOTMATCHNL), true); } else if (isCheckedOrNot(IDEXTENDED)) { _options._searchType = FindExtended; findHistory._searchMode = FindHistory::extended; + ::EnableWindow(GetDlgItem(_hSelf, IDREDOTMATCHNL), false); } else { _options._searchType = FindNormal; - findHistory._searchMode = FindHistory::normal; + findHistory._searchMode = FindHistory::normal; + ::EnableWindow(GetDlgItem(_hSelf, IDREDOTMATCHNL), false); } bool isRegex = (_options._searchType == FindRegex); @@ -1027,14 +1030,10 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP _options._isWholeWord = false; ::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, _options._isWholeWord?BST_CHECKED:BST_UNCHECKED, 0); - //regex doesnt allow upward search - ::SendDlgItemMessage(_hSelf, IDDIRECTIONDOWN, BM_SETCHECK, BST_CHECKED, 0); - ::SendDlgItemMessage(_hSelf, IDDIRECTIONUP, BM_SETCHECK, BST_UNCHECKED, 0); - _options._whichDirection = DIR_DOWN; } ::EnableWindow(::GetDlgItem(_hSelf, IDWHOLEWORD), (BOOL)!isRegex); - ::EnableWindow(::GetDlgItem(_hSelf, IDDIRECTIONUP), (BOOL)!isRegex); + return TRUE; } case IDWRAP : @@ -1266,7 +1265,11 @@ bool FindReplaceDlg::processFindNext(const TCHAR *txt2find, const FindOption *op return false; } } - + else if (posFind == -2) // Invalid Regular expression + { + ::MessageBox(_hParent, TEXT("Invalid regular expression"), TEXT("Find"), MB_ICONERROR | MB_OK); + return false; + } int start = posFind; int end = int((*_ppEditView)->execute(SCI_GETTARGETEND)); @@ -1329,6 +1332,11 @@ bool FindReplaceDlg::processReplace(const TCHAR *txt2find, const TCHAR *txt2repl (*_ppEditView)->execute(SCI_SETSEL, start, start + replacedLen); } } + else if (posFind == -2) // Invalid Regular expression + { + ::MessageBox(_hParent, TEXT("Invalid regular expression"), TEXT("Find"), MB_ICONERROR | MB_OK); + return false; + } delete [] pTextFind; delete [] pTextReplace; @@ -1509,11 +1517,12 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con (*_ppEditView)->execute(SCI_SETSEARCHFLAGS, flags); targetStart = (*_ppEditView)->searchInTarget(pTextFind, stringSizeFind, startRange, endRange); - if ((targetStart != -1) && (op == ProcessFindAll)) //add new filetitle if this file results in hits + if ((targetStart >= 0) && (op == ProcessFindAll)) //add new filetitle if this file results in hits { _pFinder->addFileNameTitle(fileName); } - while (targetStart != -1) + + while (targetStart != -1 && targetStart != -2) { //int posFindBefore = posFind; targetStart = int((*_ppEditView)->execute(SCI_GETTARGETSTART)); @@ -1866,6 +1875,8 @@ void FindReplaceDlg::saveInMacro(int cmd, int cmdType) ::SendMessage(_hParent, WM_FRSAVE_STR, IDFINDWHAT, reinterpret_cast(_options._str2Search.c_str())); booleans |= _options._isWholeWord?IDF_WHOLEWORD:0; booleans |= _options._isMatchCase?IDF_MATCHCASE:0; + booleans |= _options._dotMatchesNewline?IDF_REDOTMATCHNL:0; + ::SendMessage(_hParent, WM_FRSAVE_INT, IDNORMAL, _options._searchType); if (cmd == IDCMARKALL) { @@ -1911,6 +1922,7 @@ void FindReplaceDlg::execSavedCommand(int cmd, int intValue, generic_string stri _env->_isInSelection = ((intValue & IDF_IN_SELECTION_CHECK)> 0); _env->_isWrapAround = ((intValue & IDF_WRAP)> 0); _env->_whichDirection = ((intValue & IDF_WHICH_DIRECTION)> 0); + _env->_dotMatchesNewline = ((intValue & IDF_REDOTMATCHNL)> 0); break; case IDNORMAL: _env->_searchType = (SearchType)intValue; @@ -2063,6 +2075,7 @@ void FindReplaceDlg::initOptionsFromDlg() _options._isWrapAround = isCheckedOrNot(IDWRAP); _options._isInSelection = isCheckedOrNot(IDC_IN_SELECTION_CHECK); + _options._dotMatchesNewline = isCheckedOrNot(IDREDOTMATCHNL); _options._doPurge = isCheckedOrNot(IDC_PURGE_CHECK); _options._doMarkLine = isCheckedOrNot(IDC_MARKLINE_CHECK); diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h index cb1eb10ac..18be3e555 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h @@ -30,6 +30,8 @@ #include "DockingDlgInterface.h" #endif //DOCKINGDLGINTERFACE_H +#include "BoostRegexSearch.h" + #define FIND_RECURSIVE 1 #define FIND_INHIDDENDIR 2 @@ -78,10 +80,12 @@ struct FindOption generic_string _directory; bool _isRecursive; bool _isInHiddenDir; + bool _dotMatchesNewline; FindOption() : _isWholeWord(true), _isMatchCase(true), _searchType(FindNormal),\ _isWrapAround(true), _whichDirection(DIR_DOWN), _incrementalType(NotIncremental), _doPurge(false), _doMarkLine(false), - _isInSelection(false), _isRecursive(true), _isInHiddenDir(false), + _isInSelection(false), _isRecursive(true), _isInHiddenDir(false), + _dotMatchesNewline(false), _filters(TEXT("")), _directory(TEXT("")) {}; }; @@ -93,7 +97,8 @@ public: static int buildSearchFlags(const FindOption * option) { return (option->_isWholeWord ? SCFIND_WHOLEWORD : 0) | (option->_isMatchCase ? SCFIND_MATCHCASE : 0) | - (option->_searchType == FindRegex ? SCFIND_REGEXP|SCFIND_POSIX : 0); + (option->_searchType == FindRegex ? SCFIND_REGEXP|SCFIND_POSIX : 0) | + ((option->_searchType == FindRegex && option->_dotMatchesNewline) ? SCFIND_REGEXP_DOTMATCHESNL : 0); }; static void displaySectionCentered(int posStart, int posEnd, ScintillaEditView * pEditView, bool isDownwards = true); diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc index d14ace868..0471f25b1 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc @@ -51,11 +51,11 @@ BEGIN CONTROL "Match &whole word only",IDWHOLEWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,88,140,15 CONTROL "Match &case",IDMATCHCASE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,100,140,15 CONTROL "Wra&p around",IDWRAP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,112,110,15 - GROUPBOX "Search Mode",IDC_MODE_STATIC,6,131,156,48 + GROUPBOX "Search Mode",IDC_MODE_STATIC,6,131,159,48 CONTROL "&Normal",IDNORMAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,12,143,126,10 CONTROL "E&xtended (\\n, \\r, \\t, \\0, \\x...)",IDEXTENDED, "Button",BS_AUTORADIOBUTTON,12,155,145,10 - CONTROL "Re&gular expression",IDREGEXP,"Button",BS_AUTORADIOBUTTON,12,167,139,10 + CONTROL "Re&gular expression",IDREGEXP,"Button",BS_AUTORADIOBUTTON,12,167,78,10 CONTROL "&Up",IDDIRECTIONUP,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,177,143,64,12 CONTROL "&Down",IDDIRECTIONDOWN,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,177,155,63,12 GROUPBOX "Direction",IDC_DIR_STATIC,172,131,74,48,WS_GROUP @@ -74,6 +74,7 @@ BEGIN CONTROL "On losing focus",IDC_TRANSPARENT_LOSSFOCUS_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,268,143,86,10 CONTROL "Always",IDC_TRANSPARENT_ALWAYS_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,268,155,83,10 CONTROL "",IDC_PERCENTAGE_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | NOT WS_VISIBLE | WS_TABSTOP,271,166,53,10 + CONTROL "&. matches newline",IDREDOTMATCHNL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,167,67,9 END IDB_INCREMENTAL_BG BITMAP "..\\icons\\incrementalBg.bmp" diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h b/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h index 3c79b1580..605ab7473 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h @@ -107,6 +107,8 @@ #define IDC_FRCOMMAND_INIT 1700 #define IDC_FRCOMMAND_EXEC 1701 -#define IDC_FRCOMMAND_BOOLEANS 1702 +#define IDC_FRCOMMAND_BOOLEANS 1702 +#define IDREDOTMATCHNL 1703 +#define IDF_REDOTMATCHNL 1024 #endif //FINDREPLACE_DLG_H diff --git a/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.cpp b/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.cpp index 5bfa101dc..b3cfce8eb 100644 --- a/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.cpp +++ b/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.cpp @@ -19,14 +19,14 @@ #include "xmlMatchedTagsHighlighter.h" #include "ScintillaEditView.h" -int XmlMatchedTagsHighlighter::getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, pair & foundPos) +int XmlMatchedTagsHighlighter::getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, bool isRegex, pair & foundPos) { //int start = currentPos; //int end = (direction == DIR_LEFT)?0:_pEditView->getCurrentDocLen(); _pEditView->execute(SCI_SETTARGETSTART, targetStart); _pEditView->execute(SCI_SETTARGETEND, targetEnd); - _pEditView->execute(SCI_SETSEARCHFLAGS, SCFIND_REGEXP|SCFIND_POSIX); + _pEditView->execute(SCI_SETSEARCHFLAGS, isRegex ? (SCFIND_REGEXP|SCFIND_POSIX) : 0); int posFind = _pEditView->execute(SCI_SEARCHINTARGET, (WPARAM)strlen(token), (LPARAM)token); if (posFind != -1) { @@ -42,8 +42,8 @@ TagCateg XmlMatchedTagsHighlighter::getTagCategory(XmlMatchedTagsPos & tagsPos, int docLen = _pEditView->getCurrentDocLen(); - int gtPos = getFirstTokenPosFrom(curPos, 0, ">", foundPos); - int ltPos = getFirstTokenPosFrom(curPos, 0, "<", foundPos); + int gtPos = getFirstTokenPosFrom(curPos, 0, ">", false, foundPos); + int ltPos = getFirstTokenPosFrom(curPos, 0, "<", false, foundPos); if (ltPos != -1) { if ((gtPos != -1) && (ltPos < gtPos)) @@ -63,8 +63,8 @@ TagCateg XmlMatchedTagsHighlighter::getTagCategory(XmlMatchedTagsPos & tagsPos, // so now we are sure we have tag sign '<' // We'll see on the right - int gtPosOnR = getFirstTokenPosFrom(curPos, docLen, ">", foundPos); - int ltPosOnR = getFirstTokenPosFrom(curPos, docLen, "<", foundPos); + int gtPosOnR = getFirstTokenPosFrom(curPos, docLen, ">", false, foundPos); + int ltPosOnR = getFirstTokenPosFrom(curPos, docLen, "<", false, foundPos); if (gtPosOnR == -1) return invalidTag; @@ -112,7 +112,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd, bool direction = searchEnd > searchStart; pair foundPos; - int ltPosOnR = getFirstTokenPosFrom(searchStart, searchEnd, tag2find, foundPos); + int ltPosOnR = getFirstTokenPosFrom(searchStart, searchEnd, tag2find, true, foundPos); if (ltPosOnR == -1) return false; @@ -150,7 +150,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd, e = tagsPos.tagCloseStart; } - int ltTag = getFirstTokenPosFrom(s, e, oppositeTag2find, oppositeTagPos); + int ltTag = getFirstTokenPosFrom(s, e, oppositeTag2find, true, oppositeTagPos); if (ltTag == -1) { @@ -174,7 +174,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd, { for(;;) { - ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, oppositeTagPos); + ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, true, oppositeTagPos); if (ltTag == -1) { @@ -204,7 +204,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd, { for(;;) { - ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, oppositeTagPos); + ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, true, oppositeTagPos); if (ltTag == -1) { if (direction == search2Left) diff --git a/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.h b/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.h index b0b40b9fb..ee7dd23e5 100644 --- a/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.h +++ b/PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.h @@ -41,7 +41,7 @@ private: ScintillaEditView *_pEditView; - int getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, std::pair & foundPos); + int getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, bool isRegex, std::pair & foundPos); TagCateg getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos); bool getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector oppositeTagFound, XmlMatchedTagsPos & tagsPos); bool getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos); diff --git a/PowerEditor/visual.net/notepadPlus.vcproj b/PowerEditor/visual.net/notepadPlus.vcproj index 723db45e9..0a78b4958 100644 --- a/PowerEditor/visual.net/notepadPlus.vcproj +++ b/PowerEditor/visual.net/notepadPlus.vcproj @@ -228,7 +228,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="false" WholeProgramOptimization="false" - AdditionalIncludeDirectories="..\src\WinControls\AboutDlg;..\..\scintilla\include;..\include;..\src\WinControls;..\src\WinControls\ImageListSet;..\src\WinControls\OpenSaveFileDialog;..\src\WinControls\SplitterContainer;..\src\WinControls\StaticDialog;..\src\WinControls\TabBar;..\src\WinControls\ToolBar;..\src\MISC\Process;..\src\ScitillaComponent;..\src\MISC;..\src\MISC\SysMsg;..\src\WinControls\StatusBar;..\src;..\src\WinControls\StaticDialog\RunDlg;..\src\tinyxml;..\src\WinControls\ColourPicker;..\src\Win32Explr;..\src\MISC\RegExt;..\src\WinControls\TrayIcon;..\src\WinControls\shortcut;..\src\WinControls\Grid;..\src\WinControls\ContextMenu;..\src\MISC\PluginsManager;..\src\WinControls\Preference;..\src\WinControls\WindowsDlg;..\src\WinControls\TaskList;..\src\WinControls\DockingWnd;..\src\WinControls\ToolTip;..\src\MISC\Exception;..\src\MISC\Common;..\src\tinyxml\tinyXmlA;..\src\WinControls\AnsiCharPanel;..\src\WinControls\ClipboardHistory;..\src\WinControls\FindCharsInRange;..\src\WinControls\VerticalFileSwitcher;..\src\WinControls\ProjectPanel" + AdditionalIncludeDirectories="..\src\WinControls\AboutDlg;..\..\scintilla\include;..\include;..\src\WinControls;..\src\WinControls\ImageListSet;..\src\WinControls\OpenSaveFileDialog;..\src\WinControls\SplitterContainer;..\src\WinControls\StaticDialog;..\src\WinControls\TabBar;..\src\WinControls\ToolBar;..\src\MISC\Process;..\src\ScitillaComponent;..\src\MISC;..\src\MISC\SysMsg;..\src\WinControls\StatusBar;..\src;..\src\WinControls\StaticDialog\RunDlg;..\src\tinyxml;..\src\WinControls\ColourPicker;..\src\Win32Explr;..\src\MISC\RegExt;..\src\WinControls\TrayIcon;..\src\WinControls\shortcut;..\src\WinControls\Grid;..\src\WinControls\ContextMenu;..\src\MISC\PluginsManager;..\src\WinControls\Preference;..\src\WinControls\WindowsDlg;..\src\WinControls\TaskList;..\src\WinControls\DockingWnd;..\src\WinControls\ToolTip;..\src\MISC\Exception;..\src\MISC\Common;..\src\tinyxml\tinyXmlA;..\src\WinControls\AnsiCharPanel;..\src\WinControls\ClipboardHistory;..\src\WinControls\FindCharsInRange;..\src\WinControls\VerticalFileSwitcher;..\src\WinControls\ProjectPanel;..\src\WinControls\DocumentMap" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USE_64BIT_TIME_T;TIXML_USE_STL;TIXMLA_USE_STL;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NON_CONFORMING_SWPRINTFS=1" GeneratePreprocessedFile="0" StringPooling="true" diff --git a/scintilla/boostregex/AnsiDocumentIterator.h b/scintilla/boostregex/AnsiDocumentIterator.h new file mode 100644 index 000000000..4e4698003 --- /dev/null +++ b/scintilla/boostregex/AnsiDocumentIterator.h @@ -0,0 +1,94 @@ +#ifndef ANSIDOCUMENTITERATOR_H_12481491281240 +#define ANSIDOCUMENTITERATOR_H_12481491281240 + +class AnsiDocumentIterator : public std::iterator +{ +public: + AnsiDocumentIterator() : + m_doc(0), + m_pos(0), + m_end(0) + { + } + + AnsiDocumentIterator(Document* doc, int pos, int end) : + m_doc(doc), + m_pos(pos), + m_end(end) + { + // Check for debug builds + PLATFORM_ASSERT(m_pos <= m_end); + + // Ensure for release. + if (m_pos > m_end) + { + m_pos = m_end; + } + } + + AnsiDocumentIterator(const AnsiDocumentIterator& copy) : + m_doc(copy.m_doc), + m_pos(copy.m_pos), + m_end(copy.m_end) + { + // Check for debug builds + PLATFORM_ASSERT(m_pos <= m_end); + + // Ensure for release. + if (m_pos > m_end) + { + m_pos = m_end; + } + } + + bool operator == (const AnsiDocumentIterator& other) const + { + return (ended() == other.ended()) && (m_doc == other.m_doc) && (m_pos == other.m_pos); + } + + bool operator != (const AnsiDocumentIterator& other) const + { + return !(*this == other); + } + + char operator * () const + { + return charAt(m_pos); + } + + AnsiDocumentIterator& operator ++ () + { + PLATFORM_ASSERT(m_pos < m_end); + + m_pos++; + return *this; + } + + AnsiDocumentIterator& operator -- () + { + m_pos--; + return *this; + } + + int pos() const + { + return m_pos; + } + +private: + char charAt(int position) const + { + return m_doc->CharAt(position); + } + + bool ended() const + { + return m_pos == m_end; + } + + int m_pos; + int m_end; + Document* m_doc; +}; + +#endif \ No newline at end of file diff --git a/scintilla/boostregex/BoostRegExSearch.cxx b/scintilla/boostregex/BoostRegExSearch.cxx new file mode 100644 index 000000000..2157bbc27 --- /dev/null +++ b/scintilla/boostregex/BoostRegExSearch.cxx @@ -0,0 +1,323 @@ +/** + * Copyright (c) since 2009 Simon Steele - http://untidy.net/ + * Based on the work of Simon Steele for Programmer's Notepad 2 (http://untidy.net) + * Converted from boost::xpressive to boost::regex and performance improvements + * (principally caching the compiled regex), and support for UTF8 encoded text + * (c) 2012 Dave Brotherstone - Changes for boost::regex + * + * + */ +#include +#include +#include "scintilla.h" +#include "Platform.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "CellBuffer.h" +#include "CharClassify.h" +#include "Decoration.h" +#include "ILexer.h" +#include "Document.h" +#include "UniConversion.h" +#include "UTF8DocumentIterator.h" +#include "AnsiDocumentIterator.h" +#include "BoostRegexSearch.h" +#include +#define CP_UTF8 65001 +#define SC_CP_UTF8 65001 + + + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +using namespace boost; + + +typedef basic_regex charregex_t; +typedef boost::wregex wcharregex_t; +// , std::vector >::allocator_type +typedef match_results utf8match_t; +typedef match_results ansimatch_t; + +class BoostRegexSearch : public RegexSearchBase +{ +public: + BoostRegexSearch() : substituted(NULL), lastCompileFlags(-1) {} + + virtual ~BoostRegexSearch() + { + if (substituted) + { + delete [] substituted; + substituted = NULL; + } + } + + + virtual long FindText(Document* doc, int minPos, int maxPos, const char *s, + bool caseSensitive, bool word, bool wordStart, int flags, int *length); + + + + virtual const char *SubstituteByPosition(Document* doc, const char *text, int *length); + +private: + wchar_t *utf8ToWchar(const char *utf8); + char *wcharToUtf8(const wchar_t *w); + + charregex_t m_charre; + wcharregex_t m_wcharre; + + utf8match_t m_utf8match; + ansimatch_t m_ansimatch; + + char *substituted; + std::string m_lastRegexString; + std::string m_lastRegexUtf8string; + int lastCompileFlags; +}; + +#ifdef SCI_NAMESPACE +namespace Scintilla +{ +#endif + +RegexSearchBase *CreateRegexSearch(CharClassify* /* charClassTable */) +{ + return new BoostRegexSearch(); +} + +#ifdef SCI_NAMESPACE +} +#endif + +/** + * Find text in document, supporting both forward and backward + * searches (just pass minPos > maxPos to do a backward search) + */ + + +long BoostRegexSearch::FindText(Document* doc, int minPos, int maxPos, const char *s, + bool caseSensitive, bool /*word*/, bool /*wordStart*/, int searchFlags, int *length) +{ + int startPos, endPos, increment; + + if (minPos > maxPos) + { + startPos = maxPos; + endPos = minPos; + increment = -1; + } + else + { + startPos = minPos; + endPos = maxPos; + increment = 1; + } + + // Range endpoints should not be inside DBCS characters, but just in case, move them. + startPos = doc->MovePositionOutsideChar(startPos, 1, false); + endPos = doc->MovePositionOutsideChar(endPos, 1, false); + + + int compileFlags(regex_constants::ECMAScript); + if (!caseSensitive) + { + compileFlags |= regex_constants::icase; + } + bool isUtf8 = (doc->CodePage() == SC_CP_UTF8); + + try + { + + if (compileFlags != lastCompileFlags + || (isUtf8 && m_lastRegexUtf8string != s) + || (!isUtf8 && m_lastRegexString != s)) // Test to see if we're called with the same + // regex as last time, if we are, then we don't need to recompile it + { + if (isUtf8) + { + const wchar_t* wchars = utf8ToWchar(s); + m_wcharre = wcharregex_t(wchars, static_cast(compileFlags)); + delete [] wchars; + m_lastRegexUtf8string = s; + } + else + { // Ansi + m_charre = charregex_t(s, static_cast(compileFlags)); + m_lastRegexString = s; + } + lastCompileFlags = compileFlags; + } + } + + catch(regex_error& /*ex*/) + { + // -1 is normally used for not found, -2 is used here for invalid regex + return -2; + } + + // Work out the range of lines we're searching across, moving beyond an empty end-of-line + int lineRangeStart = doc->LineFromPosition(startPos); + int lineRangeEnd = doc->LineFromPosition(endPos); + if ((increment == 1) && + (startPos >= doc->LineEnd(lineRangeStart)) && + (lineRangeStart < lineRangeEnd)) + { + // the start position is at end of line or between line end characters. + lineRangeStart++; + startPos = doc->LineStart(lineRangeStart); + } + + regex_constants::match_flag_type flags(regex_constants::match_default); + + + + // Work out the flags: + if (startPos != doc->LineStart(lineRangeStart)) + { + flags |= regex_constants::match_not_bol; + } + + if (endPos != doc->LineEnd(lineRangeEnd)) + { + flags |= regex_constants::match_not_eol; + } + + if (0 == (searchFlags & SCFIND_REGEXP_DOTMATCHESNL)) + { + flags |= regex_constants::match_not_dot_newline; + } + + int pos(-1); + int lenRet(0); + + + if (doc->CodePage() == SC_CP_UTF8) + { + UTF8DocumentIterator end(doc, endPos, endPos); + bool success = boost::regex_search(UTF8DocumentIterator(doc, startPos, endPos), end, m_utf8match, m_wcharre, flags); + if (success) + { + pos = m_utf8match[0].first.pos(); + lenRet = m_utf8match[0].second.pos() - pos; + + if (increment == -1) + { + // Check for the last match on this line. + int repetitions = 100; // Break out of infinite loop + int previousPos = pos; + while (success && ((pos + lenRet) <= endPos)) + { + if (previousPos >= pos && 0 >= (--repetitions)) + break; + previousPos = pos; + success = regex_search(UTF8DocumentIterator(doc, pos + 1, endPos), end, m_utf8match, m_wcharre, flags); + // success = regex_search(DocumentIterator(doc, pos + 1, endPos), end, match, re, static_cast(flags)); + if (success) + { + if ((pos + lenRet) <= minPos) + { + pos = m_utf8match[0].first.pos(); + lenRet = m_utf8match[0].second.pos() - pos; + } + else + { + success = 0; + } + } + } + } + + *length = lenRet; + } + } + else + { + AnsiDocumentIterator end(doc, endPos, endPos); + + bool success = boost::regex_search(AnsiDocumentIterator(doc, startPos, endPos), end, m_ansimatch, m_charre, flags); + if (success) + { + pos = m_ansimatch[0].first.pos(); + lenRet = m_ansimatch.length(); + + if (increment == -1) + { + // Check for the last match on this line. + int repetitions = 100; // Break out of infinite loop + int previousPos = pos; + while (success && ((pos + lenRet) <= endPos)) + { + if (previousPos >= pos && 0 >= (--repetitions)) + break; + previousPos = pos; + success = regex_search(AnsiDocumentIterator(doc, pos + 1, endPos), end, m_ansimatch, m_charre, flags); + // success = regex_search(DocumentIterator(doc, pos + 1, endPos), end, match, re, static_cast(flags)); + if (success) + { + if ((pos + lenRet) <= minPos) + { + pos = m_ansimatch[0].first.pos(); + lenRet = m_ansimatch[0].length(); + } + else + { + success = 0; + } + } + } + } + + *length = lenRet; + } + } + + return pos; +} + + +const char *BoostRegexSearch::SubstituteByPosition(Document* doc, const char *text, int *length) { + delete []substituted; + substituted = NULL; + if (doc->CodePage() == SC_CP_UTF8) + { + const wchar_t* wtext = utf8ToWchar(text); + std::wstring replaced = m_utf8match.format(wtext, boost::format_all); + delete[] wtext; + substituted = wcharToUtf8(replaced.c_str()); + *length = strlen(substituted); + } + else + { + std::string replaced = m_ansimatch.format(text, boost::format_all); + *length = replaced.size(); + substituted = new char[*length + 1]; + strcpy(substituted, replaced.c_str()); + } + return substituted; +} + +wchar_t *BoostRegexSearch::utf8ToWchar(const char *utf8) +{ + int utf8Size = strlen(utf8); + int wcharSize = UTF16Length(utf8, utf8Size); + wchar_t *w = new wchar_t[wcharSize + 1]; + UTF16FromUTF8(utf8, utf8Size, w, wcharSize + 1); + w[wcharSize] = 0; + + return w; +} + +char* BoostRegexSearch::wcharToUtf8(const wchar_t *w) +{ + int wcharSize = wcslen(w); + int charSize = UTF8Length(w, wcharSize); + char *c = new char[charSize + 1]; + UTF8FromUTF16(w, wcharSize, c, charSize); + c[charSize] = 0; + return c; +} \ No newline at end of file diff --git a/scintilla/boostregex/BuildBoost.bat b/scintilla/boostregex/BuildBoost.bat new file mode 100644 index 000000000..ac53449f3 --- /dev/null +++ b/scintilla/boostregex/BuildBoost.bat @@ -0,0 +1,88 @@ +@ECHO OFF +:: Perform the pre-steps to build boost and set the boost path for the build file + +:: TODO - Shift stuff to get the boost path / check/display usage + +SET BOOSTPATH=%1 + +IF NOT EXIST "%BOOSTPATH%\boost\regex.hpp" ( + GOTO BOOSTNOTFOUND +) + +IF NOT EXIST "%BOOSTPATH%\bjam\bin\bjam.exe" ( + ECHO Building BJAM, the boost build tool + PUSHD %BOOSTPATH%\tools\build\v2 + CALL bootstrap.bat + + %BOOSTPATH%\tools\build\v2\b2 --prefix=%BOOSTPATH%\bjam install +) + +IF NOT ERRORLEVEL 0 ( + GOTO BUILDERROR +) + +ECHO. +ECHO Building Boost::regex + +CD %BOOSTPATH%\libs\regex\build + +%BOOSTPATH%\bjam\bin\bjam variant=release threading=multi link=static runtime-link=static +IF NOT ERRORLEVEL 0 ( + GOTO BUILDERROR +) + +%BOOSTPATH%\bjam\bin\bjam variant=debug threading=multi link=static runtime-link=static +IF NOT ERRORLEVEL 0 ( + GOTO BUILDERROR +) + +IF EXIST "%BOOSTPATH%\bin.v2\libs\regex\build\msvc-8.0" ( + SET BOOSTVSVERPATH=%BOOSTPATH%\bin.v2\libs\regex\build\msvc-8.0 +) ELSE IF EXIST "%BOOSTPATH%\bin.v2\libs\regex\build\msvc-9.0" ( + SET BOOSTVSVERPATH=%BOOSTPATH%\bin.v2\libs\regex\build\msvc-9.0 +) ELSE IF EXIST "%BOOSTPATH%\bin.v2\libs\regex\build\msvc-10.0" ( + SET BOOSTVSVERPATH=%BOOSTPATH%\bin.v2\libs\regex\build\msvc-10.0 +) + +ECHO # Autogenerated file, run BuildBoost.bat [path_to_boost] to generate > %~dp0%\boostpath.mak +ECHO BOOSTPATH=%BOOSTPATH% >> %~dp0%\boostpath.mak +ECHO BOOSTVSVERPATH=%BOOSTVSVERPATH% >> %~dp0%\boostpath.mak + +POPD + +ECHO Boost::regex built. +ECHO. +ECHO Now you need to build scintilla. +ECHO First, edit the scintilla\win32\scintilla.mak, and make sure there's a line in there that says +ECHO. +ECHO !INCLUDE ../boostregex/nppSpecifics.mak +ECHO. +ECHO just after all the LOBJS have been defined (it's around line 211) +ECHO If not, add it in. +ECHO Then, from the scintilla\win32 directory +ECHO. +ECHO nmake -f scintilla.mak +ECHO. +ECHO. + +GOTO EOF + +:BOOSTNOTFOUND +ECHO Boost Path not valid. Run BuildBoost.bat with the directory where you unpacked your boost zip +ECHO Boost is available free from www.boost.org +ECHO. +ECHO e.g. +ECHO buildboost.bat d:\libs\boost_1_48_0 + +GOTO EOF + + +:BUILDERROR +ECHO There was an error building boost. Please see the messages above for details. +ECHO - Have you got a clean extract from a recent boost version, such as 1.48? +ECHO - Download a fresh copy from www.boost.org and extract it to a directory, +ECHO and run the batch again with the name of that directory + +:EOF + + diff --git a/scintilla/boostregex/UTF8DocumentIterator.cxx b/scintilla/boostregex/UTF8DocumentIterator.cxx new file mode 100644 index 000000000..e075c4f39 --- /dev/null +++ b/scintilla/boostregex/UTF8DocumentIterator.cxx @@ -0,0 +1,57 @@ +#include "UTF8DocumentIterator.h" + + +void UTF8DocumentIterator::readCharacter() +{ + unsigned char currentChar = m_doc->CharAt(m_pos); + if (currentChar & 0x80) + { + int mask = 0x40; + int nBytes = 1; + + do + { + mask >>= 1; + ++nBytes; + } while (currentChar & mask); + + int result = currentChar & m_firstByteMask[nBytes]; + int pos = m_pos; + m_utf8Length = 1; + // work out the unicode point, and count the actual bytes. + // If a byte does not start with 10xxxxxx then it's not part of the + // the code. Therefore invalid UTF-8 encodings are dealt with, simply by stopping when + // the UTF8 extension bytes are no longer valid. + while ((--nBytes) && (pos < m_end) && (0x80 == ((currentChar = m_doc->CharAt(++pos)) & 0xC0))) + { + result = (result << 6) | (currentChar & 0x3F); + ++m_utf8Length; + } + + if (result >= 0x10000) + { + result -= 0x10000; + m_utf16Length = 2; + // UTF-16 Pair + m_character[0] = 0xD800 + (result >> 10); + m_character[1] = 0xDC00 + (result & 0x3FF); + + } + else + { + m_utf16Length = 1; + m_character[0] = static_cast(result); + } + } + else + { + m_utf8Length = 1; + m_utf16Length = 1; + m_characterIndex = 0; + m_character[0] = static_cast(currentChar); + } +} + + +const unsigned char UTF8DocumentIterator::m_firstByteMask[7] = { 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 }; + \ No newline at end of file diff --git a/scintilla/boostregex/UTF8DocumentIterator.h b/scintilla/boostregex/UTF8DocumentIterator.h new file mode 100644 index 000000000..534eb7d65 --- /dev/null +++ b/scintilla/boostregex/UTF8DocumentIterator.h @@ -0,0 +1,149 @@ +#ifndef UTF8DOCUMENTITERATOR_H_3452843291318441149 +#define UTF8DOCUMENTITERATOR_H_3452843291318441149 + +#include +#include +#include "Platform.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" +#include "CellBuffer.h" +#include "CharClassify.h" +#include "Decoration.h" +#include +#include + +class UTF8DocumentIterator : public std::iterator +{ +public: + UTF8DocumentIterator() : + m_doc(0), + m_pos(0), + m_end(0), + m_characterIndex(0), + m_utf8Length(0), + m_utf16Length(0) + { + } + + UTF8DocumentIterator(Document* doc, int pos, int end) : + m_doc(doc), + m_pos(pos), + m_end(end), + m_characterIndex(0) + { + // Check for debug builds + PLATFORM_ASSERT(m_pos <= m_end); + + // Ensure for release. + if (m_pos > m_end) + { + m_pos = m_end; + } + readCharacter(); + } + + UTF8DocumentIterator(const UTF8DocumentIterator& copy) : + m_doc(copy.m_doc), + m_pos(copy.m_pos), + m_end(copy.m_end), + m_characterIndex(copy.m_characterIndex), + m_utf8Length(copy.m_utf8Length), + m_utf16Length(copy.m_utf16Length) + { + // Check for debug builds + PLATFORM_ASSERT(m_pos <= m_end); + m_character[0] = copy.m_character[0]; + m_character[1] = copy.m_character[1]; + + // Ensure for release. + if (m_pos > m_end) + { + m_pos = m_end; + } + } + + bool operator == (const UTF8DocumentIterator& other) const + { + return (ended() == other.ended()) && (m_doc == other.m_doc) && (m_pos == other.m_pos); + } + + bool operator != (const UTF8DocumentIterator& other) const + { + return !(*this == other); + } + + wchar_t operator * () const + { + return m_character[m_characterIndex]; + } + + UTF8DocumentIterator& operator = (int other) + { + m_pos = other; + return *this; + } + + UTF8DocumentIterator& operator ++ () + { + PLATFORM_ASSERT(m_pos < m_end); + if (2 == m_utf16Length && 0 == m_characterIndex) + { + m_characterIndex = 1; + } + else + { + m_pos += m_utf8Length; + m_characterIndex = 0; + readCharacter(); + } + return *this; + } + + UTF8DocumentIterator& operator -- () + { + if (m_utf16Length == 2 && m_characterIndex == 1) + { + m_characterIndex = 0; + } + else + { + --m_pos; + // Skip past the UTF-8 extension bytes + while (0x80 == (m_doc->CharAt(m_pos) & 0xC0)) + --m_pos; + + readCharacter(); + if (m_utf16Length == 2) + { + m_characterIndex = 1; + } + } + return *this; + } + + int pos() const + { + return m_pos; + } + +private: + void readCharacter(); + + + bool ended() const + { + return m_pos == m_end; + } + + int m_pos; + wchar_t m_character[2]; + int m_characterIndex; + int m_end; + int m_utf8Length; + int m_utf16Length; + Document* m_doc; + static const unsigned char m_firstByteMask[]; +}; + +#endif // UTF8DOCUMENTITERATOR_H_3452843291318441149 diff --git a/scintilla/boostregex/nppSpecifics.mak b/scintilla/boostregex/nppSpecifics.mak new file mode 100644 index 000000000..422f3724c --- /dev/null +++ b/scintilla/boostregex/nppSpecifics.mak @@ -0,0 +1,44 @@ +# This makefile should be included in the main scintilla.mak file, +# just after where LOBJS is defined (around line +# +# The following line should be added around line 211 of scintilla.mak +# !INCLUDE nppSpecifics.mak + +# Set your boost path (the root of where you've unpacked your boost zip). +# Boost is available from www.boost.org + +!IF EXIST(..\boostregex\boostpath.mak) + +!INCLUDE ..\boostregex\boostpath.mak + +SOBJS=\ + $(SOBJS)\ + $(DIR_O)\BoostRegexSearch.obj\ + $(DIR_O)\UTF8DocumentIterator.obj + +LOBJS=\ + $(LOBJS)\ + $(DIR_O)\BoostRegexSearch.obj\ + $(DIR_O)\UTF8DocumentIterator.obj + + +INCLUDEDIRS=$(INCLUDEDIRS) -I$(BOOSTPATH) + +CXXFLAGS=$(CXXFLAGS) -DSCI_OWNREGEX +!IFDEF DEBUG +LDFLAGS=$(LDFLAGS) -LIBPATH:$(BOOSTVSVERPATH)\debug\link-static\runtime-link-static\threading-multi +!ELSE +LDFLAGS=$(LDFLAGS) -LIBPATH:$(BOOSTVSVERPATH)\release\link-static\runtime-link-static\threading-multi +!ENDIF + + + +$(DIR_O)\UTF8DocumentIterator.obj:: ../boostregex/UTF8DocumentIterator.cxx + $(CC) $(CXXFLAGS) -c ../boostregex/UTF8DocumentIterator.cxx + +$(DIR_O)\BoostRegexSearch.obj:: ../boostregex/BoostRegexSearch.cxx ../src/CharClassify.h ../src/RESearch.h + $(CC) $(CXXFLAGS) -c ../boostregex/BoostRegexSearch.cxx + +!ENDIF + + diff --git a/scintilla/win32/scintilla.mak b/scintilla/win32/scintilla.mak index 156812b9a..54eac2c6c 100644 --- a/scintilla/win32/scintilla.mak +++ b/scintilla/win32/scintilla.mak @@ -205,6 +205,8 @@ LOBJS=\ $(DIR_O)\WordList.obj \ $(DIR_O)\XPM.obj \ $(LEXOBJS) + +!INCLUDE ../boostregex/nppSpecifics.mak $(DIR_O)\ScintRes.res : ScintRes.rc $(RC) -fo$@ $**