[BUG_FIXED] (Author : Vitaliy Dovgan)Fix case-insensitive searching bug for non-ascii characters (for example some characters in French and Cyrillic characters).
[BUG_FIXED] Fix brace highlighting performance issue. git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@578 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
51e96391c6
commit
6f052ca8dc
@ -2764,10 +2764,51 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
if (notification->nmhdr.hwndFrom != _pEditView->getHSelf())
|
||||
break;
|
||||
|
||||
braceMatch();
|
||||
|
||||
NppGUI & nppGui = (NppGUI &)nppParam->getNppGUI();
|
||||
|
||||
static int originalColour = _pEditView->execute(SCI_STYLEGETFORE, STYLE_BRACELIGHT);
|
||||
_pEditView->execute(SCI_STYLESETFORE, STYLE_BRACELIGHT, originalColour);
|
||||
if (nppGui._enableTagsMatchHilite)
|
||||
{
|
||||
XmlMatchedTagsHighlighter xmlTagMatchHiliter(_pEditView);
|
||||
xmlTagMatchHiliter.tagMatch(nppGui._enableTagAttrsHilite);
|
||||
}
|
||||
|
||||
if (nppGui._enableSmartHilite)
|
||||
{
|
||||
if (nppGui._disableSmartHiliteTmp)
|
||||
nppGui._disableSmartHiliteTmp = false;
|
||||
else
|
||||
_smartHighlighter.highlightView(notifyView);
|
||||
}
|
||||
|
||||
updateStatusBar();
|
||||
AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub;
|
||||
autoC->update(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case SCN_UPDATEUI:
|
||||
{
|
||||
|
||||
NppParameters *nppParam = NppParameters::getInstance();
|
||||
|
||||
// if it's searching/replacing, then do nothing
|
||||
if (nppParam->_isFindReplacing)
|
||||
break;
|
||||
|
||||
if (notification->nmhdr.hwndFrom != _pEditView->getHSelf())
|
||||
break;
|
||||
|
||||
static NppGUI & nppGui = (NppGUI &)nppParam->getNppGUI();
|
||||
static StyleArray & stylers = nppParam->getMiscStylerArray();
|
||||
static int iBraceStyle = stylers.getStylerIndexByID(STYLE_BRACELIGHT);
|
||||
if (iBraceStyle != -1)
|
||||
{
|
||||
Style *pBraceStyle = &(stylers.getStyler(iBraceStyle));
|
||||
_pEditView->execute(SCI_STYLESETFORE, STYLE_BRACELIGHT, pBraceStyle->_fgColor);
|
||||
}
|
||||
|
||||
if (braceMatch())
|
||||
{
|
||||
@ -2781,6 +2822,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
XmlMatchedTagsHighlighter xmlTagMatchHiliter(_pEditView);
|
||||
pair<int, int> tagPos = xmlTagMatchHiliter.tagMatch(nppGui._enableTagAttrsHilite);
|
||||
|
||||
|
||||
int braceAtCaret = tagPos.first;
|
||||
int braceOpposite = tagPos.second;
|
||||
|
||||
@ -2788,6 +2830,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
{
|
||||
_pEditView->execute(SCI_SETHIGHLIGHTGUIDE, 0);
|
||||
}
|
||||
|
||||
else if (_pEditView->isShownIndentGuide())
|
||||
{
|
||||
int columnAtCaret = int(_pEditView->execute(SCI_GETCOLUMN, braceAtCaret));
|
||||
@ -2797,19 +2840,18 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
int lineOpposite = int(_pEditView->execute(SCI_LINEFROMPOSITION, braceOpposite));
|
||||
if (lineAtCaret != lineOpposite)
|
||||
{
|
||||
|
||||
StyleArray & stylers = nppParam->getMiscStylerArray();
|
||||
int iFind = stylers.getStylerIndexByID(SCE_UNIVERSAL_TAGMATCH);
|
||||
if (iFind)
|
||||
static int iTagMatchStyle = stylers.getStylerIndexByID(SCE_UNIVERSAL_TAGMATCH);
|
||||
if (iTagMatchStyle != -1)
|
||||
{
|
||||
Style *pStyle = &(stylers.getStyler(iFind));
|
||||
_pEditView->execute(SCI_STYLESETFORE, STYLE_BRACELIGHT, pStyle->_bgColor);
|
||||
Style *pTagStyle = &(stylers.getStyler(iTagMatchStyle));
|
||||
_pEditView->execute(SCI_STYLESETFORE, STYLE_BRACELIGHT, pTagStyle->_bgColor);
|
||||
}
|
||||
// braceAtCaret - 1, braceOpposite-1 : walk around to not highlight the '<'
|
||||
_pEditView->execute(SCI_BRACEHIGHLIGHT, braceAtCaret-1, braceOpposite-1);
|
||||
_pEditView->execute(SCI_SETHIGHLIGHTGUIDE, (columnAtCaret < columnOpposite)?columnAtCaret:columnOpposite);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -2826,6 +2868,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
autoC->update(0);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case SCN_SCROLLED:
|
||||
{
|
||||
|
@ -439,7 +439,7 @@ vector< pair<int, int> > XmlMatchedTagsHighlighter::getAttributesPos(int start,
|
||||
|
||||
|
||||
|
||||
pair<int, int> XmlMatchedTagsHighlighter::tagMatch(bool doHiliteAttr)
|
||||
void XmlMatchedTagsHighlighter::tagMatch(bool doHiliteAttr)
|
||||
{
|
||||
// Clean up all marks of previous action
|
||||
_pEditView->clearIndicator(SCE_UNIVERSAL_TAGMATCH);
|
||||
@ -449,21 +449,22 @@ pair<int, int> XmlMatchedTagsHighlighter::tagMatch(bool doHiliteAttr)
|
||||
LangType lang = (_pEditView->getCurrentBuffer())->getLangType();
|
||||
|
||||
if (lang != L_XML && lang != L_HTML && lang != L_PHP && lang != L_ASP)
|
||||
return pair<int, int>(-1, -1);
|
||||
return;
|
||||
|
||||
// Get the original targets and search options to restore after tag matching operation
|
||||
int originalStartPos = _pEditView->execute(SCI_GETTARGETSTART);
|
||||
int originalEndPos = _pEditView->execute(SCI_GETTARGETEND);
|
||||
int originalSearchFlags = _pEditView->execute(SCI_GETSEARCHFLAGS);
|
||||
|
||||
// Detect if it's a xml/html tag. If yes, Colour it!
|
||||
XmlMatchedTagsPos xmlTags;
|
||||
|
||||
// Detect if it's a xml/html tag. If yes, Colour it!
|
||||
if (getXmlMatchedTagsPos(xmlTags))
|
||||
{
|
||||
_pEditView->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_TAGMATCH);
|
||||
|
||||
int openTagTailLen = 2;
|
||||
// We colourise the close tag firstly
|
||||
|
||||
// Colourising the close tag firstly
|
||||
if ((xmlTags.tagCloseStart != -1) && (xmlTags.tagCloseEnd != -1))
|
||||
{
|
||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagCloseStart, xmlTags.tagCloseEnd - xmlTags.tagCloseStart);
|
||||
@ -471,10 +472,12 @@ pair<int, int> XmlMatchedTagsHighlighter::tagMatch(bool doHiliteAttr)
|
||||
openTagTailLen = 1;
|
||||
}
|
||||
|
||||
// Now the open tag and its attributs
|
||||
// Colourising the open tag
|
||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenStart, xmlTags.tagNameEnd - xmlTags.tagOpenStart);
|
||||
_pEditView->execute(SCI_INDICATORFILLRANGE, xmlTags.tagOpenEnd - openTagTailLen, openTagTailLen);
|
||||
|
||||
|
||||
// Colouising its attributs
|
||||
if (doHiliteAttr)
|
||||
{
|
||||
vector< pair<int, int> > attributes = getAttributesPos(xmlTags.tagNameEnd, xmlTags.tagOpenEnd - openTagTailLen);
|
||||
@ -484,12 +487,23 @@ pair<int, int> XmlMatchedTagsHighlighter::tagMatch(bool doHiliteAttr)
|
||||
_pEditView->execute(SCI_INDICATORFILLRANGE, attributes[i].first, attributes[i].second - attributes[i].first);
|
||||
}
|
||||
}
|
||||
|
||||
// Colouising indent guide line position
|
||||
int columnAtCaret = int(_pEditView->execute(SCI_GETCOLUMN, xmlTags.tagOpenStart));
|
||||
int columnOpposite = int(_pEditView->execute(SCI_GETCOLUMN, xmlTags.tagCloseStart));
|
||||
|
||||
int lineAtCaret = int(_pEditView->execute(SCI_LINEFROMPOSITION, xmlTags.tagOpenStart));
|
||||
int lineOpposite = int(_pEditView->execute(SCI_LINEFROMPOSITION, xmlTags.tagCloseStart));
|
||||
|
||||
if (xmlTags.tagCloseStart != -1 && lineAtCaret != lineOpposite)
|
||||
{
|
||||
_pEditView->execute(SCI_BRACEHIGHLIGHT, xmlTags.tagOpenStart, xmlTags.tagCloseEnd-1);
|
||||
_pEditView->execute(SCI_SETHIGHLIGHTGUIDE, (columnAtCaret < columnOpposite)?columnAtCaret:columnOpposite);
|
||||
}
|
||||
}
|
||||
|
||||
// restore the original targets and search options to avoid the conflit with search/replace function
|
||||
_pEditView->execute(SCI_SETTARGETSTART, originalStartPos);
|
||||
_pEditView->execute(SCI_SETTARGETEND, originalEndPos);
|
||||
_pEditView->execute(SCI_SETSEARCHFLAGS, originalSearchFlags);
|
||||
|
||||
return pair<int, int>(xmlTags.tagOpenStart, xmlTags.tagCloseStart);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ enum TagCateg {tagOpen, tagClose, inSingleTag, outOfTag, invalidTag, unknownPb};
|
||||
class XmlMatchedTagsHighlighter {
|
||||
public:
|
||||
XmlMatchedTagsHighlighter(ScintillaEditView *pEditView):_pEditView(pEditView){};
|
||||
pair<int, int> tagMatch(bool doHiliteAttr);
|
||||
void tagMatch(bool doHiliteAttr);
|
||||
|
||||
private:
|
||||
struct XmlMatchedTagsPos {
|
||||
|
@ -27,6 +27,98 @@
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
//Vitaliy
|
||||
#include "UniConversion.h"
|
||||
#include <windows.h>
|
||||
#ifdef FindText
|
||||
#undef FindText
|
||||
#define FindText FindText
|
||||
#endif
|
||||
|
||||
// Win32 only !!!
|
||||
static bool IsMustDie9x(void)
|
||||
{
|
||||
OSVERSIONINFO osver;
|
||||
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if ( GetVersionEx( &osver ) )
|
||||
{
|
||||
if ( (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
|
||||
(osver.dwMajorVersion == 4) )
|
||||
{
|
||||
//MessageBox(NULL, "MustDie9x == true", "Test", MB_OK);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//MessageBox(NULL, "MustDie9x == false", "Test", MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void Platform_MakeUpperW(wchar_t* wstr, unsigned int len) {
|
||||
// TODO: Add platform-specific function here
|
||||
|
||||
// Win32 example:
|
||||
static bool bIsMustDie9x = IsMustDie9x();
|
||||
|
||||
if ( !bIsMustDie9x )
|
||||
{
|
||||
::CharUpperW(wstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* str = new char[len + 1];
|
||||
if ( str )
|
||||
{
|
||||
::WideCharToMultiByte(CP_ACP, 0, wstr, len, str, len, NULL, NULL);
|
||||
str[len] = 0;
|
||||
::CharUpperA(str);
|
||||
::MultiByteToWideChar(CP_ACP, 0, str, len, wstr, len);
|
||||
wstr[len] = 0;
|
||||
delete [] str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline char Platform_MakeUpperCharA(const char ch) {
|
||||
// TODO: Add platform-specific function here
|
||||
|
||||
// Win32 example:
|
||||
char str[2] = {ch, 0};
|
||||
::CharUpperA(str);
|
||||
return str[0];
|
||||
}
|
||||
|
||||
static inline char Platform_MakeLowerCharA(const char ch) {
|
||||
// TODO: Add platform-specific function here
|
||||
|
||||
// Win32 example:
|
||||
char str[2] = {ch, 0};
|
||||
::CharLowerA(str);
|
||||
return str[0];
|
||||
}
|
||||
|
||||
// NOTE: this function is called for non-Unicode characters only!
|
||||
// ( i.e. when (!dbcsCodePage || isascii(ch)) )
|
||||
static inline char MakeUpperCaseA(char ch) {
|
||||
if (ch >= 'A' && ch <= 'Z')
|
||||
return ch;
|
||||
else if (ch >= 'a' && ch <= 'z')
|
||||
return static_cast<char>(ch - 'a' + 'A');
|
||||
else
|
||||
return Platform_MakeUpperCharA(ch);
|
||||
}
|
||||
|
||||
// NOTE: this function is called for non-Unicode characters only!
|
||||
// ( i.e. when (!dbcsCodePage || isascii(ch)) )
|
||||
static inline char MakeLowerCaseA(char ch) {
|
||||
if (ch >= 'a' && ch <= 'z')
|
||||
return ch;
|
||||
else if (ch >= 'A' && ch <= 'Z')
|
||||
return static_cast<char>(ch - 'A' + 'a');
|
||||
else
|
||||
return Platform_MakeLowerCharA(ch);
|
||||
}
|
||||
// yilatiV
|
||||
|
||||
// This is ASCII specific but is safe with chars >= 0x80
|
||||
static inline bool isspacechar(unsigned char ch) {
|
||||
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
|
||||
@ -1104,9 +1196,34 @@ long Document::FindText(int minPos, int maxPos, const char *s,
|
||||
endSearch = endPos - lengthFind + 1;
|
||||
}
|
||||
//Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
|
||||
|
||||
// >>> Added by DV
|
||||
wchar_t* ws_upr = NULL; // string we are searching for in UCS-2
|
||||
wchar_t temp_ws[4]; // buffer for current character in UCS-2
|
||||
char temp_s[8]; // buffer for current character in UTF-8
|
||||
int ws_len = 0;
|
||||
|
||||
if (dbcsCodePage == SC_CP_UTF8 && !caseSensitive)
|
||||
{
|
||||
ws_len = (int) UTF16Length(s, lengthFind);
|
||||
if (ws_len != lengthFind) {
|
||||
const int ws_size = ws_len + 2;
|
||||
ws_upr = new wchar_t[ws_size];
|
||||
if (ws_upr) {
|
||||
UTF16FromUTF8(s, lengthFind, ws_upr, ws_size - 1);
|
||||
ws_upr[ws_len] = 0;
|
||||
Platform_MakeUpperW(ws_upr, ws_len);
|
||||
// now ws_upr is UCS-2 representation of s in upper-case
|
||||
}
|
||||
}
|
||||
// else we are searching for Latin characters
|
||||
// i.e. no special processing required
|
||||
}
|
||||
// <<< Added by DV
|
||||
|
||||
char firstChar = s[0];
|
||||
if (!caseSensitive)
|
||||
firstChar = static_cast<char>(MakeUpperCase(firstChar));
|
||||
firstChar = static_cast<char>(MakeUpperCaseA(firstChar));
|
||||
int pos = forward ? startPos : (startPos - 1);
|
||||
while (forward ? (pos < endSearch) : (pos >= endSearch)) {
|
||||
char ch = CharAt(pos);
|
||||
@ -1126,13 +1243,57 @@ long Document::FindText(int minPos, int maxPos, const char *s,
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (MakeUpperCase(ch) == firstChar) {
|
||||
}
|
||||
|
||||
// >>> Added by DV
|
||||
else if (ws_upr) {
|
||||
const int maxPos = Platform::Maximum(startPos, endPos);
|
||||
int charPos = pos;
|
||||
int ws_len_checked = 0;
|
||||
|
||||
while (ws_len_checked < ws_len) {
|
||||
// LenChar returns 2 for "\r\n"
|
||||
// this is wrong for UTF8 because "\r\n"
|
||||
// is not one character with length=2
|
||||
const int charLen = IsCrLf(charPos) ? 1 : LenChar(charPos);
|
||||
if (charPos + charLen > maxPos)
|
||||
break;
|
||||
|
||||
// current UTF-8 character
|
||||
for (int i = 0; i < charLen; i++) {
|
||||
temp_s[i] = CharAt(charPos + i);
|
||||
}
|
||||
temp_s[charLen] = 0;
|
||||
// current character as UCS-2
|
||||
const unsigned int uLen = UTF16FromUTF8(temp_s, charLen, temp_ws, 3);
|
||||
temp_ws[uLen] = 0; // uLen can be 1 (ordinary) or 2 (surrogate)
|
||||
// upper case
|
||||
Platform_MakeUpperW(temp_ws, uLen);
|
||||
if ((temp_ws[0] == ws_upr[ws_len_checked]) &&
|
||||
(uLen == 1 || temp_ws[1] == ws_upr[ws_len_checked+1])) {
|
||||
ws_len_checked += uLen;
|
||||
charPos += charLen; // go to next character
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (ws_len_checked == ws_len) {
|
||||
if ((!word && !wordStart) ||
|
||||
(word && IsWordAt(pos, pos + lengthFind)) ||
|
||||
(wordStart && IsWordStartAt(pos))) {
|
||||
delete [] ws_upr;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
// <<< Added by DV
|
||||
|
||||
else {
|
||||
if (MakeUpperCaseA(ch) == firstChar) {
|
||||
bool found = true;
|
||||
if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
|
||||
for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
|
||||
ch = CharAt(pos + posMatch);
|
||||
if (MakeUpperCase(ch) != MakeUpperCase(s[posMatch]))
|
||||
if (MakeUpperCaseA(ch) != MakeUpperCaseA(s[posMatch]))
|
||||
found = false;
|
||||
}
|
||||
if (found) {
|
||||
@ -1149,6 +1310,13 @@ long Document::FindText(int minPos, int maxPos, const char *s,
|
||||
pos = MovePositionOutsideChar(pos, increment, false);
|
||||
}
|
||||
}
|
||||
|
||||
// >>> Added by DV
|
||||
if (ws_upr) {
|
||||
delete [] ws_upr;
|
||||
}
|
||||
// <<< Added by DV
|
||||
|
||||
}
|
||||
//Platform::DebugPrintf("Not found\n");
|
||||
return -1;
|
||||
@ -1169,11 +1337,11 @@ void Document::ChangeCase(Range r, bool makeUpperCase) {
|
||||
char ch = CharAt(pos);
|
||||
if (makeUpperCase) {
|
||||
if (IsLowerCase(ch)) {
|
||||
ChangeChar(pos, static_cast<char>(MakeUpperCase(ch)));
|
||||
ChangeChar(pos, static_cast<char>(MakeUpperCaseA(ch)));
|
||||
}
|
||||
} else {
|
||||
if (IsUpperCase(ch)) {
|
||||
ChangeChar(pos, static_cast<char>(MakeLowerCase(ch)));
|
||||
ChangeChar(pos, static_cast<char>(MakeLowerCaseA(ch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user