1 /***************************************************************************
2                         PreFormatter.cpp  -  description
3                              -------------------
4     begin                : Mo Jan 03 2005
5     copyright            : (C) 2005-2007 by Andre Simon
6     email                : a.simon@mailbox.org
7  ***************************************************************************/
8 
9 
10 /*
11 This file is part of Highlight.
12 
13 Highlight is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17 
18 Highlight is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with Highlight.  If not, see <http://www.gnu.org/licenses/>.
25 */
26 
27 
28 #include "preformatter.h"
29 
30 #include <iostream>
31 #include "stringtools.h"
32 
33 namespace ansifilter
34 {
35 
36 const std::string PreFormatter::LB_CHARS = " \t[](){}-+<>.:,;";
37 const std::string PreFormatter::WS_CHARS = " \n\r\t";
38 const std::string PreFormatter::INDENT_MARKERS = "{(=";
39 
PreFormatter()40 PreFormatter::PreFormatter() :
41     maxLineLength ( 80 ),
42     index ( 0 ),
43     numberSpaces ( 0 ),
44     lineNumber ( 0 ),
45     wsPrefixLength ( string::npos ),
46     hasMore ( false ),
47     indentAfterOpenBraces ( true ),
48     redefineWsPrefix ( false ),
49     wrapLines ( false ),
50     replaceTabs ( false )
51 {
52 }
53 
~PreFormatter()54 PreFormatter::~PreFormatter()
55 {
56 }
57 
hasMoreLines()58 bool PreFormatter::hasMoreLines()
59 {
60     return hasMore;
61 }
62 
indentCode()63 bool PreFormatter::indentCode()
64 {
65     return indentAfterOpenBraces;
66 }
67 
setLine(const std::string & newLine)68 void PreFormatter::setLine ( const std::string& newLine )
69 {
70 
71     line=newLine;
72 
73     if ( replaceTabs && numberSpaces ) {
74         size_t tabPos=line.find ( '\t' );
75         while ( tabPos!=string::npos ) {
76             line.replace ( tabPos , 1, numberSpaces - ( tabPos % numberSpaces ) , ' ' );
77             tabPos = line.find ( '\t', tabPos+1 );
78         }
79     }
80 
81     if ( wrapLines ) {
82         wsPrefix.clear();
83         index=0;
84         wsPrefixLength=string::npos;
85         hasMore=true;
86         redefineWsPrefix=false;
87     }
88 }
89 
getNextLine()90 std::string PreFormatter::getNextLine()
91 {
92 
93     if ( !wrapLines ) {
94         hasMore = false;
95         return line;
96     }
97 
98     ++lineNumber;
99 
100     if ( !index && line.length() > maxLineLength ) { // erster Durchlauf...
101         // wenn moeglich an oeffnender Klammer oder Geichheitszeichen ausrichten
102         if ( indentAfterOpenBraces ) {
103             wsPrefixLength=line.find_first_of ( INDENT_MARKERS );
104         }
105         // sonst die Einrckung der Originalzeile beibehalten
106         if ( wsPrefixLength==string::npos || wsPrefixLength-index>maxLineLength ) {
107             wsPrefixLength=line.find_first_not_of ( WS_CHARS );
108         } else {
109             // wsPrefix in allen neu umgebrochenen Zeilen durch Spaces ersetzen
110             redefineWsPrefix=true;
111             //  Position hinter oeffnende Klammer springen
112             wsPrefixLength=line.find_first_not_of ( WS_CHARS,wsPrefixLength+1 );
113         }
114 
115         if ( wsPrefixLength!=string::npos ) {
116             index = wsPrefixLength;
117             // Falls Anzahl der Whitespaces am beginn der ersten zeile groesser
118             // als Max. Zeilenlaenge, Whitespaces verwerfen
119             if ( wsPrefixLength>maxLineLength ) {
120                 wsPrefixLength=0;
121                 return string();
122             } else {
123                 wsPrefix=line.substr ( 0, wsPrefixLength );
124             }
125         }
126         // Zeile enthaelt nur Whitespace; verwerfen
127         else {
128             hasMore= false;
129             return string();
130         }
131     } else {
132         if ( redefineWsPrefix ) {
133             wsPrefix.clear();
134             wsPrefix.append ( wsPrefixLength, ' ' );
135         }
136         redefineWsPrefix=false;
137     }
138 
139     string resultString;
140 
141     // Position, ab der rueckwaerts nach Umbruchmglichkeit gesucht wird
142     unsigned int searchEndPos = maxLineLength - wsPrefixLength;
143 
144     // letztes Teilstueck der Zeile ausgeben; Parsen beenden
145     if ( line.length()-index < searchEndPos ) {
146         hasMore=false;
147         resultString= ( index>0 ) ? wsPrefix + line.substr ( index ) : line.substr ( index );
148         return resultString;
149     }
150 
151     // Umbrechposition suchen
152     size_t lbPos = line.find_last_of ( LB_CHARS, index+searchEndPos );
153     if ( lbPos <= index || lbPos == string::npos ) {
154         // nichts gefunden, hart umbrechen
155         lbPos = index + searchEndPos;
156     }
157     // Einrckung der Originalzeile erhalten
158     resultString+=wsPrefix;
159     // Neue Zeile erzeugen
160     resultString += line.substr ( index, lbPos-index+1 );
161 
162     // Whitespace am neuen Zeilenbeginn ignorieren, ausser beim ersten Durchlauf
163     size_t newIndex=line.find_first_not_of ( WS_CHARS, lbPos+1 );
164     index= ( newIndex!=string::npos ) ?newIndex:line.length();
165 
166     hasMore=index!=line.length(); // unnoetigen Leerstring vermeiden
167 
168     if ( hasMore ) wrappedLines.insert ( lineNumber ); // diese Zeile wurde umgebrochen
169 
170     return resultString;
171 }
172 
setWrapLineLength(unsigned int maxLineLength)173 void PreFormatter::setWrapLineLength ( unsigned int maxLineLength )
174 {
175     this->maxLineLength = maxLineLength;
176 }
setWrapIndentBraces(bool indentAfterOpenBraces)177 void PreFormatter::setWrapIndentBraces ( bool indentAfterOpenBraces )
178 {
179     this->indentAfterOpenBraces = indentAfterOpenBraces;
180 }
181 
setNumberSpaces(unsigned int num)182 void PreFormatter::setNumberSpaces ( unsigned int num )
183 {
184     numberSpaces = num;
185 }
186 
187 }
188