1 /***************************************************************************
2 TexGenerator.cpp - description
3 -------------------
4 begin : Mit Jul 24 2002
5 copyright : (C) 2002-2021 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 <sstream>
29
30 #include "charcodes.h"
31 #include "version.h"
32 #include "texgenerator.h"
33
34 namespace highlight
35 {
36
TexGenerator()37 TexGenerator::TexGenerator()
38 : CodeGenerator ( TEX )
39 {
40 /*This makes TeX to use every par it encounters (the \\leavevmode has
41 no effect when TeX is in horizontal mode and when TeX is in vertical
42 mode, it switches it to horizontal mode).*/
43 newLineTag="\\leavevmode\\par\n";
44
45 spacer = initialSpacer = "\\ ";
46 maskWs=true;
47 excludeWs=true;
48 maskWsBegin = "{\\hl"+STY_NAME_STD;
49 maskWsEnd = "}";
50 styleCommentOpen="%";
51 }
52
~TexGenerator()53 TexGenerator::~TexGenerator()
54 {}
55
initOutputTags()56 void TexGenerator::initOutputTags()
57 {
58 openTags.push_back ( "{\\hl"+STY_NAME_STD+" " );
59 openTags.push_back ( "{\\hl"+STY_NAME_STR+" " );
60 openTags.push_back ( "{\\hl"+STY_NAME_NUM+" " );
61 openTags.push_back ( "{\\hl"+STY_NAME_SLC+" " );
62 openTags.push_back ( "{\\hl"+STY_NAME_COM+" " );
63 openTags.push_back ( "{\\hl"+STY_NAME_ESC+" " );
64 openTags.push_back ( "{\\hl"+STY_NAME_DIR+" " );
65 openTags.push_back ( "{\\hl"+STY_NAME_DST+" " );
66 openTags.push_back ( "{\\hl"+STY_NAME_LIN+" " );
67 openTags.push_back ( "{\\hl"+STY_NAME_SYM+" " );
68 openTags.push_back ( "{\\hl"+STY_NAME_IPL+" " );
69
70 openTags.push_back ( "{\\hl"+STY_NAME_ERR+" " );
71 openTags.push_back ( "{\\hl"+STY_NAME_ERM+" " );
72
73 for (unsigned int i=0; i<NUMBER_BUILTIN_STATES; i++ ) {
74 closeTags.push_back ( "}" );
75 }
76 }
77
getAttributes(const string & elemName,const ElementStyle & elem)78 string TexGenerator::getAttributes ( const string & elemName,const ElementStyle & elem )
79 {
80 ostringstream s;
81
82 s << "\\def\\hl"
83 << elemName
84 << "{";
85
86 if (!elem.getCustomOverride()) {
87
88 if ( elem.isBold() ) s << "\\bf";
89 if ( elem.isItalic() ) s << "\\it";
90 s << "\\textColor{"
91 << ( elem.getColour().getRed ( TEX ) ) <<" "
92 << ( elem.getColour().getGreen ( TEX ) ) <<" "
93 << ( elem.getColour().getBlue ( TEX ) ) <<" 0.0}";
94 }
95
96 string customStyle(elem.getCustomStyle());
97
98 if (!customStyle.empty()) {
99 s << customStyle;
100 }
101
102 s << "}\n";
103
104 return s.str();
105 }
106
getHeader()107 string TexGenerator::getHeader()
108 {
109 ostringstream os;
110 os << styleCommentOpen
111 << " Document title: " << docTitle << "\n\n";
112 if ( currentSyntax->highlightingEnabled() ) {
113 if ( includeStyleDef ) {
114 os << getStyleDefinition();
115 os << CodeGenerator::readUserStyleDef();
116 } else {
117 os << "\\input "
118 << getStyleOutputPath()
119 << "\n\n";
120 }
121 }
122
123 return os.str();
124 }
125
printBody()126 void TexGenerator::printBody()
127 {
128 *out << "{\n\\"<<getBaseFont() <<"\n";
129
130 processRootState();
131
132 *out << "}\n";
133 }
134
getFooter()135 string TexGenerator::getFooter()
136 {
137 ostringstream os;
138 os << "\\bye\n";
139
140 if (!omitVersionComment) {
141 os << "% TeX generated by Highlight "
142 << highlight::Info::getVersion()
143 << ", "
144 << highlight::Info::getWebsite() << "\n";
145 }
146 return os.str();
147 }
148
maskCharacter(unsigned char c)149 string TexGenerator:: maskCharacter ( unsigned char c )
150 {
151 switch ( c ) {
152 case '{':
153 case '}': {
154 string m ( "$\\" );
155 m += c;
156 m += '$';
157 return m;
158 }
159 break;
160 case '^':
161 return "{\\bf\\^{}}";
162 break;
163 case '_':
164 // return "\\_{}";
165 // break;
166 case '&':
167 case '$':
168 case '#':
169 case '%': {
170 string m ( "\\" );
171 m += c;
172 m += "{}";
173 return m;
174 }
175 break;
176 case '\\':
177 return "$\\backslash$";
178 break;
179 case ' ':
180 return spacer;
181 break;
182 case '+':
183 case '-':
184 case '<':
185 case '>':
186 case '=': {
187 string m ( "$\\mathord{" );
188 m += c;
189 m += "}$";
190 return m;
191 }
192 break;
193 case AUML_LC:
194 return "\\\"a";
195 break;
196 case OUML_LC:
197 return "\\\"o";
198 break;
199 case UUML_LC:
200 return "\\\"u";
201 break;
202 case AUML_UC:
203 return "\\\"A";
204 break;
205 case OUML_UC:
206 return "\\\"O";
207 break;
208 case UUML_UC:
209 return "\\\"U";
210 break;
211 case AACUTE_LC:
212 return "\\'a";
213 break;
214 case EACUTE_LC:
215 return "\\'e";
216 break;
217 case OACUTE_LC:
218 return "\\'o";
219 break;
220 case UACUTE_LC:
221 return "\\'u";
222 break;
223 case AGRAVE_LC:
224 return "\\`a";
225 break;
226 case EGRAVE_LC:
227 return "\\`e";
228 break;
229 case OGRAVE_LC:
230 return "\\`o";
231 break;
232 case UGRAVE_LC:
233 return "\\`u";
234 break;
235 case AACUTE_UC:
236 return "\\'A";
237 break;
238 case EACUTE_UC:
239 return "\\'E";
240 break;
241 case OACUTE_UC:
242 return "\\'O";
243 break;
244 case UACUTE_UC:
245 return "\\'U";
246 break;
247 case AGRAVE_UC:
248 return "\\`A";
249 break;
250 case EGRAVE_UC:
251 return "\\`E";
252 break;
253 case UGRAVE_UC:
254 return "\\`O";
255 break;
256 case OGRAVE_UC:
257 return "\\`U";
258 break;
259 case SZLIG:
260 return "\\ss ";
261 break;
262
263 default :
264 return string ( 1, c );
265 }
266 }
267
getKeywordOpenTag(unsigned int styleID)268 string TexGenerator::getKeywordOpenTag ( unsigned int styleID )
269 {
270 return "{\\hl"+currentSyntax->getKeywordClasses() [styleID]+" ";
271 }
272
getKeywordCloseTag(unsigned int styleID)273 string TexGenerator::getKeywordCloseTag ( unsigned int styleID )
274 {
275 return "}";
276 }
277
278
getStyleDefinition()279 string TexGenerator::getStyleDefinition()
280 {
281 if ( disableStyleCache || styleDefinitionCache.empty() ) {
282 ostringstream os;
283 os << "% highlight theme: "<<docStyle.getDescription()<<"\n";
284 os << getAttributes ( STY_NAME_STD, docStyle.getDefaultStyle() );
285 os << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() );
286 os << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() );
287 os << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() );
288 os << getAttributes ( STY_NAME_DST, docStyle.getPreProcStringStyle() );
289 os << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() );
290 os << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() );
291 os << getAttributes ( STY_NAME_DIR, docStyle.getPreProcessorStyle() );
292 os << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() );
293 os << getAttributes ( STY_NAME_SYM, docStyle.getOperatorStyle() );
294 os << getAttributes ( STY_NAME_IPL, docStyle.getInterpolationStyle() );
295
296 os << getAttributes ( STY_NAME_ERR, docStyle.getErrorStyle() );
297 os << getAttributes ( STY_NAME_ERM, docStyle.getErrorMessageStyle() );
298
299 KeywordStyles styles = docStyle.getKeywordStyles();
300 for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) {
301 os << getAttributes ( it->first, it->second );
302 }
303
304 os << "% The special option is not supported by all dvi drivers\n"
305 << "\\special{background rgb "
306 << docStyle.getBgColour().getRed ( LATEX ) << " "
307 << docStyle.getBgColour().getGreen ( LATEX ) << " "
308 << docStyle.getBgColour().getBlue ( LATEX ) << "}";
309 os << "\n\\nopagenumbers\n"
310 << "\\input colordvi\n";
311 styleDefinitionCache=os.str();
312 }
313 return styleDefinitionCache;
314 }
315
316 }
317