[NEW_FEATURE] Add Matched Tag Highlighting feature.
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@248 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
8e9e2f30bc
commit
5be9af9cc9
@ -504,7 +504,7 @@ GLOBAL_INST:
|
||||
Delete "$INSTDIR\plugins\MultiClipboard.dll"
|
||||
|
||||
IfFileExists "$INSTDIR\plugins\Explorer.dll" 0 +3
|
||||
MessageBox MB_OK "Due to the problem of compability with this version,$\Explorer.dll is about to be deleted."
|
||||
MessageBox MB_OK "Due to the problem of compability with this version,$\nExplorer.dll is about to be deleted."
|
||||
Delete "$INSTDIR\plugins\Explorer.dll"
|
||||
|
||||
; detect the right of
|
||||
|
@ -48,6 +48,9 @@ const int smartHighlightFileSizeLimit = 1024 * 1024 * 3; // 3 MB
|
||||
int docTabIconIDs[] = {IDI_SAVED_ICON, IDI_UNSAVED_ICON, IDI_READONLY_ICON};
|
||||
enum tb_stat {tb_saved, tb_unsaved, tb_ro};
|
||||
|
||||
#define DIR_LEFT true
|
||||
#define DIR_RIGHT false
|
||||
|
||||
struct SortTaskListPred
|
||||
{
|
||||
DocTabView *_views[2];
|
||||
@ -2103,6 +2106,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
case SCN_UPDATEUI:
|
||||
{
|
||||
braceMatch();
|
||||
tagMatch();
|
||||
markSelectedText();
|
||||
updateStatusBar();
|
||||
AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub;
|
||||
@ -2288,6 +2292,201 @@ void Notepad_plus::findMatchingBracePos(int & braceAtCaret, int & braceOpposite)
|
||||
braceOpposite = int(_pEditView->execute(SCI_BRACEMATCH, braceAtCaret, 0));
|
||||
}
|
||||
|
||||
int Notepad_plus::getFirstTokenPosFrom(int currentPos, bool direction, const char *token, pair<int, int> & foundPos)
|
||||
{
|
||||
int start = currentPos;
|
||||
int end = (direction == DIR_LEFT)?0:_pEditView->getCurrentDocLen();
|
||||
|
||||
_pEditView->execute(SCI_SETTARGETSTART, start);
|
||||
_pEditView->execute(SCI_SETTARGETEND, end);
|
||||
_pEditView->execute(SCI_SETSEARCHFLAGS, SCFIND_REGEXP|SCFIND_POSIX);
|
||||
int posFind = _pEditView->execute(SCI_SEARCHINTARGET, (WPARAM)strlen(token), (LPARAM)token);
|
||||
|
||||
if (posFind != -1)
|
||||
{
|
||||
foundPos.first = _pEditView->execute(SCI_GETTARGETSTART);
|
||||
foundPos.second = _pEditView->execute(SCI_GETTARGETEND);
|
||||
}
|
||||
return posFind;
|
||||
}
|
||||
|
||||
TagCateg Notepad_plus::getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos)
|
||||
{
|
||||
pair<int, int> foundPos;
|
||||
|
||||
int gtPos = getFirstTokenPosFrom(curPos, DIR_LEFT, ">", foundPos);
|
||||
int ltPos = getFirstTokenPosFrom(curPos, DIR_LEFT, "<", foundPos);
|
||||
if (ltPos != -1)
|
||||
{
|
||||
if ((gtPos != -1) && (ltPos < gtPos))
|
||||
return outOfTag;
|
||||
|
||||
// Now we are sure about that we are inside of tag
|
||||
// We'll try to determinate the tag category :
|
||||
// tagOpen : <Tag>, <Tag Attr="1" >
|
||||
// tagClose : </Tag>
|
||||
// tagSigle : <Tag/>, <Tag Attr="0" />
|
||||
int charAfterLt = _pEditView->execute(SCI_GETCHARAT, ltPos+1);
|
||||
if (!charAfterLt)
|
||||
return unknownPb;
|
||||
|
||||
if ((char)charAfterLt == ' ')
|
||||
return invalidTag;
|
||||
|
||||
// so now we are sure we have tag sign '<'
|
||||
// We'll see on the right
|
||||
int gtPosOnR = getFirstTokenPosFrom(curPos, DIR_RIGHT, ">", foundPos);
|
||||
int ltPosOnR = getFirstTokenPosFrom(curPos, DIR_RIGHT, "<", foundPos);
|
||||
|
||||
if (gtPosOnR == -1)
|
||||
return invalidTag;
|
||||
|
||||
if ((ltPosOnR != -1) && (ltPosOnR < gtPosOnR))
|
||||
return invalidTag;
|
||||
|
||||
if ((char)charAfterLt == '/')
|
||||
{
|
||||
int char2AfterLt = _pEditView->execute(SCI_GETCHARAT, ltPos+1+1);
|
||||
|
||||
if (!char2AfterLt)
|
||||
return unknownPb;
|
||||
|
||||
if ((char)char2AfterLt == ' ')
|
||||
return invalidTag;
|
||||
|
||||
tagsPos.tagCloseStart = ltPos;
|
||||
tagsPos.tagCloseEnd = gtPosOnR + 1;
|
||||
return tagClose;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's sure for not being a tagClose
|
||||
// So we determinate if it's tagSingle or tagOpen
|
||||
tagsPos.tagOpenStart = ltPos;
|
||||
tagsPos.tagOpenEnd = gtPosOnR + 1;
|
||||
|
||||
int charBeforeLt = _pEditView->execute(SCI_GETCHARAT, gtPosOnR-1);
|
||||
if ((char)charBeforeLt == '/')
|
||||
return inSingleTag;
|
||||
|
||||
return tagOpen;
|
||||
}
|
||||
}
|
||||
|
||||
return outOfTag;
|
||||
}
|
||||
|
||||
bool Notepad_plus::getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos)
|
||||
{
|
||||
// get word where caret is on
|
||||
int caretPos = _pEditView->execute(SCI_GETCURRENTPOS);
|
||||
|
||||
// determinate the nature of current word : tagOpen, tagClose or outOfTag
|
||||
TagCateg tagCateg = getTagCategory(tagsPos, caretPos);
|
||||
|
||||
/*
|
||||
string toto;
|
||||
switch (tagCateg)
|
||||
{
|
||||
case tagOpen : toto = "tag open"; break;
|
||||
case tagClose : toto = "tag close"; break;
|
||||
case inSingleTag : toto = "tag single"; break;
|
||||
case invalidTag : toto = "tag invalid"; break;
|
||||
case unknownPb : toto = "unknown Pb"; break;
|
||||
}
|
||||
::SetWindowText(_hSelf, toto.c_str());
|
||||
*/
|
||||
switch (tagCateg)
|
||||
{
|
||||
case tagOpen : // if tagOpen search right
|
||||
{
|
||||
int startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, tagsPos.tagOpenStart+1, true);
|
||||
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagOpenStart+1, true);
|
||||
char * tagName = new char[endPos-startPos+1];
|
||||
|
||||
_pEditView->getText(tagName, startPos, endPos);
|
||||
|
||||
string closeTag = "</";
|
||||
closeTag += tagName;
|
||||
closeTag += "[ ]*>";
|
||||
|
||||
string openTag = "<";
|
||||
openTag += tagName;
|
||||
openTag += "[ >]";
|
||||
|
||||
delete [] tagName;
|
||||
|
||||
pair<int, int> foundPos;
|
||||
int ltPosOnR = getFirstTokenPosFrom(caretPos, DIR_RIGHT, closeTag.c_str(), foundPos);
|
||||
if (ltPosOnR == -1)
|
||||
return false;
|
||||
|
||||
pair<int, int> tmpPos;
|
||||
int openLtPosOnR = getFirstTokenPosFrom(caretPos, DIR_RIGHT, openTag.c_str(), tmpPos);
|
||||
if ((openLtPosOnR != -1) && (openLtPosOnR < ltPosOnR))
|
||||
return false;
|
||||
|
||||
tagsPos.tagCloseStart = foundPos.first;
|
||||
tagsPos.tagCloseEnd = foundPos.second;
|
||||
return true;
|
||||
}
|
||||
|
||||
case tagClose : // if tagClose search left
|
||||
{
|
||||
int startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, tagsPos.tagCloseStart+2, true);
|
||||
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagCloseStart+2, true);
|
||||
char * tagName = new char[endPos-startPos+1];
|
||||
|
||||
_pEditView->getText(tagName, startPos, endPos);
|
||||
|
||||
string openTag = "<";
|
||||
openTag += tagName;
|
||||
openTag += "[ >]";
|
||||
|
||||
delete [] tagName;
|
||||
|
||||
pair<int, int> foundPos;
|
||||
int ltPosOnL = getFirstTokenPosFrom(caretPos, DIR_LEFT, openTag.c_str(), foundPos);
|
||||
if (ltPosOnL == -1)
|
||||
return false;
|
||||
|
||||
if (getTagCategory(tagsPos, ltPosOnL+2) != tagOpen)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
case inSingleTag : // if in single tag
|
||||
return true;
|
||||
|
||||
default: // if outOfTag, just quit
|
||||
return false;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Notepad_plus::tagMatch()
|
||||
{
|
||||
// Clean up all marks of previous action
|
||||
_pEditView->clearIndicator(SCE_UNIVERSAL_TAGMATCH);
|
||||
|
||||
// Detect the current lang type. It works only with html and xml
|
||||
LangType lang = (_pEditView->getCurrentBuffer())->getLangType();
|
||||
if (lang != L_XML && lang != L_HTML && lang != L_PHP && lang != L_ASP)
|
||||
return;
|
||||
|
||||
// Detect if it's a xml/html tag
|
||||
// if yes, Colour it!
|
||||
|
||||
XmlMatchedTagsPos xmlTags;
|
||||
if (getXmlMatchedTagsPos(xmlTags))
|
||||
{
|
||||
_pEditView->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_TAGMATCH);
|
||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenStart, xmlTags.tagOpenEnd - xmlTags.tagOpenStart);
|
||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagCloseStart, xmlTags.tagCloseEnd - xmlTags.tagCloseStart);
|
||||
}
|
||||
}
|
||||
|
||||
void Notepad_plus::braceMatch()
|
||||
{
|
||||
int braceAtCaret = -1;
|
||||
@ -7825,7 +8024,6 @@ void Notepad_plus::markSelectedText()
|
||||
if (!nppGUI._enableSmartHilite)
|
||||
return;
|
||||
|
||||
//short
|
||||
if (_pEditView->isSelecting())
|
||||
//printStr("catch u!!!");
|
||||
return;
|
||||
|
@ -89,6 +89,8 @@ struct iconLocator {
|
||||
|
||||
class FileDialog;
|
||||
|
||||
enum TagCateg {tagOpen, tagClose, inSingleTag, outOfTag, invalidTag, unknownPb};
|
||||
|
||||
class Notepad_plus : public Window {
|
||||
enum comment_mode {cm_comment, cm_uncomment, cm_toggle};
|
||||
public:
|
||||
@ -265,6 +267,13 @@ private:
|
||||
|
||||
//For Dynamic selection highlight
|
||||
CharacterRange _prevSelectedRange;
|
||||
struct XmlMatchedTagsPos {
|
||||
int tagOpenStart;
|
||||
int tagOpenEnd;
|
||||
|
||||
int tagCloseStart;
|
||||
int tagCloseEnd;
|
||||
};
|
||||
|
||||
struct ActivateAppInfo {
|
||||
bool _isActivated;
|
||||
@ -649,6 +658,11 @@ private:
|
||||
|
||||
void findMatchingBracePos(int & braceAtCaret, int & braceOpposite);
|
||||
void braceMatch();
|
||||
|
||||
int getFirstTokenPosFrom(int currentPos, bool direction, const char *token, pair<int, int> & foundPos);
|
||||
TagCateg getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos);
|
||||
bool getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos);
|
||||
void tagMatch();
|
||||
|
||||
void activateNextDoc(bool direction);
|
||||
void activateDoc(int pos);
|
||||
|
@ -848,7 +848,7 @@ bool FindReplaceDlg::processFindNext(const char *txt2find, FindOption *options)
|
||||
(*_ppEditView)->execute(SCI_SETTARGETEND, endPosition);
|
||||
(*_ppEditView)->execute(SCI_SETSEARCHFLAGS, flags);
|
||||
|
||||
int posFind = int((*_ppEditView)->execute(SCI_SEARCHINTARGET, stringSizeFind, (LPARAM)pText));
|
||||
int posFind = int((*_ppEditView)->execute(SCI_SEARCHINTARGET, stringSizeFind, (LPARAM)pText));
|
||||
if (posFind == -1) //no match found in target, check if a new target should be used
|
||||
{
|
||||
if (pOptions->_isWrapAround)
|
||||
@ -1048,12 +1048,7 @@ int FindReplaceDlg::processAll(ProcessOperation op, const char *txt2find, const
|
||||
|
||||
bool isRegExp = pOptions->_searchType == FindRegex;
|
||||
int flags = Searching::buildSearchFlags(pOptions);
|
||||
/*
|
||||
if (op == ProcessMarkAll_2)
|
||||
flags = SCFIND_WHOLEWORD;
|
||||
else if (op == ProcessMarkAll_IncSearch)
|
||||
flags ^= SCFIND_WHOLEWORD;
|
||||
*/
|
||||
|
||||
CharacterRange cr = (*_ppEditView)->getSelection();
|
||||
int docLength = int((*_ppEditView)->execute(SCI_GETLENGTH));
|
||||
|
||||
|
@ -57,7 +57,7 @@ BEGIN
|
||||
|
||||
GROUPBOX "Search mode",IDC_MODE_STATIC,6,126,138,48
|
||||
CONTROL "&Normal",IDNORMAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,12,138,126,10
|
||||
CONTROL "&Extended",IDEXTENDED,"Button",BS_AUTORADIOBUTTON,12, 150,126,10
|
||||
CONTROL "&Extended (\\n, \\r, \\t, \\0, \\x...)",IDEXTENDED,"Button",BS_AUTORADIOBUTTON,12, 150,126,10
|
||||
CONTROL "Regular e&xpression",IDREGEXP,"Button", BS_AUTORADIOBUTTON,12,162,126,10
|
||||
|
||||
CONTROL "&Up",IDDIRECTIONUP,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,155,94,45,12
|
||||
|
@ -171,10 +171,12 @@ void ScintillaEditView::init(HINSTANCE hInst, HWND hPere)
|
||||
execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_FOUND_STYLE_2, INDIC_ROUNDBOX);
|
||||
execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_FOUND_STYLE, INDIC_ROUNDBOX);
|
||||
execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_FOUND_STYLE_INC, INDIC_ROUNDBOX);
|
||||
execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_TAGMATCH, INDIC_ROUNDBOX);
|
||||
|
||||
execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_FOUND_STYLE_2, 100);
|
||||
execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_FOUND_STYLE, 100);
|
||||
execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_FOUND_STYLE_INC, 100);
|
||||
execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_TAGMATCH, 100);
|
||||
|
||||
_pParameter = NppParameters::getInstance();
|
||||
|
||||
@ -727,6 +729,14 @@ void ScintillaEditView::defineDocType(LangType typeDoc)
|
||||
setSpecialIndicator(styleFind);
|
||||
}
|
||||
|
||||
iFind = stylers.getStylerIndexByID(SCE_UNIVERSAL_TAGMATCH);
|
||||
if (iFind != -1)
|
||||
{
|
||||
Style & styleFind = stylers.getStyler(iFind);
|
||||
//setSpecialStyle(styleFind);
|
||||
setSpecialIndicator(styleFind);
|
||||
}
|
||||
|
||||
iFind = stylers.getStylerIndexByID(SCE_UNIVERSAL_SELECT_STYLE);
|
||||
if (iFind != -1)
|
||||
{
|
||||
|
@ -713,6 +713,7 @@
|
||||
<WidgetStyle name="Smart HighLighting" styleID="29" bgColor="00FF00" />
|
||||
<WidgetStyle name="Find Mark Style" styleID="31" bgColor="FF0000" />
|
||||
<WidgetStyle name="Incremental highlight all" styleID="28" bgColor="0080FF" />
|
||||
<WidgetStyle name="Tags match highlighting" styleID="27" bgColor="8000FF" />
|
||||
<WidgetStyle name="Active tab focused indicator" styleID="0" fgColor="FAAA3C" />
|
||||
<WidgetStyle name="Active tab unfocused indicator" styleID="0" fgColor="FFCAB0" />
|
||||
<WidgetStyle name="Active tab text" styleID="0" fgColor="000000" />
|
||||
|
@ -111,6 +111,7 @@
|
||||
#define SCE_UNIVERSAL_FOUND_STYLE 31
|
||||
#define SCE_UNIVERSAL_FOUND_STYLE_2 29
|
||||
#define SCE_UNIVERSAL_FOUND_STYLE_INC 28
|
||||
#define SCE_UNIVERSAL_TAGMATCH 27
|
||||
|
||||
#define SCE_P_DEFAULT 0
|
||||
#define SCE_P_COMMENTLINE 1
|
||||
|
Loading…
Reference in New Issue
Block a user