[BUG_FIXED] (Author: Dave Brotherstone) Fix a html tag match freezing issue.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@925 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
Don Ho 2012-07-05 22:56:42 +00:00
parent af994f0042
commit 52d9ea2d4c
2 changed files with 38 additions and 12 deletions

View File

@ -133,12 +133,30 @@ bool XmlMatchedTagsHighlighter::getXmlMatchedTagsPos(XmlMatchedTagsPos &xmlTags)
{ {
bool tagFound = false; bool tagFound = false;
int caret = _pEditView->execute(SCI_GETCURRENTPOS); int caret = _pEditView->execute(SCI_GETCURRENTPOS);
FindResult openFound = findText("<", caret, 0, 0); int searchStartPoint = caret;
int styleAt;
FindResult openFound;
if (openFound.success && _pEditView->execute(SCI_GETSTYLEAT, openFound.start) != SCE_H_CDATA) // Search back for the previous open angle bracket.
// Keep looking whilst the angle bracket found is inside an XML attribute
do
{
openFound = findText("<", searchStartPoint, 0, 0);
styleAt = _pEditView->execute(SCI_GETSTYLEAT, openFound.start);
searchStartPoint = openFound.start - 1;
} while(openFound.success && (styleAt == SCE_H_DOUBLESTRING || styleAt == SCE_H_DOUBLESTRING) && searchStartPoint > 0);
if (openFound.success && styleAt != SCE_H_CDATA)
{ {
// Found the "<" before the caret, now check there isn't a > between that position and the caret. // Found the "<" before the caret, now check there isn't a > between that position and the caret.
FindResult closeFound = findText(">", openFound.start, caret, 0); FindResult closeFound;
searchStartPoint = openFound.start;
do
{
closeFound = findText(">", searchStartPoint, caret, 0);
styleAt = _pEditView->execute(SCI_GETSTYLEAT, closeFound.start);
searchStartPoint = closeFound.end;
} while (closeFound.success && (styleAt == SCE_H_DOUBLESTRING || styleAt == SCE_H_DOUBLESTRING) && searchStartPoint <= caret);
if (!closeFound.success) if (!closeFound.success)
{ {
@ -278,7 +296,7 @@ bool XmlMatchedTagsHighlighter::getXmlMatchedTagsPos(XmlMatchedTagsPos &xmlTags)
// First we need to check if this is a self-closing tag. // First we need to check if this is a self-closing tag.
// If it is, then we can just return this tag to highlight itself. // If it is, then we can just return this tag to highlight itself.
xmlTags.tagNameEnd = openFound.start + tagName.size() + 1; xmlTags.tagNameEnd = openFound.start + tagName.size() + 1;
int closeAnglePosition = findCloseAngle(position); int closeAnglePosition = findCloseAngle(position, docLength);
if (-1 != closeAnglePosition) if (-1 != closeAnglePosition)
{ {
xmlTags.tagOpenEnd = closeAnglePosition + 1; xmlTags.tagOpenEnd = closeAnglePosition + 1;
@ -385,7 +403,7 @@ XmlMatchedTagsHighlighter::FindResult XmlMatchedTagsHighlighter::findOpenTag(con
{ {
nextChar = _pEditView->execute(SCI_GETCHARAT, result.end); nextChar = _pEditView->execute(SCI_GETCHARAT, result.end);
styleAt = _pEditView->execute(SCI_GETSTYLEAT, result.start); styleAt = _pEditView->execute(SCI_GETSTYLEAT, result.start);
if (styleAt != SCE_H_CDATA) if (styleAt != SCE_H_CDATA && styleAt != SCE_H_DOUBLESTRING && styleAt != SCE_H_SINGLESTRING)
{ {
// We've got an open tag for this tag name (i.e. nextChar was space or '>') // We've got an open tag for this tag name (i.e. nextChar was space or '>')
// Now we need to find the end of the start tag. // Now we need to find the end of the start tag.
@ -398,7 +416,7 @@ XmlMatchedTagsHighlighter::FindResult XmlMatchedTagsHighlighter::findOpenTag(con
} }
else if (isWhitespace(nextChar)) else if (isWhitespace(nextChar))
{ {
int closeAnglePosition = findCloseAngle(result.end); int closeAnglePosition = findCloseAngle(result.end, forwardSearch ? end : start);
if (-1 != closeAnglePosition && '/' != _pEditView->execute(SCI_GETCHARAT, closeAnglePosition - 1)) if (-1 != closeAnglePosition && '/' != _pEditView->execute(SCI_GETCHARAT, closeAnglePosition - 1))
{ {
openTagFound.end = closeAnglePosition; openTagFound.end = closeAnglePosition;
@ -430,24 +448,32 @@ XmlMatchedTagsHighlighter::FindResult XmlMatchedTagsHighlighter::findOpenTag(con
} }
int XmlMatchedTagsHighlighter::findCloseAngle(int startPosition) int XmlMatchedTagsHighlighter::findCloseAngle(int startPosition, int endPosition)
{ {
// We'll search for the next '>', and check it's not in an attribute using the style // We'll search for the next '>', and check it's not in an attribute using the style
FindResult closeAngle; FindResult closeAngle;
int docLength = _pEditView->execute(SCI_GETLENGTH);
bool isValidClose; bool isValidClose;
int returnPosition = -1; int returnPosition = -1;
// Only search forwards
if (startPosition > endPosition)
{
int temp = endPosition;
endPosition = startPosition;
startPosition = temp;
}
do do
{ {
isValidClose = false; isValidClose = false;
closeAngle = findText(">", startPosition, docLength); closeAngle = findText(">", startPosition, endPosition);
if (closeAngle.success) if (closeAngle.success)
{ {
int style = _pEditView->execute(SCI_GETSTYLEAT, closeAngle.start); int style = _pEditView->execute(SCI_GETSTYLEAT, closeAngle.start);
// As long as we're not in an attribute ( <TAGNAME attrib="val>ue"> is VALID XML. ) // As long as we're not in an attribute ( <TAGNAME attrib="val>ue"> is VALID XML. )
if (style != SCE_H_DOUBLESTRING && style != SCE_H_SINGLESTRING && style != SCE_H_TAGUNKNOWN) if (style != SCE_H_DOUBLESTRING && style != SCE_H_SINGLESTRING)
{ {
returnPosition = closeAngle.start; returnPosition = closeAngle.start;
isValidClose = true; isValidClose = true;
@ -496,7 +522,7 @@ XmlMatchedTagsHighlighter::FindResult XmlMatchedTagsHighlighter::findCloseTag(co
searchStart = result.start - 1; searchStart = result.start - 1;
} }
if (styleAt != SCE_H_CDATA) // If what we found was in CDATA section, it's not a valid tag. if (styleAt != SCE_H_CDATA && styleAt != SCE_H_SINGLESTRING && styleAt != SCE_H_DOUBLESTRING) // If what we found was in CDATA section, it's not a valid tag.
{ {
// Common case - '>' follows the tag name directly // Common case - '>' follows the tag name directly
if (nextChar == '>') if (nextChar == '>')

View File

@ -66,7 +66,7 @@ private:
FindResult findText(const char *text, int start, int end, int flags = 0); FindResult findText(const char *text, int start, int end, int flags = 0);
FindResult findOpenTag(const std::string& tagName, int start, int end); FindResult findOpenTag(const std::string& tagName, int start, int end);
FindResult findCloseTag(const std::string& tagName, int start, int end); FindResult findCloseTag(const std::string& tagName, int start, int end);
int findCloseAngle(int startPosition); int findCloseAngle(int startPosition, int endPosition);
vector< pair<int, int> > getAttributesPos(int start, int end); vector< pair<int, int> > getAttributesPos(int start, int end);