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