[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
This commit is contained in:
parent
73ffaa8554
commit
7e0ed0ebf3
|
@ -1864,6 +1864,10 @@ void NppParameters::feedFindHistoryParameters(TiXmlNode *node)
|
||||||
(findHistoryRoot->ToElement())->Attribute(TEXT("transparency"), &_findHistory._transparency);
|
(findHistoryRoot->ToElement())->Attribute(TEXT("transparency"), &_findHistory._transparency);
|
||||||
if (_findHistory._transparency <= 0 || _findHistory._transparency > 200)
|
if (_findHistory._transparency <= 0 || _findHistory._transparency > 200)
|
||||||
_findHistory._transparency = 150;
|
_findHistory._transparency = 150;
|
||||||
|
|
||||||
|
boolStr = (findHistoryRoot->ToElement())->Attribute(TEXT("dotMatchesNewline"));
|
||||||
|
if (boolStr)
|
||||||
|
_findHistory._dotMatchesNewline = !lstrcmp(TEXT("yes"), boolStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NppParameters::feedShortcut(TiXmlNode *node)
|
void NppParameters::feedShortcut(TiXmlNode *node)
|
||||||
|
@ -4633,6 +4637,7 @@ bool NppParameters::writeFindHistory()
|
||||||
(findHistoryRoot->ToElement())->SetAttribute(TEXT("searchMode"), _findHistory._searchMode);
|
(findHistoryRoot->ToElement())->SetAttribute(TEXT("searchMode"), _findHistory._searchMode);
|
||||||
(findHistoryRoot->ToElement())->SetAttribute(TEXT("transparencyMode"), _findHistory._transparencyMode);
|
(findHistoryRoot->ToElement())->SetAttribute(TEXT("transparencyMode"), _findHistory._transparencyMode);
|
||||||
(findHistoryRoot->ToElement())->SetAttribute(TEXT("transparency"), _findHistory._transparency);
|
(findHistoryRoot->ToElement())->SetAttribute(TEXT("transparency"), _findHistory._transparency);
|
||||||
|
(findHistoryRoot->ToElement())->SetAttribute(TEXT("dotMatchesNewline"), _findHistory._dotMatchesNewline?TEXT("yes"):TEXT("no"));
|
||||||
|
|
||||||
TiXmlElement hist_element(TEXT(""));
|
TiXmlElement hist_element(TEXT(""));
|
||||||
|
|
||||||
|
|
|
@ -961,7 +961,8 @@ struct FindHistory {
|
||||||
_isMatchWord(false), _isMatchCase(false),_isWrap(true),_isDirectionDown(true),\
|
_isMatchWord(false), _isMatchCase(false),_isWrap(true),_isDirectionDown(true),\
|
||||||
_isFifRecuisive(true), _isFifInHiddenFolder(false), _isDlgAlwaysVisible(false),\
|
_isFifRecuisive(true), _isFifInHiddenFolder(false), _isDlgAlwaysVisible(false),\
|
||||||
_isFilterFollowDoc(false), _isFolderFollowDoc(false),\
|
_isFilterFollowDoc(false), _isFolderFollowDoc(false),\
|
||||||
_searchMode(normal), _transparencyMode(onLossingFocus), _transparency(150)
|
_searchMode(normal), _transparencyMode(onLossingFocus), _transparency(150),
|
||||||
|
_dotMatchesNewline(false)
|
||||||
|
|
||||||
{};
|
{};
|
||||||
int _nbMaxFindHistoryPath;
|
int _nbMaxFindHistoryPath;
|
||||||
|
@ -978,6 +979,7 @@ struct FindHistory {
|
||||||
bool _isMatchCase;
|
bool _isMatchCase;
|
||||||
bool _isWrap;
|
bool _isWrap;
|
||||||
bool _isDirectionDown;
|
bool _isDirectionDown;
|
||||||
|
bool _dotMatchesNewline;
|
||||||
|
|
||||||
bool _isFifRecuisive;
|
bool _isFifRecuisive;
|
||||||
bool _isFifInHiddenFolder;
|
bool _isFifInHiddenFolder;
|
||||||
|
|
|
@ -343,16 +343,12 @@ void FindReplaceDlg::fillFindHistory()
|
||||||
::SendDlgItemMessage(_hSelf, IDNORMAL, BM_SETCHECK, findHistory._searchMode == FindHistory::normal, 0);
|
::SendDlgItemMessage(_hSelf, IDNORMAL, BM_SETCHECK, findHistory._searchMode == FindHistory::normal, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDEXTENDED, BM_SETCHECK, findHistory._searchMode == FindHistory::extended, 0);
|
::SendDlgItemMessage(_hSelf, IDEXTENDED, BM_SETCHECK, findHistory._searchMode == FindHistory::extended, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDREGEXP, BM_SETCHECK, findHistory._searchMode == FindHistory::regExpr, 0);
|
::SendDlgItemMessage(_hSelf, IDREGEXP, BM_SETCHECK, findHistory._searchMode == FindHistory::regExpr, 0);
|
||||||
|
::SendDlgItemMessage(_hSelf, IDREDOTMATCHNL, BM_SETCHECK, findHistory._dotMatchesNewline, 0);
|
||||||
if (findHistory._searchMode == FindHistory::regExpr)
|
if (findHistory._searchMode == FindHistory::regExpr)
|
||||||
{
|
{
|
||||||
//regex doesnt allow wholeword
|
//regex doesnt allow wholeword
|
||||||
::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, BST_UNCHECKED, 0);
|
::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, BST_UNCHECKED, 0);
|
||||||
::EnableWindow(::GetDlgItem(_hSelf, IDWHOLEWORD), (BOOL)false);
|
::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())
|
if (nppParams->isTransparentAvailable())
|
||||||
|
@ -993,6 +989,10 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
//Option actions
|
//Option actions
|
||||||
|
case IDREDOTMATCHNL:
|
||||||
|
findHistory._dotMatchesNewline = _options._dotMatchesNewline = isCheckedOrNot(IDREDOTMATCHNL);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
case IDWHOLEWORD :
|
case IDWHOLEWORD :
|
||||||
findHistory._isMatchWord = _options._isWholeWord = isCheckedOrNot(IDWHOLEWORD);
|
findHistory._isMatchWord = _options._isWholeWord = isCheckedOrNot(IDWHOLEWORD);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1008,16 +1008,19 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP
|
||||||
{
|
{
|
||||||
_options._searchType = FindRegex;
|
_options._searchType = FindRegex;
|
||||||
findHistory._searchMode = FindHistory::regExpr;
|
findHistory._searchMode = FindHistory::regExpr;
|
||||||
|
::EnableWindow(GetDlgItem(_hSelf, IDREDOTMATCHNL), true);
|
||||||
}
|
}
|
||||||
else if (isCheckedOrNot(IDEXTENDED))
|
else if (isCheckedOrNot(IDEXTENDED))
|
||||||
{
|
{
|
||||||
_options._searchType = FindExtended;
|
_options._searchType = FindExtended;
|
||||||
findHistory._searchMode = FindHistory::extended;
|
findHistory._searchMode = FindHistory::extended;
|
||||||
|
::EnableWindow(GetDlgItem(_hSelf, IDREDOTMATCHNL), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_options._searchType = FindNormal;
|
_options._searchType = FindNormal;
|
||||||
findHistory._searchMode = FindHistory::normal;
|
findHistory._searchMode = FindHistory::normal;
|
||||||
|
::EnableWindow(GetDlgItem(_hSelf, IDREDOTMATCHNL), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRegex = (_options._searchType == FindRegex);
|
bool isRegex = (_options._searchType == FindRegex);
|
||||||
|
@ -1027,14 +1030,10 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP
|
||||||
_options._isWholeWord = false;
|
_options._isWholeWord = false;
|
||||||
::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, _options._isWholeWord?BST_CHECKED:BST_UNCHECKED, 0);
|
::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, IDWHOLEWORD), (BOOL)!isRegex);
|
||||||
::EnableWindow(::GetDlgItem(_hSelf, IDDIRECTIONUP), (BOOL)!isRegex);
|
|
||||||
return TRUE; }
|
return TRUE; }
|
||||||
|
|
||||||
case IDWRAP :
|
case IDWRAP :
|
||||||
|
@ -1266,7 +1265,11 @@ bool FindReplaceDlg::processFindNext(const TCHAR *txt2find, const FindOption *op
|
||||||
return false;
|
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 start = posFind;
|
||||||
int end = int((*_ppEditView)->execute(SCI_GETTARGETEND));
|
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);
|
(*_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 [] pTextFind;
|
||||||
delete [] pTextReplace;
|
delete [] pTextReplace;
|
||||||
|
@ -1509,11 +1517,12 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con
|
||||||
(*_ppEditView)->execute(SCI_SETSEARCHFLAGS, flags);
|
(*_ppEditView)->execute(SCI_SETSEARCHFLAGS, flags);
|
||||||
targetStart = (*_ppEditView)->searchInTarget(pTextFind, stringSizeFind, startRange, endRange);
|
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);
|
_pFinder->addFileNameTitle(fileName);
|
||||||
}
|
}
|
||||||
while (targetStart != -1)
|
|
||||||
|
while (targetStart != -1 && targetStart != -2)
|
||||||
{
|
{
|
||||||
//int posFindBefore = posFind;
|
//int posFindBefore = posFind;
|
||||||
targetStart = int((*_ppEditView)->execute(SCI_GETTARGETSTART));
|
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<LPARAM>(_options._str2Search.c_str()));
|
::SendMessage(_hParent, WM_FRSAVE_STR, IDFINDWHAT, reinterpret_cast<LPARAM>(_options._str2Search.c_str()));
|
||||||
booleans |= _options._isWholeWord?IDF_WHOLEWORD:0;
|
booleans |= _options._isWholeWord?IDF_WHOLEWORD:0;
|
||||||
booleans |= _options._isMatchCase?IDF_MATCHCASE:0;
|
booleans |= _options._isMatchCase?IDF_MATCHCASE:0;
|
||||||
|
booleans |= _options._dotMatchesNewline?IDF_REDOTMATCHNL:0;
|
||||||
|
|
||||||
::SendMessage(_hParent, WM_FRSAVE_INT, IDNORMAL, _options._searchType);
|
::SendMessage(_hParent, WM_FRSAVE_INT, IDNORMAL, _options._searchType);
|
||||||
if (cmd == IDCMARKALL)
|
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->_isInSelection = ((intValue & IDF_IN_SELECTION_CHECK)> 0);
|
||||||
_env->_isWrapAround = ((intValue & IDF_WRAP)> 0);
|
_env->_isWrapAround = ((intValue & IDF_WRAP)> 0);
|
||||||
_env->_whichDirection = ((intValue & IDF_WHICH_DIRECTION)> 0);
|
_env->_whichDirection = ((intValue & IDF_WHICH_DIRECTION)> 0);
|
||||||
|
_env->_dotMatchesNewline = ((intValue & IDF_REDOTMATCHNL)> 0);
|
||||||
break;
|
break;
|
||||||
case IDNORMAL:
|
case IDNORMAL:
|
||||||
_env->_searchType = (SearchType)intValue;
|
_env->_searchType = (SearchType)intValue;
|
||||||
|
@ -2063,6 +2075,7 @@ void FindReplaceDlg::initOptionsFromDlg()
|
||||||
_options._isWrapAround = isCheckedOrNot(IDWRAP);
|
_options._isWrapAround = isCheckedOrNot(IDWRAP);
|
||||||
_options._isInSelection = isCheckedOrNot(IDC_IN_SELECTION_CHECK);
|
_options._isInSelection = isCheckedOrNot(IDC_IN_SELECTION_CHECK);
|
||||||
|
|
||||||
|
_options._dotMatchesNewline = isCheckedOrNot(IDREDOTMATCHNL);
|
||||||
_options._doPurge = isCheckedOrNot(IDC_PURGE_CHECK);
|
_options._doPurge = isCheckedOrNot(IDC_PURGE_CHECK);
|
||||||
_options._doMarkLine = isCheckedOrNot(IDC_MARKLINE_CHECK);
|
_options._doMarkLine = isCheckedOrNot(IDC_MARKLINE_CHECK);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "DockingDlgInterface.h"
|
#include "DockingDlgInterface.h"
|
||||||
#endif //DOCKINGDLGINTERFACE_H
|
#endif //DOCKINGDLGINTERFACE_H
|
||||||
|
|
||||||
|
#include "BoostRegexSearch.h"
|
||||||
|
|
||||||
#define FIND_RECURSIVE 1
|
#define FIND_RECURSIVE 1
|
||||||
#define FIND_INHIDDENDIR 2
|
#define FIND_INHIDDENDIR 2
|
||||||
|
|
||||||
|
@ -78,10 +80,12 @@ struct FindOption
|
||||||
generic_string _directory;
|
generic_string _directory;
|
||||||
bool _isRecursive;
|
bool _isRecursive;
|
||||||
bool _isInHiddenDir;
|
bool _isInHiddenDir;
|
||||||
|
bool _dotMatchesNewline;
|
||||||
FindOption() : _isWholeWord(true), _isMatchCase(true), _searchType(FindNormal),\
|
FindOption() : _isWholeWord(true), _isMatchCase(true), _searchType(FindNormal),\
|
||||||
_isWrapAround(true), _whichDirection(DIR_DOWN), _incrementalType(NotIncremental),
|
_isWrapAround(true), _whichDirection(DIR_DOWN), _incrementalType(NotIncremental),
|
||||||
_doPurge(false), _doMarkLine(false),
|
_doPurge(false), _doMarkLine(false),
|
||||||
_isInSelection(false), _isRecursive(true), _isInHiddenDir(false),
|
_isInSelection(false), _isRecursive(true), _isInHiddenDir(false),
|
||||||
|
_dotMatchesNewline(false),
|
||||||
_filters(TEXT("")), _directory(TEXT("")) {};
|
_filters(TEXT("")), _directory(TEXT("")) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,7 +97,8 @@ public:
|
||||||
static int buildSearchFlags(const FindOption * option) {
|
static int buildSearchFlags(const FindOption * option) {
|
||||||
return (option->_isWholeWord ? SCFIND_WHOLEWORD : 0) |
|
return (option->_isWholeWord ? SCFIND_WHOLEWORD : 0) |
|
||||||
(option->_isMatchCase ? SCFIND_MATCHCASE : 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);
|
static void displaySectionCentered(int posStart, int posEnd, ScintillaEditView * pEditView, bool isDownwards = true);
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,11 @@ BEGIN
|
||||||
CONTROL "Match &whole word only",IDWHOLEWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,88,140,15
|
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 "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
|
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 "&Normal",IDNORMAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,12,143,126,10
|
||||||
CONTROL "E&xtended (\\n, \\r, \\t, \\0, \\x...)",IDEXTENDED,
|
CONTROL "E&xtended (\\n, \\r, \\t, \\0, \\x...)",IDEXTENDED,
|
||||||
"Button",BS_AUTORADIOBUTTON,12,155,145,10
|
"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 "&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
|
CONTROL "&Down",IDDIRECTIONDOWN,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,177,155,63,12
|
||||||
GROUPBOX "Direction",IDC_DIR_STATIC,172,131,74,48,WS_GROUP
|
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 "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 "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 "",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
|
END
|
||||||
|
|
||||||
IDB_INCREMENTAL_BG BITMAP "..\\icons\\incrementalBg.bmp"
|
IDB_INCREMENTAL_BG BITMAP "..\\icons\\incrementalBg.bmp"
|
||||||
|
|
|
@ -107,6 +107,8 @@
|
||||||
|
|
||||||
#define IDC_FRCOMMAND_INIT 1700
|
#define IDC_FRCOMMAND_INIT 1700
|
||||||
#define IDC_FRCOMMAND_EXEC 1701
|
#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
|
#endif //FINDREPLACE_DLG_H
|
||||||
|
|
|
@ -19,14 +19,14 @@
|
||||||
#include "xmlMatchedTagsHighlighter.h"
|
#include "xmlMatchedTagsHighlighter.h"
|
||||||
#include "ScintillaEditView.h"
|
#include "ScintillaEditView.h"
|
||||||
|
|
||||||
int XmlMatchedTagsHighlighter::getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, pair<int, int> & foundPos)
|
int XmlMatchedTagsHighlighter::getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, bool isRegex, pair<int, int> & foundPos)
|
||||||
{
|
{
|
||||||
//int start = currentPos;
|
//int start = currentPos;
|
||||||
//int end = (direction == DIR_LEFT)?0:_pEditView->getCurrentDocLen();
|
//int end = (direction == DIR_LEFT)?0:_pEditView->getCurrentDocLen();
|
||||||
|
|
||||||
_pEditView->execute(SCI_SETTARGETSTART, targetStart);
|
_pEditView->execute(SCI_SETTARGETSTART, targetStart);
|
||||||
_pEditView->execute(SCI_SETTARGETEND, targetEnd);
|
_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);
|
int posFind = _pEditView->execute(SCI_SEARCHINTARGET, (WPARAM)strlen(token), (LPARAM)token);
|
||||||
if (posFind != -1)
|
if (posFind != -1)
|
||||||
{
|
{
|
||||||
|
@ -42,8 +42,8 @@ TagCateg XmlMatchedTagsHighlighter::getTagCategory(XmlMatchedTagsPos & tagsPos,
|
||||||
|
|
||||||
int docLen = _pEditView->getCurrentDocLen();
|
int docLen = _pEditView->getCurrentDocLen();
|
||||||
|
|
||||||
int gtPos = getFirstTokenPosFrom(curPos, 0, ">", foundPos);
|
int gtPos = getFirstTokenPosFrom(curPos, 0, ">", false, foundPos);
|
||||||
int ltPos = getFirstTokenPosFrom(curPos, 0, "<", foundPos);
|
int ltPos = getFirstTokenPosFrom(curPos, 0, "<", false, foundPos);
|
||||||
if (ltPos != -1)
|
if (ltPos != -1)
|
||||||
{
|
{
|
||||||
if ((gtPos != -1) && (ltPos < gtPos))
|
if ((gtPos != -1) && (ltPos < gtPos))
|
||||||
|
@ -63,8 +63,8 @@ TagCateg XmlMatchedTagsHighlighter::getTagCategory(XmlMatchedTagsPos & tagsPos,
|
||||||
|
|
||||||
// so now we are sure we have tag sign '<'
|
// so now we are sure we have tag sign '<'
|
||||||
// We'll see on the right
|
// We'll see on the right
|
||||||
int gtPosOnR = getFirstTokenPosFrom(curPos, docLen, ">", foundPos);
|
int gtPosOnR = getFirstTokenPosFrom(curPos, docLen, ">", false, foundPos);
|
||||||
int ltPosOnR = getFirstTokenPosFrom(curPos, docLen, "<", foundPos);
|
int ltPosOnR = getFirstTokenPosFrom(curPos, docLen, "<", false, foundPos);
|
||||||
|
|
||||||
if (gtPosOnR == -1)
|
if (gtPosOnR == -1)
|
||||||
return invalidTag;
|
return invalidTag;
|
||||||
|
@ -112,7 +112,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd,
|
||||||
bool direction = searchEnd > searchStart;
|
bool direction = searchEnd > searchStart;
|
||||||
|
|
||||||
pair<int, int> foundPos;
|
pair<int, int> foundPos;
|
||||||
int ltPosOnR = getFirstTokenPosFrom(searchStart, searchEnd, tag2find, foundPos);
|
int ltPosOnR = getFirstTokenPosFrom(searchStart, searchEnd, tag2find, true, foundPos);
|
||||||
if (ltPosOnR == -1)
|
if (ltPosOnR == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd,
|
||||||
e = tagsPos.tagCloseStart;
|
e = tagsPos.tagCloseStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ltTag = getFirstTokenPosFrom(s, e, oppositeTag2find, oppositeTagPos);
|
int ltTag = getFirstTokenPosFrom(s, e, oppositeTag2find, true, oppositeTagPos);
|
||||||
|
|
||||||
if (ltTag == -1)
|
if (ltTag == -1)
|
||||||
{
|
{
|
||||||
|
@ -174,7 +174,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd,
|
||||||
{
|
{
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, oppositeTagPos);
|
ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, true, oppositeTagPos);
|
||||||
|
|
||||||
if (ltTag == -1)
|
if (ltTag == -1)
|
||||||
{
|
{
|
||||||
|
@ -204,7 +204,7 @@ bool XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd,
|
||||||
{
|
{
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, oppositeTagPos);
|
ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, true, oppositeTagPos);
|
||||||
if (ltTag == -1)
|
if (ltTag == -1)
|
||||||
{
|
{
|
||||||
if (direction == search2Left)
|
if (direction == search2Left)
|
||||||
|
|
|
@ -41,7 +41,7 @@ private:
|
||||||
|
|
||||||
ScintillaEditView *_pEditView;
|
ScintillaEditView *_pEditView;
|
||||||
|
|
||||||
int getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, std::pair<int, int> & foundPos);
|
int getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, bool isRegex, std::pair<int, int> & foundPos);
|
||||||
TagCateg getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos);
|
TagCateg getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos);
|
||||||
bool getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector<int> oppositeTagFound, XmlMatchedTagsPos & tagsPos);
|
bool getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector<int> oppositeTagFound, XmlMatchedTagsPos & tagsPos);
|
||||||
bool getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos);
|
bool getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos);
|
||||||
|
|
|
@ -228,7 +228,7 @@
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="false"
|
OmitFramePointers="false"
|
||||||
WholeProgramOptimization="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"
|
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"
|
GeneratePreprocessedFile="0"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
#ifndef ANSIDOCUMENTITERATOR_H_12481491281240
|
||||||
|
#define ANSIDOCUMENTITERATOR_H_12481491281240
|
||||||
|
|
||||||
|
class AnsiDocumentIterator : public std::iterator<std::bidirectional_iterator_tag, char>
|
||||||
|
{
|
||||||
|
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
|
|
@ -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 <stdlib.h>
|
||||||
|
#include <iterator>
|
||||||
|
#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 <boost/regex.hpp>
|
||||||
|
#define CP_UTF8 65001
|
||||||
|
#define SC_CP_UTF8 65001
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SCI_NAMESPACE
|
||||||
|
using namespace Scintilla;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace boost;
|
||||||
|
|
||||||
|
|
||||||
|
typedef basic_regex<char> charregex_t;
|
||||||
|
typedef boost::wregex wcharregex_t;
|
||||||
|
// , std::vector<boost::sub_match<DocumentIterator> >::allocator_type
|
||||||
|
typedef match_results<UTF8DocumentIterator> utf8match_t;
|
||||||
|
typedef match_results<AnsiDocumentIterator> 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<regex_constants::syntax_option_type>(compileFlags));
|
||||||
|
delete [] wchars;
|
||||||
|
m_lastRegexUtf8string = s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Ansi
|
||||||
|
m_charre = charregex_t(s, static_cast<regex_constants::syntax_option_type>(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<regex_constants::match_flag_type>(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<regex_constants::match_flag_type>(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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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<wchar_t>(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_utf8Length = 1;
|
||||||
|
m_utf16Length = 1;
|
||||||
|
m_characterIndex = 0;
|
||||||
|
m_character[0] = static_cast<wchar_t>(currentChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const unsigned char UTF8DocumentIterator::m_firstByteMask[7] = { 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
#ifndef UTF8DOCUMENTITERATOR_H_3452843291318441149
|
||||||
|
#define UTF8DOCUMENTITERATOR_H_3452843291318441149
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iterator>
|
||||||
|
#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>
|
||||||
|
|
||||||
|
class UTF8DocumentIterator : public std::iterator<std::bidirectional_iterator_tag, wchar_t>
|
||||||
|
{
|
||||||
|
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
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,8 @@ LOBJS=\
|
||||||
$(DIR_O)\WordList.obj \
|
$(DIR_O)\WordList.obj \
|
||||||
$(DIR_O)\XPM.obj \
|
$(DIR_O)\XPM.obj \
|
||||||
$(LEXOBJS)
|
$(LEXOBJS)
|
||||||
|
|
||||||
|
!INCLUDE ../boostregex/nppSpecifics.mak
|
||||||
|
|
||||||
$(DIR_O)\ScintRes.res : ScintRes.rc
|
$(DIR_O)\ScintRes.res : ScintRes.rc
|
||||||
$(RC) -fo$@ $**
|
$(RC) -fo$@ $**
|
||||||
|
|
Loading…
Reference in New Issue