[ENHANCEMENT] (Author: Ivan Radic,aka. Loreia L.) Enhance TAB/Space conversion: support UTF8 and to preserve formatting.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@1060 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
Don Ho 2013-06-18 19:44:32 +00:00
parent d39c743ff4
commit 197a28d1bd

View File

@ -1043,18 +1043,35 @@ bool Notepad_plus::matchInList(const TCHAR *fileName, const vector<generic_strin
return false; return false;
} }
void Notepad_plus::wsTabConvert(spaceTab whichWay) void Notepad_plus::wsTabConvert(spaceTab whichWay)
{ {
int tabWidth = _pEditView->execute(SCI_GETTABWIDTH); int tabWidth = _pEditView->execute(SCI_GETTABWIDTH);
int currentPos = _pEditView->execute(SCI_GETCURRENTPOS);
int lastLine = _pEditView->lastZeroBasedLineNumber();
int docLength = int(_pEditView->execute(SCI_GETLENGTH)) + 1; int docLength = int(_pEditView->execute(SCI_GETLENGTH)) + 1;
if (docLength < 2) if (docLength < 2)
return; return;
int count = 0; int count = 0;
int column = 0; int column = 0;
int counter = 0; int counter = 0;
int newCurrentPos = 0;
int tabStop = tabWidth - 1; // remember, counting from zero ! int tabStop = tabWidth - 1; // remember, counting from zero !
bool onlyLeading = false; bool onlyLeading = false;
bool nonSpaceFound = false; bool nonSpaceFound = false;
vector<int> bookmarks;
vector<int> folding;
for (int i=0; i<lastLine; ++i)
{
if (bookmarkPresent(i))
bookmarks.push_back(i);
if ((_pEditView->execute(SCI_GETFOLDLEVEL, i) & SC_FOLDLEVELHEADERFLAG))
if (_pEditView->execute(SCI_GETFOLDEXPANDED, i) == 0)
folding.push_back(i);
}
char * source = new char[docLength]; char * source = new char[docLength];
if (source == NULL) if (source == NULL)
@ -1089,24 +1106,28 @@ void Notepad_plus::wsTabConvert(spaceTab whichWay)
{ {
case tab2Space: case tab2Space:
{ {
// rip through each line in the file // rip through each line of the file
for (const char * ch = source; *ch; ++ch) for (int i = 0; source[i] != '\0'; ++i)
{ {
if (*ch == '\t') if (source[i] == '\t')
{ {
size_t insertTabs = tabWidth - (column % tabWidth); size_t insertTabs = tabWidth - (column % tabWidth);
for (size_t i = 0; i<insertTabs; ++i) for (size_t j = 0; j<insertTabs; ++j)
{ {
*dest++ = ' '; *dest++ = ' ';
if (i <= currentPos)
++newCurrentPos;
} }
column += insertTabs; column += insertTabs;
} }
else else
{ {
*dest++ = *ch; *dest++ = source[i];
if ((*ch == '\n') || (*ch == '\r')) if (i <= currentPos)
++newCurrentPos;
if ((source[i] == '\n') || (source[i] == '\r'))
column = 0; column = 0;
else else if ((source[i] & 0xC0) != 0x80) // UTF_8 support: count only bytes that don't start with 10......
++column; ++column;
} }
} }
@ -1120,37 +1141,43 @@ void Notepad_plus::wsTabConvert(spaceTab whichWay)
case space2TabAll: case space2TabAll:
{ {
bool nextChar = false; bool nextChar = false;
for (const char * ch=source; *ch; ++ch) for (int i=0; source[i] != '\0'; ++i)
{ {
if (nonSpaceFound == false) if (nonSpaceFound == false)
{ {
while (*(ch + counter) == ' ') while (source[i + counter] == ' ')
{ {
if ((column + counter) == tabStop) if ((column + counter) == tabStop)
{ {
tabStop += tabWidth; tabStop += tabWidth;
if (counter >= 1) // counter is counted from 0, so counter >= max -1 if (counter >= 1) // counter is counted from 0, so counter >= max-1
{ {
*dest++ = '\t'; *dest++ = '\t';
ch += counter; i += counter;
column += counter + 1; column += counter + 1;
counter = 0; counter = 0;
nextChar = true; nextChar = true;
if (i <= currentPos)
++newCurrentPos;
break; break;
} }
else if (*(ch+1) == ' ' || *(ch+1) == '\t') // if followed by space or TAB, convert even a single space to TAB else if (source[i+1] == ' ' || source[i+1] == '\t') // if followed by space or TAB, convert even a single space to TAB
{ {
*dest++ = '\t'; *dest++ = '\t';
ch++; i++;
column += 1; column += 1;
counter = 0; counter = 0;
if (i <= currentPos)
++newCurrentPos;
} }
else // single space, don't convert it to TAB else // single space, don't convert it to TAB
{ {
*dest++ = *ch; *dest++ = source[i];
column += 1; column += 1;
counter = 0; counter = 0;
nextChar = true; nextChar = true;
if (i <= currentPos)
++newCurrentPos;
break; break;
} }
} }
@ -1164,13 +1191,15 @@ void Notepad_plus::wsTabConvert(spaceTab whichWay)
continue; continue;
} }
if (*ch == ' ' && *(ch + counter) == '\t') // spaces "absorbed" by a TAB on the right if (source[i] == ' ' && source[i + counter] == '\t') // spaces "absorbed" by a TAB on the right
{ {
*dest++ = '\t'; *dest++ = '\t';
ch += counter; i += counter;
column = tabStop + 1; column = tabStop + 1;
tabStop += tabWidth; tabStop += tabWidth;
counter = 0; counter = 0;
if (i <= currentPos)
++newCurrentPos;
continue; continue;
} }
} }
@ -1178,30 +1207,36 @@ void Notepad_plus::wsTabConvert(spaceTab whichWay)
if (onlyLeading == true && nonSpaceFound == false) if (onlyLeading == true && nonSpaceFound == false)
nonSpaceFound = true; nonSpaceFound = true;
if (*ch == '\n' || *ch == '\r') if (source[i] == '\n' || source[i] == '\r')
{ {
*dest++ = *ch; *dest++ = source[i];
column = 0; column = 0;
tabStop = tabWidth - 1; tabStop = tabWidth - 1;
nonSpaceFound = false; nonSpaceFound = false;
} }
else if (*ch == '\t') else if (source[i] == '\t')
{ {
*dest++ = *ch; *dest++ = source[i];
column = tabStop + 1; column = tabStop + 1;
tabStop += tabWidth; tabStop += tabWidth;
counter = 0; counter = 0;
} }
else else
{ {
*dest++ = *ch; *dest++ = source[i];
++column;
counter = 0; counter = 0;
if ((source[i] & 0xC0) != 0x80) // UTF_8 support: count only bytes that don't start with 10......
{
++column;
if (column > 0 && column % tabWidth == 0) if (column > 0 && column % tabWidth == 0)
tabStop += tabWidth; tabStop += tabWidth;
} }
} }
if (i <= currentPos)
++newCurrentPos;
}
*dest = '\0'; *dest = '\0';
break; break;
} }
@ -1209,6 +1244,14 @@ void Notepad_plus::wsTabConvert(spaceTab whichWay)
_pEditView->execute(SCI_BEGINUNDOACTION); _pEditView->execute(SCI_BEGINUNDOACTION);
_pEditView->execute(SCI_SETTEXT, 0, (LPARAM)destination); _pEditView->execute(SCI_SETTEXT, 0, (LPARAM)destination);
_pEditView->execute(SCI_GOTOPOS, newCurrentPos);
for (size_t i=0; i<bookmarks.size(); ++i)
_pEditView->execute(SCI_MARKERADD, bookmarks[i], MARK_BOOKMARK);
for (size_t i=0; i<folding.size(); ++i)
_pEditView->fold(folding[i], false);
_pEditView->execute(SCI_ENDUNDOACTION); _pEditView->execute(SCI_ENDUNDOACTION);
// clean up // clean up