[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:
donho 2008-06-22 23:32:56 +00:00
parent 8e9e2f30bc
commit 5be9af9cc9
8 changed files with 229 additions and 10 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -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

View File

@ -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)
{

View File

@ -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" />

View File

@ -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