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