mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-23 05:45:00 +02:00
[IMPROVE] Reorganize the xml tag match hilite.
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@283 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
d8973543ad
commit
7523faff29
@ -39,6 +39,7 @@
|
|||||||
#include "xpm_icons.h"
|
#include "xpm_icons.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "xmlMatchedTagsHighlighter.h"
|
||||||
|
|
||||||
const char Notepad_plus::_className[32] = NOTEPAD_PP_CLASS_NAME;
|
const char Notepad_plus::_className[32] = NOTEPAD_PP_CLASS_NAME;
|
||||||
const char *urlHttpRegExpr = "http://[a-z0-9_\\-\\+.:?&@=/%#]*";
|
const char *urlHttpRegExpr = "http://[a-z0-9_\\-\\+.:?&@=/%#]*";
|
||||||
@ -2212,7 +2213,8 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||||||
case SCN_UPDATEUI:
|
case SCN_UPDATEUI:
|
||||||
{
|
{
|
||||||
braceMatch();
|
braceMatch();
|
||||||
tagMatch();
|
XmlMatchedTagsHighlighter xmlTagMatchHiliter(_pEditView);
|
||||||
|
xmlTagMatchHiliter.tagMatch();
|
||||||
markSelectedText();
|
markSelectedText();
|
||||||
updateStatusBar();
|
updateStatusBar();
|
||||||
AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub;
|
AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub;
|
||||||
@ -2398,428 +2400,6 @@ void Notepad_plus::findMatchingBracePos(int & braceAtCaret, int & braceOpposite)
|
|||||||
braceOpposite = int(_pEditView->execute(SCI_BRACEMATCH, braceAtCaret, 0));
|
braceOpposite = int(_pEditView->execute(SCI_BRACEMATCH, braceAtCaret, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Notepad_plus::getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, pair<int, int> & 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);
|
|
||||||
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 docLen = _pEditView->getCurrentDocLen();
|
|
||||||
|
|
||||||
int gtPos = getFirstTokenPosFrom(curPos, 0, ">", foundPos);
|
|
||||||
int ltPos = getFirstTokenPosFrom(curPos, 0, "<", 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, docLen, ">", foundPos);
|
|
||||||
int ltPosOnR = getFirstTokenPosFrom(curPos, docLen, "<", 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::getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector<int> oppositeTagFound, XmlMatchedTagsPos & tagsPos)
|
|
||||||
{
|
|
||||||
const bool search2Left = false;
|
|
||||||
const bool search2Right = true;
|
|
||||||
|
|
||||||
bool direction = searchEnd > searchStart;
|
|
||||||
|
|
||||||
pair<int, int> foundPos;
|
|
||||||
int ltPosOnR = getFirstTokenPosFrom(searchStart, searchEnd, tag2find, foundPos);
|
|
||||||
if (ltPosOnR == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
TagCateg tc = outOfTag;
|
|
||||||
if (direction == search2Left)
|
|
||||||
{
|
|
||||||
tc = getTagCategory(tagsPos, ltPosOnR+2);
|
|
||||||
|
|
||||||
if (tc != tagOpen && tc != inSingleTag)
|
|
||||||
return false;
|
|
||||||
if (tc == inSingleTag)
|
|
||||||
{
|
|
||||||
int start = foundPos.first;
|
|
||||||
int end = searchEnd;
|
|
||||||
return getMatchedTagPos(start, end, tag2find, oppositeTag2find, oppositeTagFound, tagsPos);
|
|
||||||
}
|
|
||||||
//oppositeTagFound.push_back(foundPos.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
pair<int, int> oppositeTagPos;
|
|
||||||
int s = foundPos.first;
|
|
||||||
int e = tagsPos.tagOpenEnd;
|
|
||||||
if (direction == search2Left)
|
|
||||||
{
|
|
||||||
s = foundPos.second;
|
|
||||||
e = tagsPos.tagCloseStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ltTag = getFirstTokenPosFrom(s, e, oppositeTag2find, oppositeTagPos);
|
|
||||||
|
|
||||||
if (ltTag == -1)
|
|
||||||
{
|
|
||||||
if (direction == search2Left)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tagsPos.tagCloseStart = foundPos.first;
|
|
||||||
tagsPos.tagCloseEnd = foundPos.second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isInList(ltTag, oppositeTagFound))
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, oppositeTagPos);
|
|
||||||
if (ltTag == -1)
|
|
||||||
{
|
|
||||||
if (direction == search2Left)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tagsPos.tagCloseStart = foundPos.first;
|
|
||||||
tagsPos.tagCloseEnd = foundPos.second;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (!isInList(ltTag, oppositeTagFound))
|
|
||||||
{
|
|
||||||
oppositeTagFound.push_back(ltTag);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (direction == search2Left)
|
|
||||||
{
|
|
||||||
XmlMatchedTagsPos tmpTagsPos;
|
|
||||||
getTagCategory(tmpTagsPos, ltTag+1);
|
|
||||||
ltTag = tmpTagsPos.tagCloseEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oppositeTagFound.push_back(ltTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
int start, end;
|
|
||||||
if (direction == search2Left)
|
|
||||||
{
|
|
||||||
start = foundPos.first;
|
|
||||||
end = searchEnd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = foundPos.second;
|
|
||||||
end = searchEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getMatchedTagPos(start, end, tag2find, oppositeTag2find, oppositeTagFound, tagsPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Notepad_plus::getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos)
|
|
||||||
{
|
|
||||||
// get word where caret is on
|
|
||||||
int caretPos = _pEditView->execute(SCI_GETCURRENTPOS);
|
|
||||||
|
|
||||||
int docLen = _pEditView->getCurrentDocLen();
|
|
||||||
|
|
||||||
// determinate the nature of current word : tagOpen, tagClose or outOfTag
|
|
||||||
TagCateg tagCateg = getTagCategory(tagsPos, caretPos);
|
|
||||||
|
|
||||||
static const char tagNameChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_:";
|
|
||||||
|
|
||||||
switch (tagCateg)
|
|
||||||
{
|
|
||||||
case tagOpen : // if tagOpen search right
|
|
||||||
{
|
|
||||||
_pEditView->execute(SCI_SETWORDCHARS, 0, (LPARAM)tagNameChars);
|
|
||||||
int startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, tagsPos.tagOpenStart+1, true);
|
|
||||||
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagOpenStart+1, true);
|
|
||||||
tagsPos.tagNameEnd = endPos;
|
|
||||||
|
|
||||||
_pEditView->execute(SCI_SETCHARSDEFAULT);
|
|
||||||
char * tagName = new char[endPos-startPos+1];
|
|
||||||
|
|
||||||
_pEditView->getText(tagName, startPos, endPos);
|
|
||||||
|
|
||||||
string closeTag = "</";
|
|
||||||
closeTag += tagName;
|
|
||||||
closeTag += "[ ]*>";
|
|
||||||
|
|
||||||
string openTag = "<";
|
|
||||||
openTag += tagName;
|
|
||||||
openTag += "[ >]";
|
|
||||||
|
|
||||||
delete [] tagName;
|
|
||||||
|
|
||||||
vector<int> passedTagList;
|
|
||||||
return getMatchedTagPos(tagsPos.tagOpenEnd, docLen, closeTag.c_str(), openTag.c_str(), passedTagList, tagsPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
case tagClose : // if tagClose search left
|
|
||||||
{
|
|
||||||
_pEditView->execute(SCI_SETWORDCHARS, 0, (LPARAM)tagNameChars);
|
|
||||||
int startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, tagsPos.tagCloseStart+2, true);
|
|
||||||
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagCloseStart+2, true);
|
|
||||||
|
|
||||||
_pEditView->execute(SCI_SETCHARSDEFAULT);
|
|
||||||
char * tagName = new char[endPos-startPos+1];
|
|
||||||
_pEditView->getText(tagName, startPos, endPos);
|
|
||||||
|
|
||||||
string openTag = "<";
|
|
||||||
openTag += tagName;
|
|
||||||
|
|
||||||
string closeTag = "</";
|
|
||||||
closeTag += tagName;
|
|
||||||
closeTag += "[ ]*>";
|
|
||||||
|
|
||||||
delete [] tagName;
|
|
||||||
|
|
||||||
vector<int> passedTagList;
|
|
||||||
bool isFound = getMatchedTagPos(tagsPos.tagCloseStart, 0, openTag.c_str(), closeTag.c_str(), passedTagList, tagsPos);
|
|
||||||
if (isFound)
|
|
||||||
tagsPos.tagNameEnd = tagsPos.tagOpenStart + 1 + (endPos - startPos);
|
|
||||||
|
|
||||||
return isFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
case inSingleTag : // if in single tag
|
|
||||||
{
|
|
||||||
_pEditView->execute(SCI_SETWORDCHARS, 0, (LPARAM)tagNameChars);
|
|
||||||
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagOpenStart+1, true);
|
|
||||||
tagsPos.tagNameEnd = endPos;
|
|
||||||
_pEditView->execute(SCI_SETCHARSDEFAULT);
|
|
||||||
|
|
||||||
tagsPos.tagCloseStart = -1;
|
|
||||||
tagsPos.tagCloseEnd = -1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default: // if outOfTag, just quit
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector< pair<int, int> > Notepad_plus::getAttributesPos(int start, int end)
|
|
||||||
{
|
|
||||||
vector< pair<int, int> > attributes;
|
|
||||||
|
|
||||||
int bufLen = end - start + 1;
|
|
||||||
char *buf = new char[bufLen+1];
|
|
||||||
_pEditView->getText(buf, start, end);
|
|
||||||
|
|
||||||
enum {\
|
|
||||||
attr_invalid,\
|
|
||||||
attr_key,\
|
|
||||||
attr_pre_assign,\
|
|
||||||
attr_assign,\
|
|
||||||
attr_string,\
|
|
||||||
attr_value,\
|
|
||||||
attr_valid\
|
|
||||||
} state = attr_invalid;
|
|
||||||
|
|
||||||
int startPos = -1;
|
|
||||||
int oneMoreChar = 1;
|
|
||||||
int i = 0;
|
|
||||||
for (; i < bufLen ; i++)
|
|
||||||
{
|
|
||||||
switch (buf[i])
|
|
||||||
{
|
|
||||||
case ' ':
|
|
||||||
case '\t':
|
|
||||||
case '\n':
|
|
||||||
case '\r':
|
|
||||||
{
|
|
||||||
if (state == attr_key)
|
|
||||||
state = attr_pre_assign;
|
|
||||||
else if (state == attr_value)
|
|
||||||
{
|
|
||||||
state = attr_valid;
|
|
||||||
oneMoreChar = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '=':
|
|
||||||
{
|
|
||||||
if (state == attr_key || state == attr_pre_assign)
|
|
||||||
state = attr_assign;
|
|
||||||
else if (state == attr_assign || state == attr_value)
|
|
||||||
state = attr_invalid;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '"':
|
|
||||||
{
|
|
||||||
if (state == attr_string)
|
|
||||||
{
|
|
||||||
state = attr_valid;
|
|
||||||
oneMoreChar = 1;
|
|
||||||
}
|
|
||||||
else if (state == attr_key || state == attr_pre_assign || state == attr_value)
|
|
||||||
state = attr_invalid;
|
|
||||||
else if (state == attr_assign)
|
|
||||||
state = attr_string;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (state == attr_invalid)
|
|
||||||
{
|
|
||||||
state = attr_key;
|
|
||||||
startPos = i;
|
|
||||||
}
|
|
||||||
else if (state == attr_pre_assign)
|
|
||||||
state = attr_invalid;
|
|
||||||
else if (state == attr_assign)
|
|
||||||
state = attr_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == attr_valid)
|
|
||||||
{
|
|
||||||
attributes.push_back(pair<int, int>(start+startPos, start+i+oneMoreChar));
|
|
||||||
state = attr_invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (state == attr_value)
|
|
||||||
attributes.push_back(pair<int, int>(start+startPos, start+i-1));
|
|
||||||
|
|
||||||
delete [] buf;
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Notepad_plus::tagMatch()
|
|
||||||
{
|
|
||||||
const NppGUI & nppGUI = (NppParameters::getInstance())->getNppGUI();
|
|
||||||
if (!nppGUI._enableTagsMatchHilite)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Clean up all marks of previous action
|
|
||||||
_pEditView->clearIndicator(SCE_UNIVERSAL_TAGMATCH);
|
|
||||||
_pEditView->clearIndicator(SCE_UNIVERSAL_TAGATTR);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Get the original targets to restore after tag matching operation
|
|
||||||
int originalStartPos = _pEditView->execute(SCI_GETTARGETSTART);
|
|
||||||
int originalEndPos = _pEditView->execute(SCI_GETTARGETEND);
|
|
||||||
|
|
||||||
// Detect if it's a xml/html tag. If yes, Colour it!
|
|
||||||
XmlMatchedTagsPos xmlTags;
|
|
||||||
if (getXmlMatchedTagsPos(xmlTags))
|
|
||||||
{
|
|
||||||
_pEditView->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_TAGMATCH);
|
|
||||||
|
|
||||||
int openTagTailLen = 2;
|
|
||||||
// We colourise the close tag firstly
|
|
||||||
if ((xmlTags.tagCloseStart != -1) && (xmlTags.tagCloseEnd != -1))
|
|
||||||
{
|
|
||||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagCloseStart, xmlTags.tagCloseEnd - xmlTags.tagCloseStart);
|
|
||||||
// tag close is present, so it's not single tag
|
|
||||||
openTagTailLen = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now the open tag and its attributs
|
|
||||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenStart, xmlTags.tagNameEnd - xmlTags.tagOpenStart);
|
|
||||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenEnd - openTagTailLen, openTagTailLen);
|
|
||||||
|
|
||||||
if (nppGUI._enableTagAttrsHilite)
|
|
||||||
{
|
|
||||||
vector< pair<int, int> > attributes = getAttributesPos(xmlTags.tagNameEnd, xmlTags.tagOpenEnd - openTagTailLen);
|
|
||||||
_pEditView->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_TAGATTR);
|
|
||||||
for (size_t i = 0 ; i < attributes.size() ; i++)
|
|
||||||
{
|
|
||||||
_pEditView->execute(SCI_INDICATORFILLRANGE, attributes[i].first, attributes[i].second - attributes[i].first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore the original targets to avoid the conflit with search/replace function
|
|
||||||
_pEditView->execute(SCI_SETTARGETSTART, originalStartPos);
|
|
||||||
_pEditView->execute(SCI_SETTARGETEND, originalEndPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notepad_plus::braceMatch()
|
void Notepad_plus::braceMatch()
|
||||||
{
|
{
|
||||||
|
@ -89,8 +89,6 @@ struct iconLocator {
|
|||||||
|
|
||||||
class FileDialog;
|
class FileDialog;
|
||||||
|
|
||||||
enum TagCateg {tagOpen, tagClose, inSingleTag, outOfTag, invalidTag, unknownPb};
|
|
||||||
|
|
||||||
class Notepad_plus : public Window {
|
class Notepad_plus : public Window {
|
||||||
enum comment_mode {cm_comment, cm_uncomment, cm_toggle};
|
enum comment_mode {cm_comment, cm_uncomment, cm_toggle};
|
||||||
public:
|
public:
|
||||||
@ -269,14 +267,6 @@ private:
|
|||||||
|
|
||||||
//For Dynamic selection highlight
|
//For Dynamic selection highlight
|
||||||
CharacterRange _prevSelectedRange;
|
CharacterRange _prevSelectedRange;
|
||||||
struct XmlMatchedTagsPos {
|
|
||||||
int tagOpenStart;
|
|
||||||
int tagNameEnd;
|
|
||||||
int tagOpenEnd;
|
|
||||||
|
|
||||||
int tagCloseStart;
|
|
||||||
int tagCloseEnd;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ActivateAppInfo {
|
struct ActivateAppInfo {
|
||||||
bool _isActivated;
|
bool _isActivated;
|
||||||
@ -675,19 +665,6 @@ private:
|
|||||||
void findMatchingBracePos(int & braceAtCaret, int & braceOpposite);
|
void findMatchingBracePos(int & braceAtCaret, int & braceOpposite);
|
||||||
void braceMatch();
|
void braceMatch();
|
||||||
|
|
||||||
int getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, pair<int, int> & foundPos);
|
|
||||||
TagCateg getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos);
|
|
||||||
bool getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector<int> oppositeTagFound, XmlMatchedTagsPos & tagsPos);
|
|
||||||
bool getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos);
|
|
||||||
vector< pair<int, int> > getAttributesPos(int start, int end);
|
|
||||||
bool isInList(int element, vector<int> elementList) {
|
|
||||||
for (size_t i = 0 ; i < elementList.size() ; i++)
|
|
||||||
if (element == elementList[i])
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
void tagMatch();
|
|
||||||
|
|
||||||
void activateNextDoc(bool direction);
|
void activateNextDoc(bool direction);
|
||||||
void activateDoc(int pos);
|
void activateDoc(int pos);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//this file is part of notepad++
|
//this file is part of notepad++
|
||||||
//Copyright (C)2003 Don HO ( donho@altern.org )
|
//Copyright (C)2003 Don HO <donho@altern.org>
|
||||||
//
|
//
|
||||||
//This program is free software; you can redistribute it and/or
|
//This program is free software; you can redistribute it and/or
|
||||||
//modify it under the terms of the GNU General Public License
|
//modify it under the terms of the GNU General Public License
|
||||||
|
442
PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.cpp
Normal file
442
PowerEditor/src/ScitillaComponent/xmlMatchedTagsHighlighter.cpp
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
//this file is part of notepad++
|
||||||
|
//Copyright (C)2003 Don HO <donho@altern.org>
|
||||||
|
//
|
||||||
|
//This program is free software; you can redistribute it and/or
|
||||||
|
//modify it under the terms of the GNU General Public License
|
||||||
|
//as published by the Free Software Foundation; either
|
||||||
|
//version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
//This program is distributed in the hope that it will be useful,
|
||||||
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
//GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//You should have received a copy of the GNU General Public License
|
||||||
|
//along with this program; if not, write to the Free Software
|
||||||
|
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
#include "xmlMatchedTagsHighlighter.h"
|
||||||
|
#include "ScintillaEditView.h"
|
||||||
|
|
||||||
|
int XmlMatchedTagsHighlighter::getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, pair<int, int> & 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);
|
||||||
|
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 XmlMatchedTagsHighlighter::getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos)
|
||||||
|
{
|
||||||
|
pair<int, int> foundPos;
|
||||||
|
|
||||||
|
int docLen = _pEditView->getCurrentDocLen();
|
||||||
|
|
||||||
|
int gtPos = getFirstTokenPosFrom(curPos, 0, ">", foundPos);
|
||||||
|
int ltPos = getFirstTokenPosFrom(curPos, 0, "<", 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, docLen, ">", foundPos);
|
||||||
|
int ltPosOnR = getFirstTokenPosFrom(curPos, docLen, "<", 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 XmlMatchedTagsHighlighter::getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector<int> oppositeTagFound, XmlMatchedTagsPos & tagsPos)
|
||||||
|
{
|
||||||
|
const bool search2Left = false;
|
||||||
|
const bool search2Right = true;
|
||||||
|
|
||||||
|
bool direction = searchEnd > searchStart;
|
||||||
|
|
||||||
|
pair<int, int> foundPos;
|
||||||
|
int ltPosOnR = getFirstTokenPosFrom(searchStart, searchEnd, tag2find, foundPos);
|
||||||
|
if (ltPosOnR == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TagCateg tc = outOfTag;
|
||||||
|
if (direction == search2Left)
|
||||||
|
{
|
||||||
|
tc = getTagCategory(tagsPos, ltPosOnR+2);
|
||||||
|
|
||||||
|
if (tc != tagOpen && tc != inSingleTag)
|
||||||
|
return false;
|
||||||
|
if (tc == inSingleTag)
|
||||||
|
{
|
||||||
|
int start = foundPos.first;
|
||||||
|
int end = searchEnd;
|
||||||
|
return getMatchedTagPos(start, end, tag2find, oppositeTag2find, oppositeTagFound, tagsPos);
|
||||||
|
}
|
||||||
|
//oppositeTagFound.push_back(foundPos.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<int, int> oppositeTagPos;
|
||||||
|
int s = foundPos.first;
|
||||||
|
int e = tagsPos.tagOpenEnd;
|
||||||
|
if (direction == search2Left)
|
||||||
|
{
|
||||||
|
s = foundPos.second;
|
||||||
|
e = tagsPos.tagCloseStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ltTag = getFirstTokenPosFrom(s, e, oppositeTag2find, oppositeTagPos);
|
||||||
|
|
||||||
|
if (ltTag == -1)
|
||||||
|
{
|
||||||
|
if (direction == search2Left)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tagsPos.tagCloseStart = foundPos.first;
|
||||||
|
tagsPos.tagCloseEnd = foundPos.second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isInList(ltTag, oppositeTagFound))
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ltTag = getFirstTokenPosFrom(ltTag, e, oppositeTag2find, oppositeTagPos);
|
||||||
|
if (ltTag == -1)
|
||||||
|
{
|
||||||
|
if (direction == search2Left)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tagsPos.tagCloseStart = foundPos.first;
|
||||||
|
tagsPos.tagCloseEnd = foundPos.second;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!isInList(ltTag, oppositeTagFound))
|
||||||
|
{
|
||||||
|
oppositeTagFound.push_back(ltTag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (direction == search2Left)
|
||||||
|
{
|
||||||
|
XmlMatchedTagsPos tmpTagsPos;
|
||||||
|
getTagCategory(tmpTagsPos, ltTag+1);
|
||||||
|
ltTag = tmpTagsPos.tagCloseEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oppositeTagFound.push_back(ltTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int start, end;
|
||||||
|
if (direction == search2Left)
|
||||||
|
{
|
||||||
|
start = foundPos.first;
|
||||||
|
end = searchEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start = foundPos.second;
|
||||||
|
end = searchEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getMatchedTagPos(start, end, tag2find, oppositeTag2find, oppositeTagFound, tagsPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool XmlMatchedTagsHighlighter::getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos)
|
||||||
|
{
|
||||||
|
// get word where caret is on
|
||||||
|
int caretPos = _pEditView->execute(SCI_GETCURRENTPOS);
|
||||||
|
|
||||||
|
int docLen = _pEditView->getCurrentDocLen();
|
||||||
|
|
||||||
|
// determinate the nature of current word : tagOpen, tagClose or outOfTag
|
||||||
|
TagCateg tagCateg = getTagCategory(tagsPos, caretPos);
|
||||||
|
|
||||||
|
static const char tagNameChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_:";
|
||||||
|
|
||||||
|
switch (tagCateg)
|
||||||
|
{
|
||||||
|
case tagOpen : // if tagOpen search right
|
||||||
|
{
|
||||||
|
_pEditView->execute(SCI_SETWORDCHARS, 0, (LPARAM)tagNameChars);
|
||||||
|
int startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, tagsPos.tagOpenStart+1, true);
|
||||||
|
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagOpenStart+1, true);
|
||||||
|
tagsPos.tagNameEnd = endPos;
|
||||||
|
|
||||||
|
_pEditView->execute(SCI_SETCHARSDEFAULT);
|
||||||
|
char * tagName = new char[endPos-startPos+1];
|
||||||
|
|
||||||
|
_pEditView->getText(tagName, startPos, endPos);
|
||||||
|
|
||||||
|
string closeTag = "</";
|
||||||
|
closeTag += tagName;
|
||||||
|
closeTag += "[ ]*>";
|
||||||
|
|
||||||
|
string openTag = "<";
|
||||||
|
openTag += tagName;
|
||||||
|
openTag += "[ >]";
|
||||||
|
|
||||||
|
delete [] tagName;
|
||||||
|
|
||||||
|
vector<int> passedTagList;
|
||||||
|
return getMatchedTagPos(tagsPos.tagOpenEnd, docLen, closeTag.c_str(), openTag.c_str(), passedTagList, tagsPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
case tagClose : // if tagClose search left
|
||||||
|
{
|
||||||
|
_pEditView->execute(SCI_SETWORDCHARS, 0, (LPARAM)tagNameChars);
|
||||||
|
int startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, tagsPos.tagCloseStart+2, true);
|
||||||
|
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagCloseStart+2, true);
|
||||||
|
|
||||||
|
_pEditView->execute(SCI_SETCHARSDEFAULT);
|
||||||
|
char * tagName = new char[endPos-startPos+1];
|
||||||
|
_pEditView->getText(tagName, startPos, endPos);
|
||||||
|
|
||||||
|
string openTag = "<";
|
||||||
|
openTag += tagName;
|
||||||
|
|
||||||
|
string closeTag = "</";
|
||||||
|
closeTag += tagName;
|
||||||
|
closeTag += "[ ]*>";
|
||||||
|
|
||||||
|
delete [] tagName;
|
||||||
|
|
||||||
|
vector<int> passedTagList;
|
||||||
|
bool isFound = getMatchedTagPos(tagsPos.tagCloseStart, 0, openTag.c_str(), closeTag.c_str(), passedTagList, tagsPos);
|
||||||
|
if (isFound)
|
||||||
|
tagsPos.tagNameEnd = tagsPos.tagOpenStart + 1 + (endPos - startPos);
|
||||||
|
|
||||||
|
return isFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
case inSingleTag : // if in single tag
|
||||||
|
{
|
||||||
|
_pEditView->execute(SCI_SETWORDCHARS, 0, (LPARAM)tagNameChars);
|
||||||
|
int endPos = _pEditView->execute(SCI_WORDENDPOSITION, tagsPos.tagOpenStart+1, true);
|
||||||
|
tagsPos.tagNameEnd = endPos;
|
||||||
|
_pEditView->execute(SCI_SETCHARSDEFAULT);
|
||||||
|
|
||||||
|
tagsPos.tagCloseStart = -1;
|
||||||
|
tagsPos.tagCloseEnd = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: // if outOfTag, just quit
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector< pair<int, int> > XmlMatchedTagsHighlighter::getAttributesPos(int start, int end)
|
||||||
|
{
|
||||||
|
vector< pair<int, int> > attributes;
|
||||||
|
|
||||||
|
int bufLen = end - start + 1;
|
||||||
|
char *buf = new char[bufLen+1];
|
||||||
|
_pEditView->getText(buf, start, end);
|
||||||
|
|
||||||
|
enum {\
|
||||||
|
attr_invalid,\
|
||||||
|
attr_key,\
|
||||||
|
attr_pre_assign,\
|
||||||
|
attr_assign,\
|
||||||
|
attr_string,\
|
||||||
|
attr_value,\
|
||||||
|
attr_valid\
|
||||||
|
} state = attr_invalid;
|
||||||
|
|
||||||
|
int startPos = -1;
|
||||||
|
int oneMoreChar = 1;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < bufLen ; i++)
|
||||||
|
{
|
||||||
|
switch (buf[i])
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
{
|
||||||
|
if (state == attr_key)
|
||||||
|
state = attr_pre_assign;
|
||||||
|
else if (state == attr_value)
|
||||||
|
{
|
||||||
|
state = attr_valid;
|
||||||
|
oneMoreChar = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '=':
|
||||||
|
{
|
||||||
|
if (state == attr_key || state == attr_pre_assign)
|
||||||
|
state = attr_assign;
|
||||||
|
else if (state == attr_assign || state == attr_value)
|
||||||
|
state = attr_invalid;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
{
|
||||||
|
if (state == attr_string)
|
||||||
|
{
|
||||||
|
state = attr_valid;
|
||||||
|
oneMoreChar = 1;
|
||||||
|
}
|
||||||
|
else if (state == attr_key || state == attr_pre_assign || state == attr_value)
|
||||||
|
state = attr_invalid;
|
||||||
|
else if (state == attr_assign)
|
||||||
|
state = attr_string;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (state == attr_invalid)
|
||||||
|
{
|
||||||
|
state = attr_key;
|
||||||
|
startPos = i;
|
||||||
|
}
|
||||||
|
else if (state == attr_pre_assign)
|
||||||
|
state = attr_invalid;
|
||||||
|
else if (state == attr_assign)
|
||||||
|
state = attr_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == attr_valid)
|
||||||
|
{
|
||||||
|
attributes.push_back(pair<int, int>(start+startPos, start+i+oneMoreChar));
|
||||||
|
state = attr_invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state == attr_value)
|
||||||
|
attributes.push_back(pair<int, int>(start+startPos, start+i-1));
|
||||||
|
|
||||||
|
delete [] buf;
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void XmlMatchedTagsHighlighter::tagMatch()
|
||||||
|
{
|
||||||
|
const NppGUI & nppGUI = (NppParameters::getInstance())->getNppGUI();
|
||||||
|
if (!nppGUI._enableTagsMatchHilite)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Clean up all marks of previous action
|
||||||
|
_pEditView->clearIndicator(SCE_UNIVERSAL_TAGMATCH);
|
||||||
|
_pEditView->clearIndicator(SCE_UNIVERSAL_TAGATTR);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Get the original targets to restore after tag matching operation
|
||||||
|
int originalStartPos = _pEditView->execute(SCI_GETTARGETSTART);
|
||||||
|
int originalEndPos = _pEditView->execute(SCI_GETTARGETEND);
|
||||||
|
|
||||||
|
// Detect if it's a xml/html tag. If yes, Colour it!
|
||||||
|
XmlMatchedTagsPos xmlTags;
|
||||||
|
if (getXmlMatchedTagsPos(xmlTags))
|
||||||
|
{
|
||||||
|
_pEditView->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_TAGMATCH);
|
||||||
|
|
||||||
|
int openTagTailLen = 2;
|
||||||
|
// We colourise the close tag firstly
|
||||||
|
if ((xmlTags.tagCloseStart != -1) && (xmlTags.tagCloseEnd != -1))
|
||||||
|
{
|
||||||
|
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagCloseStart, xmlTags.tagCloseEnd - xmlTags.tagCloseStart);
|
||||||
|
// tag close is present, so it's not single tag
|
||||||
|
openTagTailLen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the open tag and its attributs
|
||||||
|
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenStart, xmlTags.tagNameEnd - xmlTags.tagOpenStart);
|
||||||
|
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenEnd - openTagTailLen, openTagTailLen);
|
||||||
|
|
||||||
|
if (nppGUI._enableTagAttrsHilite)
|
||||||
|
{
|
||||||
|
vector< pair<int, int> > attributes = getAttributesPos(xmlTags.tagNameEnd, xmlTags.tagOpenEnd - openTagTailLen);
|
||||||
|
_pEditView->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_TAGATTR);
|
||||||
|
for (size_t i = 0 ; i < attributes.size() ; i++)
|
||||||
|
{
|
||||||
|
_pEditView->execute(SCI_INDICATORFILLRANGE, attributes[i].first, attributes[i].second - attributes[i].first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore the original targets to avoid the conflit with search/replace function
|
||||||
|
_pEditView->execute(SCI_SETTARGETSTART, originalStartPos);
|
||||||
|
_pEditView->execute(SCI_SETTARGETEND, originalEndPos);
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
//this file is part of notepad++
|
||||||
|
//Copyright (C)2003 Don HO <donho@altern.org>
|
||||||
|
//
|
||||||
|
//This program is free software; you can redistribute it and/or
|
||||||
|
//modify it under the terms of the GNU General Public License
|
||||||
|
//as published by the Free Software Foundation; either
|
||||||
|
//version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
//This program is distributed in the hope that it will be useful,
|
||||||
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
//GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//You should have received a copy of the GNU General Public License
|
||||||
|
//along with this program; if not, write to the Free Software
|
||||||
|
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
#ifndef XMLMATCHEDTAGSHIGHLIGHTER_H
|
||||||
|
#define XMLMATCHEDTAGSHIGHLIGHTER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class ScintillaEditView;
|
||||||
|
|
||||||
|
enum TagCateg {tagOpen, tagClose, inSingleTag, outOfTag, invalidTag, unknownPb};
|
||||||
|
|
||||||
|
class XmlMatchedTagsHighlighter {
|
||||||
|
public:
|
||||||
|
XmlMatchedTagsHighlighter(ScintillaEditView *pEditView):_pEditView(pEditView){};
|
||||||
|
void tagMatch();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct XmlMatchedTagsPos {
|
||||||
|
int tagOpenStart;
|
||||||
|
int tagNameEnd;
|
||||||
|
int tagOpenEnd;
|
||||||
|
|
||||||
|
int tagCloseStart;
|
||||||
|
int tagCloseEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
ScintillaEditView *_pEditView;
|
||||||
|
|
||||||
|
int getFirstTokenPosFrom(int targetStart, int targetEnd, const char *token, std::pair<int, int> & foundPos);
|
||||||
|
TagCateg getTagCategory(XmlMatchedTagsPos & tagsPos, int curPos);
|
||||||
|
bool getMatchedTagPos(int searchStart, int searchEnd, const char *tag2find, const char *oppositeTag2find, vector<int> oppositeTagFound, XmlMatchedTagsPos & tagsPos);
|
||||||
|
bool getXmlMatchedTagsPos(XmlMatchedTagsPos & tagsPos);
|
||||||
|
vector< pair<int, int> > getAttributesPos(int start, int end);
|
||||||
|
bool isInList(int element, vector<int> elementList) {
|
||||||
|
for (size_t i = 0 ; i < elementList.size() ; i++)
|
||||||
|
if (element == elementList[i])
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //XMLMATCHEDTAGSHIGHLIGHTER_H
|
||||||
|
|
@ -1,3 +1,20 @@
|
|||||||
|
//this file is part of notepad++
|
||||||
|
//Copyright (C)2003 Don HO ( donho@altern.org )
|
||||||
|
//
|
||||||
|
//This program is free software; you can redistribute it and/or
|
||||||
|
//modify it under the terms of the GNU General Public License
|
||||||
|
//as published by the Free Software Foundation; either
|
||||||
|
//version 2 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
//This program is distributed in the hope that it will be useful,
|
||||||
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
//GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
//You should have received a copy of the GNU General Public License
|
||||||
|
//along with this program; if not, write to the Free Software
|
||||||
|
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "preferenceDlg.h"
|
#include "preferenceDlg.h"
|
||||||
#include "SysMsg.h"
|
#include "SysMsg.h"
|
||||||
|
@ -437,6 +437,10 @@
|
|||||||
RelativePath="..\src\WinControls\ColourPicker\WordStyleDlg.cpp"
|
RelativePath="..\src\WinControls\ColourPicker\WordStyleDlg.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\ScitillaComponent\xmlMatchedTagsHighlighter.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
@ -603,11 +607,11 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\resource.h"
|
RelativePath="..\src\WinControls\Preference\resource.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\WinControls\Preference\resource.h"
|
RelativePath="..\src\resource.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@ -750,6 +754,10 @@
|
|||||||
RelativePath="..\src\WinControls\ColourPicker\WordStyleDlg.h"
|
RelativePath="..\src\WinControls\ColourPicker\WordStyleDlg.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\ScitillaComponent\xmlMatchedTagsHighlighter.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\xpm_icons.h"
|
RelativePath="..\src\xpm_icons.h"
|
||||||
>
|
>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user