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 "<";
197 break;
198 case '>' :
199 return ">";
200 break;
201 case '&' :
202 return "&";
203 break;
204 case '\"' :
205 return """;
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