/src/libstaroffice/src/lib/StarObjectMath.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libstaroffice |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <cstring> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <limits> |
38 | | #include <sstream> |
39 | | |
40 | | #include <librevenge/librevenge.h> |
41 | | |
42 | | #include "STOFFFont.hxx" |
43 | | #include "STOFFListener.hxx" |
44 | | #include "STOFFParagraph.hxx" |
45 | | |
46 | | #include "StarAttribute.hxx" |
47 | | #include "StarObject.hxx" |
48 | | #include "StarItemPool.hxx" |
49 | | #include "StarState.hxx" |
50 | | #include "StarZone.hxx" |
51 | | #include "STOFFStarMathToMMLConverter.hxx" |
52 | | |
53 | | #include "StarObjectMath.hxx" |
54 | | |
55 | | /** Internal: the structures of a StarObjectMath */ |
56 | | namespace StarObjectMathInternal |
57 | | { |
58 | | //////////////////////////////////////// |
59 | | //! Internal: the state of a StarObjectMath |
60 | | struct State { |
61 | | //! constructor |
62 | | State() |
63 | 1.16k | : m_mml() |
64 | 1.16k | { |
65 | 1.16k | } |
66 | | |
67 | | //! the mml data |
68 | | librevenge::RVNGString m_mml; |
69 | | }; |
70 | | |
71 | | } |
72 | | |
73 | | //////////////////////////////////////////////////////////// |
74 | | // constructor/destructor, ... |
75 | | //////////////////////////////////////////////////////////// |
76 | | StarObjectMath::StarObjectMath(StarObject const &orig, bool duplicateState) |
77 | 1.16k | : StarObject(orig, duplicateState) |
78 | 1.16k | , m_mathState(new StarObjectMathInternal::State) |
79 | 1.16k | { |
80 | 1.16k | } |
81 | | |
82 | | StarObjectMath::~StarObjectMath() |
83 | 1.16k | { |
84 | 1.16k | } |
85 | | |
86 | | bool StarObjectMath::send(STOFFListenerPtr listener, STOFFFrameStyle const &pos, STOFFGraphicStyle const &style) |
87 | 1.16k | { |
88 | 1.16k | if (!listener || m_mathState->m_mml.empty()) { |
89 | 187 | STOFF_DEBUG_MSG(("StarObjectMath::send: oops, can not create the graphic representation\n")); |
90 | 187 | return false; |
91 | 187 | } |
92 | 980 | listener->insertEquation(pos, m_mathState->m_mml, style); |
93 | 980 | return true; |
94 | 1.16k | } |
95 | | |
96 | | //////////////////////////////////////////////////////////// |
97 | | // the parser |
98 | | //////////////////////////////////////////////////////////// |
99 | | bool StarObjectMath::parse() |
100 | 1.16k | { |
101 | 1.16k | if (!getOLEDirectory() || !getOLEDirectory()->m_input) { |
102 | 0 | STOFF_DEBUG_MSG(("StarObjectMath::parser: error, incomplete document\n")); |
103 | 0 | return false; |
104 | 0 | } |
105 | 1.16k | auto &directory=*getOLEDirectory(); |
106 | 1.16k | StarObject::parse(); |
107 | 1.16k | auto unparsedOLEs=directory.getUnparsedOles(); |
108 | 1.16k | STOFFInputStreamPtr input=directory.m_input; |
109 | 2.07k | for (auto const &name : unparsedOLEs) { |
110 | 2.07k | STOFFInputStreamPtr ole = input->getSubStreamByName(name.c_str()); |
111 | 2.07k | if (!ole.get()) { |
112 | 492 | STOFF_DEBUG_MSG(("StarObjectMath::parse: error: can not find OLE part: \"%s\"\n", name.c_str())); |
113 | 492 | continue; |
114 | 492 | } |
115 | | |
116 | 1.58k | auto pos = name.find_last_of('/'); |
117 | 1.58k | std::string base; |
118 | 1.58k | if (pos == std::string::npos) base = name; |
119 | 1.58k | else base = name.substr(pos+1); |
120 | 1.58k | ole->setReadInverted(true); |
121 | 1.58k | if (base=="StarMathDocument") { |
122 | 1.18k | readMathDocument(ole,name); |
123 | 1.18k | continue; |
124 | 1.18k | } |
125 | 392 | libstoff::DebugFile asciiFile(ole); |
126 | 392 | asciiFile.open(name); |
127 | | |
128 | 392 | libstoff::DebugStream f; |
129 | 392 | f << "Entries(" << base << "):"; |
130 | 392 | asciiFile.addPos(0); |
131 | 392 | asciiFile.addNote(f.str().c_str()); |
132 | 392 | asciiFile.reset(); |
133 | 392 | } |
134 | 1.16k | return true; |
135 | 1.16k | } |
136 | | |
137 | | bool StarObjectMath::readMathDocument(STOFFInputStreamPtr input, std::string const &fileName) |
138 | 1.18k | try |
139 | 1.18k | { |
140 | | // checkme this zone can not be encoded |
141 | 1.18k | StarZone zone(input, fileName, "MathDocument", nullptr); // use encoding RTL_TEXTENCODING_MS_1252 |
142 | 1.18k | libstoff::DebugFile &ascii=zone.ascii(); |
143 | 1.18k | ascii.open(fileName); |
144 | | |
145 | 1.18k | input->seek(0, librevenge::RVNG_SEEK_SET); |
146 | 1.18k | libstoff::DebugStream f; |
147 | 1.18k | f << "Entries(SMMathDocument):"; |
148 | | // starmath_document.cxx Try3x |
149 | 1.18k | uint32_t lIdent, lVersion; |
150 | 1.18k | *input >> lIdent; |
151 | 1.18k | if (lIdent==0x534d3330 || lIdent==0x30333034) { |
152 | 0 | input->setReadInverted(input->readInverted()); |
153 | 0 | input->seek(0, librevenge::RVNG_SEEK_SET); |
154 | 0 | *input >> lIdent; |
155 | 0 | } |
156 | 1.18k | if (lIdent!=0x30334d53L && lIdent!=0x34303330L) { |
157 | 174 | STOFF_DEBUG_MSG(("StarObjectMath::readMathDocument: find unexpected header\n")); |
158 | 174 | f << "###header"; |
159 | 174 | ascii.addPos(0); |
160 | 174 | ascii.addNote(f.str().c_str()); |
161 | 174 | return true; |
162 | 174 | } |
163 | 1.01k | *input >> lVersion; |
164 | 1.01k | f << "vers=" << std::hex << lVersion << std::dec << ","; |
165 | 1.01k | ascii.addPos(0); |
166 | 1.01k | ascii.addNote(f.str().c_str()); |
167 | 1.01k | std::vector<uint32_t> text; |
168 | 2.17k | while (!input->isEnd()) { |
169 | 2.16k | long pos=input->tell(); |
170 | 2.16k | int8_t cTag; |
171 | 2.16k | *input>>cTag; |
172 | 2.16k | f.str(""); |
173 | 2.16k | f << "SMMathDocument[" << char(cTag) << "]:"; |
174 | 2.16k | bool done=true, isEnd=false;; |
175 | 2.16k | switch (cTag) { |
176 | 424 | case 0: |
177 | 424 | isEnd=true; |
178 | 424 | break; |
179 | 1.00k | case 'T': { |
180 | 1.00k | if (!zone.readString(text)) { |
181 | 12 | done=false; |
182 | 12 | break; |
183 | 12 | } |
184 | 996 | f << libstoff::getString(text).cstr(); |
185 | 996 | librevenge::RVNGString mml; |
186 | 996 | if (STOFFStarMathToMMLConverter::convertStarMath(libstoff::getString(text), mml)) |
187 | 996 | m_mathState->m_mml=mml; |
188 | 996 | break; |
189 | 1.00k | } |
190 | 12 | case 'D': |
191 | 31 | for (int i=0; i<4; ++i) { |
192 | 27 | if (!zone.readString(text)) { |
193 | 8 | STOFF_DEBUG_MSG(("StarObjectMath::readMathDocument: can not read a string\n")); |
194 | 8 | f << "###string" << i << ","; |
195 | 8 | done=false; |
196 | 8 | break; |
197 | 8 | } |
198 | 19 | if (!text.empty()) f << "str" << i << "=" << libstoff::getString(text).cstr() << ","; |
199 | 19 | if (i==1 || i==2) { |
200 | 9 | uint32_t date, time; |
201 | 9 | *input >> date >> time; |
202 | 9 | f << "date" << i << "=" << date << ","; |
203 | 9 | f << "time" << i << "=" << time << ","; |
204 | 9 | } |
205 | 19 | } |
206 | 12 | break; |
207 | 150 | case 'F': { |
208 | | // starmath_format.cxx operator>> |
209 | 150 | uint16_t n, vLeftSpace, vRightSpace, vTopSpace, vDist, vSize; |
210 | 150 | *input>>n>>vLeftSpace>>vRightSpace; |
211 | 150 | f << "baseHeight=" << (n&0xff) << ","; |
212 | 150 | if (n&0x100) f << "isTextMode,"; |
213 | 150 | if (n&0x200) f << "bScaleNormalBracket,"; |
214 | 150 | if (vLeftSpace) f << "vLeftSpace=" << vLeftSpace << ","; |
215 | 150 | if (vRightSpace) f << "vRightSpace=" << vRightSpace << ","; |
216 | 150 | f << "size=["; |
217 | 900 | for (int i=0; i<=4; ++i) { |
218 | 750 | *input>>vSize; |
219 | 750 | f << vSize << ","; |
220 | 750 | } |
221 | 150 | f << "],"; |
222 | 150 | *input>>vTopSpace; |
223 | 150 | if (vTopSpace) f << "vTopSpace=" << vTopSpace << ","; |
224 | 150 | f << "fonts=["; |
225 | 969 | for (int i=0; i<=6; ++i) { |
226 | | // starmath_utility.cxx operator>>(..., SmFace) |
227 | 864 | uint32_t nData1, nData2, nData3, nData4; |
228 | 864 | f << "["; |
229 | 864 | if (input->isEnd() || !zone.readString(text)) { |
230 | 45 | STOFF_DEBUG_MSG(("StarObjectMath::readMathDocument: can not read a font string\n")); |
231 | 45 | f << "###string,"; |
232 | 45 | done=false; |
233 | 45 | break; |
234 | 45 | } |
235 | 819 | f << libstoff::getString(text).cstr() << ","; |
236 | 819 | *input >> nData1 >> nData2 >> nData3 >> nData4; |
237 | 819 | if (nData1) f << "familly=" << nData1 << ","; |
238 | 819 | if (nData2) f << "encoding=" << nData2 << ","; |
239 | 819 | if (nData3) f << "weight=" << nData3 << ","; |
240 | 819 | if (nData4) f << "bold=" << nData4 << ","; |
241 | 819 | f << "],"; |
242 | 819 | } |
243 | 150 | f << "],"; |
244 | 150 | if (!done) break; |
245 | 105 | if (input->tell()+21*2 > input->size()) { |
246 | 21 | STOFF_DEBUG_MSG(("StarObjectMath::readMathDocument: zone is too short\n")); |
247 | 21 | f << "###short,"; |
248 | 21 | done=false; |
249 | 21 | break; |
250 | 21 | } |
251 | 84 | f << "vDist=["; |
252 | 1.68k | for (int i=0; i<=18; ++i) { |
253 | 1.59k | *input >> vDist; |
254 | 1.59k | if (vDist) |
255 | 1.59k | f << vDist << ","; |
256 | 0 | else |
257 | 0 | f << "_,"; |
258 | 1.59k | } |
259 | 84 | f << "],"; |
260 | 84 | *input >> n >> vDist; |
261 | 84 | f << "vers=" << (n>>8) << ","; |
262 | 84 | f << "eHorAlign=" << (n&0xFF) << ","; |
263 | 84 | if (vDist) f << "bottomSpace=" << vDist << ","; |
264 | 84 | break; |
265 | 105 | } |
266 | 93 | case 'S': { |
267 | 93 | if (!zone.readString(text)) { |
268 | 14 | STOFF_DEBUG_MSG(("StarObjectMath::readMathDocument: can not read a string\n")); |
269 | 14 | f << "###string,"; |
270 | 14 | done=false; |
271 | 14 | break; |
272 | 14 | } |
273 | 79 | f << libstoff::getString(text).cstr() << ","; |
274 | 79 | uint16_t n; |
275 | 79 | *input>>n; |
276 | 79 | if (n) f << "n=" << n << ","; |
277 | 79 | break; |
278 | 93 | } |
279 | 477 | default: |
280 | 477 | STOFF_DEBUG_MSG(("StarObjectMath::readMathDocument: find unexpected type\n")); |
281 | 477 | f << "###type,"; |
282 | 477 | done=false; |
283 | 477 | break; |
284 | 2.16k | } |
285 | 2.16k | ascii.addPos(pos); |
286 | 2.16k | ascii.addNote(f.str().c_str()); |
287 | 2.16k | if (!done) { |
288 | 577 | ascii.addDelimiter(input->tell(),'|'); |
289 | 577 | break; |
290 | 577 | } |
291 | 1.58k | if (isEnd) |
292 | 424 | break; |
293 | 1.58k | } |
294 | 1.01k | return true; |
295 | 1.01k | } |
296 | 1.18k | catch (...) |
297 | 1.18k | { |
298 | 0 | return false; |
299 | 0 | } |
300 | | |
301 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |