1 /***************************************************************************
2                     odtgenerator.cpp  -  description
3                              -------------------
4     begin                : Jul 19 2012
5     copyright            : (C) 2012-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 #include <sstream>
28 #include "odtgenerator.h"
29 
30 namespace highlight
31 {
32 
ODTGenerator()33 ODTGenerator::ODTGenerator() : CodeGenerator ( ODTFLAT )
34 {
35     newLineTag = "</text:p>\n<text:p text:style-name=\"Standard\">";
36     spacer = initialSpacer = "<text:s text:c=\"1\"/>";
37     maskWs=true;
38     if ( !preFormatter.getReplaceTabs()) { // TODO use <text:tab/>
39 
40         preFormatter.setReplaceTabs ( true );
41         preFormatter.setNumberSpaces ( 4 );
42     }
43 }
44 
~ODTGenerator()45 ODTGenerator::~ODTGenerator() {}
46 
getStyleDefinition()47 string ODTGenerator::getStyleDefinition()
48 {
49     if ( disableStyleCache || styleDefinitionCache.empty() ) {
50         ostringstream os;
51 
52         os  << "<office:styles>\n<style:style style:name=\"Standard\" style:family=\"paragraph\" style:class=\"text\">\n"
53             << "  <style:text-properties style:font-name=\""<< getBaseFont()<<"\" fo:font-size=\""<<getBaseFontSize()<<"pt\"/>"
54             << "</style:style>\n</office:styles>"
55             << "<office:automatic-styles>\n";
56 
57         os << getAttributes ( STY_NAME_STD, docStyle.getDefaultStyle() )
58            << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() )
59            << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() )
60            << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() )
61            << getAttributes ( STY_NAME_DST, docStyle.getPreProcStringStyle() )
62            << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() )
63            << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() )
64            << getAttributes ( STY_NAME_DIR, docStyle.getPreProcessorStyle() )
65            << getAttributes ( STY_NAME_SYM, docStyle.getOperatorStyle() )
66            << getAttributes ( STY_NAME_IPL, docStyle.getInterpolationStyle() )
67            << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() )
68            << getAttributes ( STY_NAME_ERR, docStyle.getErrorStyle() )
69            << getAttributes ( STY_NAME_ERM, docStyle.getErrorMessageStyle() );
70 
71         KeywordStyles styles = docStyle.getKeywordStyles();
72         for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) {
73             os << getAttributes (it->first, it->second );
74         }
75 
76         os << "<style:page-layout style:name=\"pm1\">"
77            << "<style:page-layout-properties fo:page-width=\"21.001cm\" fo:page-height=\"29.7cm\" style:num-format=\"1\""
78            << " style:print-orientation=\"portrait\" fo:margin=\"2cm\" fo:margin-top=\"2cm\" fo:margin-bottom=\"2cm\" fo:margin-left=\"2cm\" fo:margin-right=\"2cm\" "
79            << "fo:background-color=\"#"
80            << ( docStyle.getBgColour().getRed ( HTML ) )
81            << ( docStyle.getBgColour().getGreen ( HTML ) )
82            << ( docStyle.getBgColour().getBlue ( HTML ) )
83            << "\" style:writing-mode=\"lr-tb\" style:footnote-max-height=\"0cm\">\n"
84            << " <style:background-image/>\n"
85            << " <style:footnote-sep style:width=\"0.018cm\" style:distance-before-sep=\"0.101cm\" style:distance-after-sep=\"0.101cm\" style:line-style=\"solid\""
86            << " style:adjustment=\"left\" style:rel-width=\"25%\" style:color=\"#000000\"/>"
87            << "</style:page-layout-properties>\n"
88            << "<style:header-style/>\n"
89            << "<style:footer-style/>\n"
90            << "</style:page-layout>\n"
91            << "</office:automatic-styles>\n"
92            << "<office:master-styles>\n"
93            << " <style:master-page style:name=\"Standard\" style:page-layout-name=\"pm1\"/>\n"
94            << "</office:master-styles>\n";
95 
96         styleDefinitionCache=os.str();
97     }
98     return styleDefinitionCache;
99 }
100 
getAttributes(const string & elemName,const ElementStyle & elem)101 string ODTGenerator::getAttributes ( const string & elemName,
102                                      const ElementStyle & elem )
103 {
104     ostringstream s;
105     s << "<style:style style:name=\""<<elemName<<"\" style:family=\"text\">\n"
106       << "<style:text-properties fo:color=\"#"
107       << ( elem.getColour().getRed ( HTML ) )
108       << ( elem.getColour().getGreen ( HTML ) )
109       << ( elem.getColour().getBlue ( HTML ) )
110       << "\""
111       << ( elem.isBold() ?     " fo:font-weight=\"bold\"" :"" )
112       << ( elem.isItalic() ?   " fo:font-style=\"italic\"" :"" )
113       << ( elem.isUnderline() ? " style:text-underline-style=\"solid\" style:text-underline-width=\"auto\" style:text-underline-color=\"font-color\"" :"" )
114       <<"/>\n</style:style>\n" ;
115 
116     return s.str();
117 }
118 
getHeader()119 string ODTGenerator::getHeader()
120 {
121       string enc = "UTF-8";
122      if ( encodingDefined() ) {
123         enc = encoding;
124     }
125     ostringstream header;
126     header << "<?xml version=\"1.0\" encoding=\""<<enc<<"\"?>\n"\
127            "<office:document xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\""\
128            " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\""\
129            " xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\""\
130            " xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\""\
131            " xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\""\
132            " xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\" xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\""\
133            " xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\" xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\""\
134            " xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\" xmlns:ooo=\"http://openoffice.org/2004/office\" xmlns:ooow=\"http://openoffice.org/2004/writer\""\
135            " xmlns:oooc=\"http://openoffice.org/2004/calc\" xmlns:dom=\"http://www.w3.org/2001/xml-events\" xmlns:xforms=\"http://www.w3.org/2002/xforms\""\
136            " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:rpt=\"http://openoffice.org/2005/report\""\
137            " xmlns:of=\"urn:oasis:names:tc:opendocument:xmlns:of:1.2\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" xmlns:grddl=\"http://www.w3.org/2003/g/data-view#\""\
138            " xmlns:tableooo=\"http://openoffice.org/2009/table\" xmlns:field=\"urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0\""\
139            " xmlns:formx=\"urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0\" xmlns:css3t=\"http://www.w3.org/TR/css3-text/\" office:version=\"1.2\""\
140            " office:mimetype=\"application/vnd.oasis.opendocument.text\">\n"\
141            " <office:font-face-decls>\n"\
142            "  <style:font-face style:name=\""<< getBaseFont()<<"\" svg:font-family=\""<< getBaseFont()<<"\" style:font-family-generic=\"modern\" style:font-pitch=\"fixed\"/>\n"\
143            " </office:font-face-decls>\n";
144 
145     header << getStyleDefinition();
146 
147     header  << " <office:body>\n"
148             << "  <office:text>\n"
149             << "<text:p text:style-name=\"Standard\">";
150 
151     return header.str();
152 }
153 
printBody()154 void ODTGenerator::printBody()
155 {
156     processRootState();
157 }
158 
getFooter()159 string ODTGenerator::getFooter()
160 {
161     return "</text:p>\n  </office:text>\n </office:body>\n</office:document>";
162 }
163 
getOpenTag(const string & styleName)164 string  ODTGenerator::getOpenTag ( const string& styleName )
165 {
166     return "<text:span text:style-name=\""+styleName+"\">";
167 }
168 
initOutputTags()169 void ODTGenerator::initOutputTags ()
170 {
171     openTags.push_back ( "" );
172     openTags.push_back ( getOpenTag ( STY_NAME_STR ) );
173     openTags.push_back ( getOpenTag ( STY_NAME_NUM ) );
174     openTags.push_back ( getOpenTag ( STY_NAME_SLC ) );
175     openTags.push_back ( getOpenTag ( STY_NAME_COM ) );
176     openTags.push_back ( getOpenTag ( STY_NAME_ESC ) );
177     openTags.push_back ( getOpenTag ( STY_NAME_DIR ) );
178     openTags.push_back ( getOpenTag ( STY_NAME_DST ) );
179     openTags.push_back ( getOpenTag ( STY_NAME_LIN ) );
180     openTags.push_back ( getOpenTag ( STY_NAME_SYM ) );
181     openTags.push_back ( getOpenTag ( STY_NAME_IPL ) );
182 
183     openTags.push_back ( getOpenTag ( STY_NAME_ERR ) );
184     openTags.push_back ( getOpenTag ( STY_NAME_ERM ) );
185     closeTags.push_back ( "" );
186     for (unsigned int i=1; i<NUMBER_BUILTIN_STATES; i++ ) {
187         closeTags.push_back ( "</text:span>" );
188     }
189 
190 }
191 
maskCharacter(unsigned char c)192 string ODTGenerator::maskCharacter ( unsigned char c )
193 {
194     switch ( c ) {
195     case '<' :
196         return "&lt;";
197         break;
198     case '>' :
199         return "&gt;";
200         break;
201     case '&' :
202         return "&amp;";
203         break;
204     case '\"' :
205         return "&quot;";
206         break;
207     case ' ':
208         return spacer;
209         break;
210     //	case '\t':
211     //		return "<text:tab/>";
212     //		break;
213     default:
214         return string ( 1, c );
215     }
216 }
217 
getKeywordOpenTag(unsigned int styleID)218 string ODTGenerator::getKeywordOpenTag ( unsigned int styleID )
219 {
220     return getOpenTag ( currentSyntax->getKeywordClasses() [styleID] );
221 }
222 
getKeywordCloseTag(unsigned int styleID)223 string ODTGenerator::getKeywordCloseTag ( unsigned int styleID )
224 {
225     return "</text:span>";
226 }
227 
228 }
229