mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-26 20:03:10 +00:00
738 lines
17 KiB
C++
738 lines
17 KiB
C++
![]() |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
|
* ASEnhancer.cpp
|
||
|
*
|
||
|
* Copyright (C) 2006-2011 by Jim Pattee <jimp03@email.com>
|
||
|
* Copyright (C) 1998-2002 by Tal Davidson
|
||
|
* <http://www.gnu.org/licenses/lgpl-3.0.html>
|
||
|
*
|
||
|
* This file is a part of Artistic Style - an indentation and
|
||
|
* reformatting tool for C, C++, C# and Java source files.
|
||
|
* <http://astyle.sourceforge.net>
|
||
|
*
|
||
|
* Artistic Style is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Lesser General Public License as published
|
||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* Artistic Style 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 Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public License
|
||
|
* along with Artistic Style. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
|
*/
|
||
|
|
||
|
#include "astyle.h"
|
||
|
#include <iostream> // for cout
|
||
|
|
||
|
namespace astyle
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
* ASEnhancer constructor
|
||
|
*/
|
||
|
ASEnhancer::ASEnhancer()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Destructor of ASEnhancer
|
||
|
*/
|
||
|
ASEnhancer::~ASEnhancer()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* initialize the ASEnhancer.
|
||
|
*
|
||
|
* init() is called each time an ASFormatter object is initialized.
|
||
|
*/
|
||
|
void ASEnhancer::init(int _fileType,
|
||
|
int _indentLength,
|
||
|
int _tabLength,
|
||
|
bool _useTabs,
|
||
|
bool _forceTab,
|
||
|
bool _caseIndent,
|
||
|
bool _preprocessorIndent,
|
||
|
bool _emptyLineFill)
|
||
|
{
|
||
|
// formatting variables from ASFormatter and ASBeautifier
|
||
|
ASBase::init(_fileType);
|
||
|
indentLength = _indentLength;
|
||
|
tabLength = _tabLength;
|
||
|
useTabs = _useTabs;
|
||
|
forceTab = _forceTab;
|
||
|
caseIndent = _caseIndent;
|
||
|
preprocessorIndent = _preprocessorIndent;
|
||
|
emptyLineFill = _emptyLineFill;
|
||
|
quoteChar = '\'';
|
||
|
|
||
|
// unindent variables
|
||
|
lineNumber = 0;
|
||
|
bracketCount = 0;
|
||
|
isInComment = false;
|
||
|
isInQuote = false;
|
||
|
switchDepth = 0;
|
||
|
lookingForCaseBracket = false;
|
||
|
unindentNextLine = false;
|
||
|
shouldIndentLine = false;
|
||
|
|
||
|
// switch struct and vector
|
||
|
sw.switchBracketCount = 0;
|
||
|
sw.unindentDepth = 0;
|
||
|
sw.unindentCase = false;
|
||
|
switchStack.clear();
|
||
|
|
||
|
// other variables
|
||
|
nextLineIsEventIndent = false;
|
||
|
isInEventTable = false;
|
||
|
nextLineIsDeclareIndent = false;
|
||
|
isInDeclareSection = false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* additional formatting for line of source code.
|
||
|
* every line of source code in a source code file should be sent
|
||
|
* one after the other to this function.
|
||
|
* indents event tables
|
||
|
* unindents the case blocks
|
||
|
*
|
||
|
* @param line the original formatted line will be updated if necessary.
|
||
|
*/
|
||
|
void ASEnhancer::enhance(string &line, bool isInPreprocessor, bool isInSQL)
|
||
|
{
|
||
|
bool isSpecialChar = false; // is a backslash escape character
|
||
|
shouldIndentLine = true;
|
||
|
lineNumber++;
|
||
|
|
||
|
// check for beginning of event table
|
||
|
if (nextLineIsEventIndent)
|
||
|
{
|
||
|
isInEventTable = true;
|
||
|
nextLineIsEventIndent = false;
|
||
|
}
|
||
|
|
||
|
// check for beginning of SQL declare section
|
||
|
if (nextLineIsDeclareIndent)
|
||
|
{
|
||
|
isInDeclareSection = true;
|
||
|
nextLineIsDeclareIndent = false;
|
||
|
}
|
||
|
|
||
|
if (line.length() == 0
|
||
|
&& ! isInEventTable
|
||
|
&& ! isInDeclareSection
|
||
|
&& ! emptyLineFill)
|
||
|
return;
|
||
|
|
||
|
// test for unindent on attached brackets
|
||
|
if (unindentNextLine)
|
||
|
{
|
||
|
sw.unindentDepth++;
|
||
|
sw.unindentCase = true;
|
||
|
unindentNextLine = false;
|
||
|
}
|
||
|
|
||
|
// parse characters in the current line.
|
||
|
|
||
|
for (size_t i = 0; i < line.length(); i++)
|
||
|
{
|
||
|
char ch = line[i];
|
||
|
|
||
|
// bypass whitespace
|
||
|
if (isWhiteSpace(ch))
|
||
|
continue;
|
||
|
|
||
|
// handle special characters (i.e. backslash+character such as \n, \t, ...)
|
||
|
if (isSpecialChar)
|
||
|
{
|
||
|
isSpecialChar = false;
|
||
|
continue;
|
||
|
}
|
||
|
if (!(isInComment) && line.compare(i, 2, "\\\\") == 0)
|
||
|
{
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
if (!(isInComment) && ch == '\\')
|
||
|
{
|
||
|
isSpecialChar = true;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// handle quotes (such as 'x' and "Hello Dolly")
|
||
|
if (!isInComment && (ch == '"' || ch == '\''))
|
||
|
{
|
||
|
if (!isInQuote)
|
||
|
{
|
||
|
quoteChar = ch;
|
||
|
isInQuote = true;
|
||
|
}
|
||
|
else if (quoteChar == ch)
|
||
|
{
|
||
|
isInQuote = false;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isInQuote)
|
||
|
continue;
|
||
|
|
||
|
// handle comments
|
||
|
|
||
|
if (!(isInComment) && line.compare(i, 2, "//") == 0)
|
||
|
{
|
||
|
// check for windows line markers
|
||
|
if (line.compare(i + 2, 1, "\xf0") > 0)
|
||
|
lineNumber--;
|
||
|
break; // finished with the line
|
||
|
}
|
||
|
else if (!(isInComment) && line.compare(i, 2, "/*") == 0)
|
||
|
{
|
||
|
isInComment = true;
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
else if ((isInComment) && line.compare(i, 2, "*/") == 0)
|
||
|
{
|
||
|
isInComment = false;
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (isInComment)
|
||
|
continue;
|
||
|
|
||
|
// if we have reached this far then we are NOT in a comment or string of special characters
|
||
|
|
||
|
if (line[i] == '{')
|
||
|
bracketCount++;
|
||
|
|
||
|
if (line[i] == '}')
|
||
|
bracketCount--;
|
||
|
|
||
|
bool isPotentialKeyword = isCharPotentialHeader(line, i);
|
||
|
|
||
|
// ---------------- wxWidgets and MFC macros ----------------------------------
|
||
|
|
||
|
if (isPotentialKeyword)
|
||
|
{
|
||
|
if (findKeyword(line, i, "BEGIN_EVENT_TABLE")
|
||
|
|| findKeyword(line, i, "BEGIN_DISPATCH_MAP")
|
||
|
|| findKeyword(line, i, "BEGIN_EVENT_MAP")
|
||
|
|| findKeyword(line, i, "BEGIN_MESSAGE_MAP")
|
||
|
|| findKeyword(line, i, "BEGIN_PROPPAGEIDS"))
|
||
|
{
|
||
|
nextLineIsEventIndent = true;
|
||
|
break;
|
||
|
}
|
||
|
if (findKeyword(line, i, "END_EVENT_TABLE")
|
||
|
|| findKeyword(line, i, "END_DISPATCH_MAP")
|
||
|
|| findKeyword(line, i, "END_EVENT_MAP")
|
||
|
|| findKeyword(line, i, "END_MESSAGE_MAP")
|
||
|
|| findKeyword(line, i, "END_PROPPAGEIDS"))
|
||
|
{
|
||
|
isInEventTable = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ---------------- process SQL -----------------------------------------------
|
||
|
|
||
|
if (isInSQL)
|
||
|
{
|
||
|
if (isBeginDeclareSectionSQL(line, i))
|
||
|
nextLineIsDeclareIndent = true;
|
||
|
if (isEndDeclareSectionSQL(line, i))
|
||
|
isInDeclareSection = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// ---------------- process switch statements ---------------------------------
|
||
|
|
||
|
if (isPotentialKeyword && findKeyword(line, i, "switch"))
|
||
|
{
|
||
|
switchDepth++;
|
||
|
switchStack.push_back(sw); // save current variables
|
||
|
sw.switchBracketCount = 0;
|
||
|
sw.unindentCase = false; // don't clear case until end of switch
|
||
|
i += 5; // bypass switch statement
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// just want unindented case statements from this point
|
||
|
|
||
|
if (caseIndent
|
||
|
|| switchDepth == 0
|
||
|
|| (isInPreprocessor && !preprocessorIndent))
|
||
|
{
|
||
|
// bypass the entire word
|
||
|
if (isPotentialKeyword)
|
||
|
{
|
||
|
string name = getCurrentWord(line, i);
|
||
|
i += name.length() - 1;
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
i = processSwitchBlock(line, i);
|
||
|
|
||
|
} // end of for loop * end of for loop * end of for loop * end of for loop
|
||
|
|
||
|
if (isInEventTable || isInDeclareSection)
|
||
|
{
|
||
|
if (line.length() == 0 || line[0] != '#')
|
||
|
indentLine(line, 1);
|
||
|
}
|
||
|
|
||
|
if (shouldIndentLine && sw.unindentDepth > 0)
|
||
|
unindentLine(line, sw.unindentDepth);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* find the colon following a 'case' statement
|
||
|
*
|
||
|
* @param line a reference to the line.
|
||
|
* @param i the line index of the case statement.
|
||
|
* @return the line index of the colon.
|
||
|
*/
|
||
|
size_t ASEnhancer::findCaseColon(string &line, size_t caseIndex) const
|
||
|
{
|
||
|
size_t i = caseIndex;
|
||
|
bool isInQuote_ = false;
|
||
|
char quoteChar_ = ' ';
|
||
|
for (; i < line.length(); i++)
|
||
|
{
|
||
|
if (isInQuote_)
|
||
|
{
|
||
|
if (line[i] == '\\')
|
||
|
{
|
||
|
i++;
|
||
|
continue;
|
||
|
}
|
||
|
else if (line[i] == quoteChar_) // check ending quote
|
||
|
{
|
||
|
isInQuote_ = false;
|
||
|
quoteChar_ = ' ';
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
continue; // must close quote before continuing
|
||
|
}
|
||
|
}
|
||
|
if (line[i] == '\'' || line[i] == '\"') // check opening quote
|
||
|
{
|
||
|
isInQuote_ = true;
|
||
|
quoteChar_ = line[i];
|
||
|
continue;
|
||
|
}
|
||
|
if (line[i] == ':')
|
||
|
{
|
||
|
if ((i + 1 < line.length()) && (line[i + 1] == ':'))
|
||
|
i++; // bypass scope resolution operator
|
||
|
else
|
||
|
break; // found it
|
||
|
}
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* convert a force-tab indent to spaces
|
||
|
*
|
||
|
* @param line a reference to the line that will be converted.
|
||
|
*/
|
||
|
void ASEnhancer::convertForceTabIndentToSpaces(string &line) const
|
||
|
{
|
||
|
// replace tab indents with spaces
|
||
|
for (size_t i = 0; i < line.length(); i++)
|
||
|
{
|
||
|
if (!isWhiteSpace(line[i]))
|
||
|
break;
|
||
|
if (line[i] == '\t')
|
||
|
{
|
||
|
line.erase(i, 1);
|
||
|
line.insert(i, tabLength, ' ');
|
||
|
i += tabLength - 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* convert a space indent to force-tab
|
||
|
*
|
||
|
* @param line a reference to the line that will be converted.
|
||
|
*/
|
||
|
void ASEnhancer::convertSpaceIndentToForceTab(string &line) const
|
||
|
{
|
||
|
assert(tabLength > 0);
|
||
|
|
||
|
// replace leading spaces with tab indents
|
||
|
size_t newSpaceIndentLength = line.find_first_not_of(" \t");
|
||
|
size_t tabCount = newSpaceIndentLength / tabLength; // truncate extra spaces
|
||
|
line.erase(0U, tabCount * tabLength);
|
||
|
line.insert(0U, tabCount, '\t');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* indent a line by a given number of tabsets
|
||
|
* by inserting leading whitespace to the line argument.
|
||
|
*
|
||
|
* @param line a reference to the line to indent.
|
||
|
* @param indent the number of tabsets to insert.
|
||
|
* @return the number of characters inserted.
|
||
|
*/
|
||
|
int ASEnhancer::indentLine(string &line, int indent) const
|
||
|
{
|
||
|
if (line.length() == 0
|
||
|
&& ! emptyLineFill)
|
||
|
return 0;
|
||
|
|
||
|
size_t charsToInsert;
|
||
|
|
||
|
if (forceTab && indentLength != tabLength)
|
||
|
{
|
||
|
// replace tab indents with spaces
|
||
|
convertForceTabIndentToSpaces(line);
|
||
|
// insert the space indents
|
||
|
charsToInsert = indent * indentLength;
|
||
|
line.insert(0U, charsToInsert, ' ');
|
||
|
// replace leading spaces with tab indents
|
||
|
convertSpaceIndentToForceTab(line);
|
||
|
}
|
||
|
else if (useTabs)
|
||
|
{
|
||
|
charsToInsert = indent;
|
||
|
line.insert(0U, charsToInsert, '\t');
|
||
|
}
|
||
|
else // spaces
|
||
|
{
|
||
|
charsToInsert = indent * indentLength;
|
||
|
line.insert(0U, charsToInsert, ' ');
|
||
|
}
|
||
|
|
||
|
return charsToInsert;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* check for SQL "BEGIN DECLARE SECTION".
|
||
|
* must compare case insensitive and allow any spacing between words.
|
||
|
*
|
||
|
* @param line a reference to the line to indent.
|
||
|
* @param index the current line index.
|
||
|
* @return true if a hit.
|
||
|
*/
|
||
|
bool ASEnhancer::isBeginDeclareSectionSQL(string &line, size_t index) const
|
||
|
{
|
||
|
string word;
|
||
|
size_t hits = 0;
|
||
|
size_t i;
|
||
|
for (i = index; i < line.length(); i++)
|
||
|
{
|
||
|
i = line.find_first_not_of(" \t", i);
|
||
|
if (i == string::npos)
|
||
|
return false;
|
||
|
if (line[i] == ';')
|
||
|
break;
|
||
|
if (!isCharPotentialHeader(line, i))
|
||
|
continue;
|
||
|
word = getCurrentWord(line, i);
|
||
|
for (size_t j = 0; j < word.length(); j++)
|
||
|
word[j] = (char) toupper(word[j]);
|
||
|
if (word == "EXEC" || word == "SQL")
|
||
|
{
|
||
|
i += word.length() - 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (word == "DECLARE" || word == "SECTION")
|
||
|
{
|
||
|
hits++;
|
||
|
i += word.length() - 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (word == "BEGIN")
|
||
|
{
|
||
|
hits++;
|
||
|
i += word.length() - 1;
|
||
|
continue;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
if (hits == 3)
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* check for SQL "END DECLARE SECTION".
|
||
|
* must compare case insensitive and allow any spacing between words.
|
||
|
*
|
||
|
* @param line a reference to the line to indent.
|
||
|
* @param index the current line index.
|
||
|
* @return true if a hit.
|
||
|
*/
|
||
|
bool ASEnhancer::isEndDeclareSectionSQL(string &line, size_t index) const
|
||
|
{
|
||
|
string word;
|
||
|
size_t hits = 0;
|
||
|
size_t i;
|
||
|
for (i = index; i < line.length(); i++)
|
||
|
{
|
||
|
i = line.find_first_not_of(" \t", i);
|
||
|
if (i == string::npos)
|
||
|
return false;
|
||
|
if (line[i] == ';')
|
||
|
break;
|
||
|
if (!isCharPotentialHeader(line, i))
|
||
|
continue;
|
||
|
word = getCurrentWord(line, i);
|
||
|
for (size_t j = 0; j < word.length(); j++)
|
||
|
word[j] = (char) toupper(word[j]);
|
||
|
if (word == "EXEC" || word == "SQL")
|
||
|
{
|
||
|
i += word.length() - 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (word == "DECLARE" || word == "SECTION")
|
||
|
{
|
||
|
hits++;
|
||
|
i += word.length() - 1;
|
||
|
continue;
|
||
|
}
|
||
|
if (word == "END")
|
||
|
{
|
||
|
hits++;
|
||
|
i += word.length() - 1;
|
||
|
continue;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
if (hits == 3)
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* check if a one-line bracket has been reached,
|
||
|
* i.e. if the currently reached '{' character is closed
|
||
|
* with a complimentry '}' elsewhere on the current line,
|
||
|
*.
|
||
|
* @return false = one-line bracket has not been reached.
|
||
|
* true = one-line bracket has been reached.
|
||
|
*/
|
||
|
bool ASEnhancer::isOneLineBlockReached(string &line, int startChar) const
|
||
|
{
|
||
|
assert(line[startChar] == '{');
|
||
|
|
||
|
bool isInComment_ = false;
|
||
|
bool isInQuote_ = false;
|
||
|
int _bracketCount = 1;
|
||
|
int lineLength = line.length();
|
||
|
char quoteChar_ = ' ';
|
||
|
char ch = ' ';
|
||
|
|
||
|
for (int i = startChar + 1; i < lineLength; ++i)
|
||
|
{
|
||
|
ch = line[i];
|
||
|
|
||
|
if (isInComment_)
|
||
|
{
|
||
|
if (line.compare(i, 2, "*/") == 0)
|
||
|
{
|
||
|
isInComment_ = false;
|
||
|
++i;
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ch == '\\')
|
||
|
{
|
||
|
++i;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (isInQuote_)
|
||
|
{
|
||
|
if (ch == quoteChar_)
|
||
|
isInQuote_ = false;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ch == '"' || ch == '\'')
|
||
|
{
|
||
|
isInQuote_ = true;
|
||
|
quoteChar_ = ch;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (line.compare(i, 2, "//") == 0)
|
||
|
break;
|
||
|
|
||
|
if (line.compare(i, 2, "/*") == 0)
|
||
|
{
|
||
|
isInComment_ = true;
|
||
|
++i;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (ch == '{')
|
||
|
++_bracketCount;
|
||
|
else if (ch == '}')
|
||
|
--_bracketCount;
|
||
|
|
||
|
if (_bracketCount == 0)
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* process the character at the current index in a switch block.
|
||
|
*
|
||
|
* @param line a reference to the line to indent.
|
||
|
* @param index the current line index.
|
||
|
* @return the new line index.
|
||
|
*/
|
||
|
size_t ASEnhancer::processSwitchBlock(string &line, size_t index)
|
||
|
{
|
||
|
size_t i = index;
|
||
|
bool isPotentialKeyword = isCharPotentialHeader(line, i);
|
||
|
|
||
|
if (line[i] == '{')
|
||
|
{
|
||
|
sw.switchBracketCount++;
|
||
|
if (lookingForCaseBracket) // if 1st after case statement
|
||
|
{
|
||
|
sw.unindentCase = true; // unindenting this case
|
||
|
sw.unindentDepth++;
|
||
|
lookingForCaseBracket = false; // not looking now
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
lookingForCaseBracket = false; // no opening bracket, don't indent
|
||
|
|
||
|
if (line[i] == '}')
|
||
|
{
|
||
|
sw.switchBracketCount--;
|
||
|
assert(sw.switchBracketCount <= bracketCount);
|
||
|
if (sw.switchBracketCount == 0) // if end of switch statement
|
||
|
{
|
||
|
int lineUnindent = sw.unindentDepth;
|
||
|
if (line.find_first_not_of(" \t") == i
|
||
|
&& !switchStack.empty())
|
||
|
lineUnindent = switchStack[switchStack.size()-1].unindentDepth;
|
||
|
if (shouldIndentLine)
|
||
|
{
|
||
|
if (lineUnindent > 0)
|
||
|
i -= unindentLine(line, lineUnindent);
|
||
|
shouldIndentLine = false;
|
||
|
}
|
||
|
switchDepth--;
|
||
|
sw = switchStack.back();
|
||
|
switchStack.pop_back();
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
if (isPotentialKeyword
|
||
|
&& (findKeyword(line, i, "case") || findKeyword(line, i, "default")))
|
||
|
{
|
||
|
if (sw.unindentCase) // if unindented last case
|
||
|
{
|
||
|
sw.unindentCase = false; // stop unindenting previous case
|
||
|
sw.unindentDepth--;
|
||
|
}
|
||
|
|
||
|
i = findCaseColon(line, i);
|
||
|
|
||
|
i++;
|
||
|
for (; i < line.length(); i++) // bypass whitespace
|
||
|
{
|
||
|
if (!isWhiteSpace(line[i]))
|
||
|
break;
|
||
|
}
|
||
|
if (i < line.length())
|
||
|
{
|
||
|
if (line[i] == '{')
|
||
|
{
|
||
|
bracketCount++;
|
||
|
sw.switchBracketCount++;
|
||
|
if (!isOneLineBlockReached(line, i))
|
||
|
unindentNextLine = true;
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
lookingForCaseBracket = true;
|
||
|
i--; // need to process this char
|
||
|
return i;
|
||
|
}
|
||
|
if (isPotentialKeyword)
|
||
|
{
|
||
|
string name = getCurrentWord(line, i); // bypass the entire name
|
||
|
i += name.length() - 1;
|
||
|
}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* unindent a line by a given number of tabsets
|
||
|
* by erasing the leading whitespace from the line argument.
|
||
|
*
|
||
|
* @param line a reference to the line to unindent.
|
||
|
* @param unindent the number of tabsets to erase.
|
||
|
* @return the number of characters erased.
|
||
|
*/
|
||
|
int ASEnhancer::unindentLine(string &line, int unindent) const
|
||
|
{
|
||
|
size_t whitespace = line.find_first_not_of(" \t");
|
||
|
|
||
|
if (whitespace == string::npos) // if line is blank
|
||
|
whitespace = line.length(); // must remove padding, if any
|
||
|
|
||
|
if (whitespace == 0)
|
||
|
return 0;
|
||
|
|
||
|
size_t charsToErase = 0;
|
||
|
|
||
|
if (forceTab && indentLength != tabLength)
|
||
|
{
|
||
|
// replace tab indents with spaces
|
||
|
convertForceTabIndentToSpaces(line);
|
||
|
// remove the space indents
|
||
|
size_t spaceIndentLength = line.find_first_not_of(" \t");
|
||
|
charsToErase = unindent * indentLength;
|
||
|
if (charsToErase <= spaceIndentLength)
|
||
|
line.erase(0, charsToErase);
|
||
|
else
|
||
|
charsToErase = 0;
|
||
|
// replace leading spaces with tab indents
|
||
|
convertSpaceIndentToForceTab(line);
|
||
|
}
|
||
|
else if (useTabs)
|
||
|
{
|
||
|
charsToErase = unindent;
|
||
|
if (charsToErase <= whitespace)
|
||
|
line.erase(0, charsToErase);
|
||
|
else
|
||
|
charsToErase = 0;
|
||
|
}
|
||
|
else // spaces
|
||
|
{
|
||
|
charsToErase = unindent * indentLength;
|
||
|
if (charsToErase <= whitespace)
|
||
|
line.erase(0, charsToErase);
|
||
|
else
|
||
|
charsToErase = 0;
|
||
|
}
|
||
|
|
||
|
return charsToErase;
|
||
|
}
|
||
|
|
||
|
|
||
|
} // end namespace astyle
|