/***************************************************************************
PreFormatter.cpp - description
-------------------
begin : Mo Jan 03 2005
copyright : (C) 2005-2026 by Andre Simon
email : a.simon@mailbox.org
***************************************************************************/
/*
This file is part of Highlight.
Highlight 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 3 of the License, or
(at your option) any later version.
Highlight 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 Highlight. If not, see <http://www.gnu.org/licenses/>.
*/
#include "preformatter.h"
#include <iostream>
#include "stringtools.h"
using std::string;
namespace highlight
{
const std::string PreFormatter::LB_CHARS = " \t[](){}-+<>.:,;";
const std::string PreFormatter::WS_CHARS = " \n\r\t";
const std::string PreFormatter::INDENT_MARKERS = "{(=";
PreFormatter::PreFormatter() :
wsPrefixLength ( string::npos )
{
}
PreFormatter::~PreFormatter()
{
}
bool PreFormatter::hasMoreLines()
{
return hasMore;
}
bool PreFormatter::indentCode()
{
return indentAfterOpenBraces;
}
void PreFormatter::setLine ( const std::string& newLine )
{
line=newLine;
if ( replaceTabs && numberSpaces ) {
size_t tabPos=line.find ( '\t' );
while ( tabPos!=string::npos ) {
line.replace ( tabPos , 1, numberSpaces - ( tabPos % numberSpaces ) , ' ' );
tabPos = line.find ( '\t', tabPos+1 );
}
}
if ( wrapLines ) {
wsPrefix.clear();
index=0;
wsPrefixLength=string::npos;
hasMore=true;
redefineWsPrefix=false;
}
}
std::string PreFormatter::getNextLine()
{
if ( !wrapLines ) {
hasMore = false;
return line;
}
++lineNumber;
if ( !index && line.length() > maxLineLength ) { // erster Durchlauf...
// wenn moeglich an oeffnender Klammer oder Geichheitszeichen ausrichten
if ( indentAfterOpenBraces ) {
wsPrefixLength=line.find_first_of ( INDENT_MARKERS );
}
// sonst die Einrckung der Originalzeile beibehalten
if ( wsPrefixLength==string::npos || wsPrefixLength-index>maxLineLength ) {
wsPrefixLength=line.find_first_not_of ( WS_CHARS );
} else {
// wsPrefix in allen neu umgebrochenen Zeilen durch Spaces ersetzen
redefineWsPrefix=true;
// Position hinter oeffnende Klammer springen
wsPrefixLength=line.find_first_not_of ( WS_CHARS,wsPrefixLength+1 );
}
if ( wsPrefixLength!=string::npos ) {
index = wsPrefixLength;
// Falls Anzahl der Whitespaces am Beginn der ersten Zeile groesser
// als Max. Zeilenlaenge, Whitespaces verwerfen
if ( wsPrefixLength>maxLineLength ) {
wsPrefixLength=0;
return string();
} else {
wsPrefix=line.substr ( 0, wsPrefixLength );
}
}
// Zeile enthaelt nur Whitespace; verwerfen
else {
hasMore= false;
return string();
}
} else {
if ( redefineWsPrefix ) {
wsPrefix.clear();
wsPrefix.append ( wsPrefixLength, ' ' );
}
redefineWsPrefix=false;
}
string resultString;
// Position, ab der rueckwaerts nach Umbruchmglichkeit gesucht wird
unsigned int searchEndPos = maxLineLength - wsPrefixLength;
// letztes Teilstueck der Zeile ausgeben; Parsen beenden
if ( line.length()-index < searchEndPos ) {
hasMore=false;
resultString= ( index>0 ) ? wsPrefix + line.substr ( index ) : line.substr ( index );
return resultString;
}
// Umbrechposition suchen
size_t lbPos = line.find_last_of ( LB_CHARS, index+searchEndPos );
if ( lbPos <= index || lbPos == string::npos ) {
// nichts gefunden, hart umbrechen
lbPos = index + searchEndPos;
}
// Einrckung der Originalzeile erhalten
resultString+=wsPrefix;
// Neue Zeile erzeugen
resultString += line.substr ( index, lbPos-index+1 );
// Whitespace am neuen Zeilenbeginn ignorieren, ausser beim ersten Durchlauf
size_t newIndex=line.find_first_not_of ( WS_CHARS, lbPos+1 );
index= ( newIndex!=string::npos ) ?newIndex:line.length();
hasMore=index!=line.length(); // unnoetigen Leerstring vermeiden
if ( hasMore ) wrappedLines.insert ( lineNumber ); // diese Zeile wurde umgebrochen
return resultString;
}
void PreFormatter::setWrapLineLength ( unsigned int maxLineLength )
{
this->maxLineLength = maxLineLength;
}
void PreFormatter::setWrapIndentBraces ( bool indentAfterOpenBraces )
{
this->indentAfterOpenBraces = indentAfterOpenBraces;
}
void PreFormatter::setNumberSpaces ( unsigned int num )
{
numberSpaces = num;
}
}