Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: