LibreOffice Module lotuswordpro (master) 1
lwptblformula.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * The Contents of this file are made available subject to the terms of
5 * either of the following licenses
6 *
7 * - GNU Lesser General Public License Version 2.1
8 * - Sun Industry Standards Source License Version 1.1
9 *
10 * Sun Microsystems Inc., October, 2000
11 *
12 * GNU Lesser General Public License Version 2.1
13 * =============================================
14 * Copyright 2000 by Sun Microsystems, Inc.
15 * 901 San Antonio Road, Palo Alto, CA 94303, USA
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License version 2.1, as published by the Free Software Foundation.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 * MA 02111-1307 USA
30 *
31 *
32 * Sun Industry Standards Source License Version 1.1
33 * =================================================
34 * The contents of this file are subject to the Sun Industry Standards
35 * Source License Version 1.1 (the "License"); You may not use this file
36 * except in compliance with the License. You may obtain a copy of the
37 * License at http://www.openoffice.org/license.html.
38 *
39 * Software provided under this License is provided on an "AS IS" basis,
40 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 * See the License for the specific provisions governing your rights and
44 * obligations concerning the Software.
45 *
46 * The Initial Developer of the Original Code is: IBM Corporation
47 *
48 * Copyright: 2008 by IBM Corporation
49 *
50 * All Rights Reserved.
51 *
52 * Contributor(s): _______________________________________
53 *
54 *
55 ************************************************************************/
61#include "lwptblcell.hxx"
62#include "lwppara.hxx"
63#include "lwptblformula.hxx"
64
65#include "lwptablelayout.hxx"
66#include <osl/thread.h>
67#include <rtl/ustrbuf.hxx>
68#include <sal/log.hxx>
69#include <memory>
70#include <utility>
71
73{
74}
75
77 : LwpCellList(objHdr, pStrm)
78 , m_bSupported(true)
79 , m_nFormulaRow(0)
80{}
81
83{
84}
85
87{
88 double Constant = m_pObjStrm->QuickReadDouble();
89
90 m_aStack.push_back( std::make_unique<LwpFormulaConst>(Constant) );
91}
92
97{
98 m_pObjStrm->QuickReadInt16(); //Disk Size
99 sal_uInt16 nStrLen = m_pObjStrm->QuickReadInt16();
100
101 std::vector<char> aBuf(nStrLen + 1);
102 m_pObjStrm->QuickRead(aBuf.data(), nStrLen);
103 aBuf[nStrLen]= '\0';
104 OUString aText = "\"" +
105 OUString(aBuf.data(), nStrLen, osl_getThreadTextEncoding()) +
106 "\"";
107
108 m_aStack.push_back(std::make_unique<LwpFormulaText>(aText));
109}
110
112{
113 LwpRowSpecifier RowSpecifier;
114 LwpColumnSpecifier ColumnSpecifier;
115
116 RowSpecifier.QuickRead(m_pObjStrm.get());
117 ColumnSpecifier.QuickRead(m_pObjStrm.get());
118
119 m_aStack.push_back( std::make_unique<LwpFormulaCellAddr>(ColumnSpecifier.ColumnID(cColumn),
120 RowSpecifier.RowID(m_nFormulaRow)) );
121}
122
124{
125 ReadCellID( ); // start
126 std::unique_ptr<LwpFormulaCellAddr> pStartCellAddr( static_cast<LwpFormulaCellAddr*>(m_aStack.back().release()));
127 m_aStack.pop_back();
128
129 ReadCellID(); // end
130 std::unique_ptr<LwpFormulaCellAddr> pEndCellAddr(static_cast<LwpFormulaCellAddr*>(m_aStack.back().release()));
131 m_aStack.pop_back();
132
133 m_aStack.push_back( std::make_unique<LwpFormulaCellRangeAddr>(pStartCellAddr->GetCol(),
134 pStartCellAddr->GetRow(),
135 pEndCellAddr->GetCol(),
136 pEndCellAddr->GetRow()) );
137}
138
143{
144 sal_uInt16 TokenType, DiskLength;
145
146 /* Read the compiled expression length */
147 m_pObjStrm->SeekRel(2);
148
149 bool bError = false;
150 while ((TokenType = m_pObjStrm->QuickReaduInt16(&bError)) != TK_END)
151 {
152
153 if (bError)
154 throw std::runtime_error("error reading expression");
155
156 // Get the disk length of this token
157 DiskLength = m_pObjStrm->QuickReaduInt16();
158
159 switch (TokenType)
160 {
161 case TK_CONSTANT:
162 {
163 ReadConst();
164 break;
165 }
166
167 case TK_CELLID:
168 ReadCellID();
169 break;
170
171 case TK_CELLRANGE:
173 break;
174
175 case TK_SUM:
176 case TK_IF:
177 case TK_COUNT:
178 case TK_MINIMUM:
179 case TK_MAXIMUM:
180 case TK_AVERAGE:
181 {
182 std::unique_ptr<LwpFormulaFunc> xFunc(new LwpFormulaFunc(TokenType));
183 ReadArguments(*xFunc);
184 m_aStack.push_back(std::move(xFunc));
185 }
186 break;
187
188 case TK_ADD://7
189 case TK_SUBTRACT:
190 case TK_MULTIPLY:
191 case TK_DIVIDE:
192 case TK_LESS:
193 case TK_LESS_OR_EQUAL:
194 case TK_GREATER:
196 case TK_EQUAL:
197 case TK_NOT_EQUAL:
198 case TK_AND:
199 case TK_OR:
200 case TK_NOT:
201 m_pObjStrm->SeekRel(DiskLength); // extensible for future
202
203 if (m_aStack.size() >= 2)
204 {//binary operator
205 std::unique_ptr<LwpFormulaOp> pOp(new LwpFormulaOp(TokenType));
206 pOp->AddArg(std::move(m_aStack.back())); m_aStack.pop_back();
207 pOp->AddArg(std::move(m_aStack.back())); m_aStack.pop_back();
208 m_aStack.push_back(std::move(pOp));
209 }
210 break;
211 case TK_UNARY_MINUS:
212 if (!m_aStack.empty())
213 {
214 std::unique_ptr<LwpFormulaUnaryOp> pOp(new LwpFormulaUnaryOp(TokenType));
215 pOp->AddArg(std::move(m_aStack.back())); m_aStack.pop_back();
216 m_aStack.push_back(std::move(pOp));
217 }
218 break;
219 default:
220 // We don't know what to do with this token, so eat it.
221 m_pObjStrm->SeekRel(DiskLength);
222 break;
223 }
225 }
226}
227
229{
230 switch(TokenType)
231 {
232 case TK_IF:
233 case TK_COUNT:
234 case TK_NOT:
235 {
236 m_bSupported = false;//Not supported formulas
237 }
238 break;
239 default:
240 break;
241 }
242}
248{
249 sal_uInt16 NumberOfArguments = m_pObjStrm->QuickReaduInt16();
250
251 for (sal_uInt16 Count = 0; Count < NumberOfArguments; Count++)
252 {
253 sal_uInt8 ArgumentType = static_cast<sal_uInt8>(m_pObjStrm->QuickReaduInt16()); // written as lushort
254 sal_uInt16 ArgumentDiskLength = m_pObjStrm->QuickReaduInt16();
255 bool bArgument = true;
256
257 switch(ArgumentType)
258 {
259 case TK_CELLID:
260 ReadCellID();
261 break;
262
263 case TK_CELLRANGE:
265 break;
266
267 case TK_CONSTANT:
268 ReadConst();
269 break;
270
271 case TK_TEXT:
272 ReadText();
273 break;
274
275 case TK_EXPRESSION:
277 break;
278
279 default:
280 bArgument = false;
281 m_pObjStrm->SeekRel(ArgumentDiskLength);
282 break;
283 }
284
285 if (bArgument && !m_aStack.empty())
286 {
287 aFunc.AddArg(std::move(m_aStack.back()));
288 m_aStack.pop_back();
289 }
290 }
291}
292
294{
296 {
297 LwpRowList* pRowList = dynamic_cast<LwpRowList*>(cParent.obj().get());
298 if (pRowList)
299 {
300 m_nFormulaRow = pRowList->GetRowID();
301 }
302 else
303 {
304 SAL_WARN("lwp", "missing row list");
305 }
306 }
307 m_pObjStrm->SeekRel(2);//flags, size in file: sal_uInt16
308
309 LwpNotifyListPersistent cNotifyList;
310 cNotifyList.Read(m_pObjStrm.get());
311
313
314 m_pObjStrm->SkipExtra();
315}
316
321{
322 OUString aFormula;
323 if (m_bSupported)
324 {
325 if(1==m_aStack.size())
326 {
327 aFormula = m_aStack[0]->ToString(pCellsMap);
328 }
329 else
330 {
331 assert(false);
332 }
333 }
334 return aFormula;
335}
336
341{
342 OUString aFormula = Convert(pCellsMap);
343 if (!aFormula.isEmpty())
344 {
345 pCell->SetFormula(aFormula);
346 }
348}
349
351{
352 m_dVal = dVal;
353}
354
356{
357 return OUString::number(m_dVal);
358}
359
360LwpFormulaText::LwpFormulaText( OUString aText) : m_aText(std::move(aText))
361{
362}
363
364LwpFormulaCellAddr::LwpFormulaCellAddr(sal_Int16 aCol, sal_Int16 aRow)
365 : m_aCol(aCol), m_aRow(aRow)
366{
367}
368
370{
371 OUString aCellAddr = "<" + LwpFormulaTools::GetCellAddr(m_aRow,m_aCol,pCellsMap) + ">";
372 return aCellAddr;
373}
374
376 sal_Int16 aStartRow,
377 sal_Int16 aEndCol,
378 sal_Int16 aEndRow)
379 : m_aStartCol(aStartCol), m_aStartRow(aStartRow),
380 m_aEndCol(aEndCol), m_aEndRow(aEndRow)
381{
382}
383
388{
389 OUString aCellAddr = "<"
392
393 return aCellAddr;
394}
395
396LwpFormulaFunc::LwpFormulaFunc(sal_uInt16 nTokenType) : m_nTokenType(nTokenType)
397{
398}
399
401{
402}
403void LwpFormulaFunc::AddArg(std::unique_ptr<LwpFormulaArg> pArg)
404{
405 m_aArgs.push_back(std::move(pArg));
406}
411{
412 return "(" + ToString(pCellsMap) + ")";
413}
418{
419 OUStringBuffer aFormula;
420
421 OUString aFuncName = LwpFormulaTools::GetName(m_nTokenType);
422 aFormula.append(aFuncName +
423 " ");//Append a blank space
424
425 //Append args
426 for (auto const& elem : m_aArgs)
427 {
428 aFormula.append(elem->ToArgString(pCellsMap) + "|"); //separator
429 }
430
431 //erase the last "|"
432 if (!m_aArgs.empty())
433 {
434 aFormula.setLength(aFormula.getLength()-1);
435 }
436 else
437 {
438 assert(false);
439 }
440
441 return aFormula.makeStringAndClear();
442}
443
448{
449 OUString aFormula;
450 if (2==m_aArgs.size())
451 {
452 aFormula += m_aArgs[1]->ToArgString(pCellsMap) + " ";
453 OUString aFuncName = LwpFormulaTools::GetName(m_nTokenType);
454
455 aFormula += aFuncName + " " +
456 m_aArgs[0]->ToArgString(pCellsMap);
457 }
458 else
459 {
460 assert(false);
461 }
462 return aFormula;
463}
464
469{
470 OUString aFormula;
471 if (1==m_aArgs.size())
472 {
473 OUString aFuncName = LwpFormulaTools::GetName(m_nTokenType);
474 aFormula += aFuncName +
475 m_aArgs[0]->ToArgString(pCellsMap);
476 }
477 else
478 {
479 assert(false);
480 }
481 return aFormula;
482}
486OUString LwpFormulaTools::GetName(sal_uInt16 nTokenType)
487{
488 OUString aName;
489 switch(nTokenType)
490 {
491 case TK_SUM:
492 aName = "SUM";
493 break;
494 case TK_IF:
495 aName = "IF";//Not supported by SODC
496 break;
497 case TK_COUNT:
498 aName = "COUNT";//Not supported by SODC
499 break;
500 case TK_MINIMUM:
501 aName = "MIN";
502 break;
503 case TK_MAXIMUM:
504 aName = "MAX";
505 break;
506 case TK_AVERAGE:
507 aName = "MEAN";
508 break;
509 case TK_ADD:
510 aName = "+";
511 break;
512 case TK_SUBTRACT:
513 aName = "-";
514 break;
515 case TK_MULTIPLY:
516 aName = "*";
517 break;
518 case TK_DIVIDE:
519 aName = "/";
520 break;
521 case TK_UNARY_MINUS:
522 aName = "-";
523 break;
524 case TK_LESS:
525 aName = "L";
526 break;
527 case TK_LESS_OR_EQUAL:
528 aName = "LEQ";
529 break;
530 case TK_GREATER:
531 aName = "G";
532 break;
534 aName = "GEQ";
535 break;
536 case TK_EQUAL:
537 aName = "EQ";
538 break;
539 case TK_NOT_EQUAL:
540 aName = "NEQ";
541 break;
542 case TK_NOT:
543 aName = "NOT";
544 break;
545 case TK_AND:
546 aName = "AND";
547 break;
548 case TK_OR:
549 aName = "OR";
550 break;
551 default:
552 assert(false);
553 break;
554 }
555 return aName;
556}
557
561OUString LwpFormulaTools::GetCellAddr(sal_Int16 nRow, sal_Int16 nCol, LwpTableLayout* pCellsMap)
562{
563 OUString aCellAddr;
564 XFCell* pCell = pCellsMap->GetCellsMap(nRow,static_cast<sal_uInt8>(nCol));
565 if (pCell)
566 {
567 aCellAddr = pCell->GetCellName();
568 }
569 else
570 {
571 assert( -1==nRow || -1==static_cast<sal_Int8>(nCol));
572 }
573 return aCellAddr;
574}
575
576/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
VO_CELLLIST object.
Definition: lwptblcell.hxx:79
LwpObjectID cParent
Definition: lwptblcell.hxx:92
void Read() override
@descr Read LwpDLVList data from object stream
Definition: lwptblcell.cxx:73
sal_uInt8 cColumn
Definition: lwptblcell.hxx:91
virtual void Convert(XFCell *pCell, LwpTableLayout *pCellsMap=nullptr)
Definition: lwptblcell.cxx:99
sal_uInt8 ColumnID(sal_uInt8 FormulaColumn)
Definition: lwptblcell.hxx:325
void QuickRead(LwpObjectStream *pStrm)
Definition: lwptblcell.cxx:234
virtual ~LwpFormulaArg()=0
LwpFormulaCellAddr(sal_Int16 aCol, sal_Int16 aRow)
virtual OUString ToString(LwpTableLayout *pCellsMap) override
LwpFormulaCellRangeAddr(sal_Int16 aStartCol, sal_Int16 aStartRow, sal_Int16 aEndCol, sal_Int16 aEndRow)
virtual OUString ToString(LwpTableLayout *pCellsMap) override
Convert the cell range into a string.
virtual OUString ToString(LwpTableLayout *pCellsMap) override
LwpFormulaConst(double dVal)
virtual ~LwpFormulaFunc() override
OUString ToArgString(LwpTableLayout *pCellsMap) override
Convert the functions to a string, which is an argument of other formula.
void AddArg(std::unique_ptr< LwpFormulaArg > pArg)
std::vector< std::unique_ptr< LwpFormulaArg > > m_aArgs
virtual OUString ToString(LwpTableLayout *pCellsMap) override
Convert the function to a formula string.
LwpFormulaFunc(sal_uInt16 nTokenType)
sal_uInt16 m_nTokenType
void ReadArguments(LwpFormulaFunc &aFunc)
Read arguments of functions from wordpro file.
std::vector< std::unique_ptr< LwpFormulaArg > > m_aStack
OUString Convert(LwpTableLayout *pCellsMap)
Make the formula string.
void ReadExpression()
Read expression from wordpro file.
void MarkUnsupported(sal_uInt16 TokenType)
sal_uInt16 m_nFormulaRow
void ReadText()
Need more effort for unicode.
void Read() override
@descr Read LwpDLVList data from object stream
LwpFormulaInfo(LwpObjectHeader const &objHdr, LwpSvStream *pStrm)
virtual ~LwpFormulaInfo() override
virtual OUString ToString(LwpTableLayout *pCellsMap) override
Convert the formula in operators to a string : e.g.
LwpFormulaText(OUString aText)
static OUString GetName(sal_uInt16 nTokenType)
Get token name.
static OUString GetCellAddr(sal_Int16 nRow, sal_Int16 nCol, LwpTableLayout *pCellsMap)
Get cell address in String.
virtual OUString ToString(LwpTableLayout *pCellsMap) override
convert the formula in unary operators into string : e.g.
void Read(LwpObjectStream *pObjStrm)
Definition: lwppara.cxx:842
Base class of all Lwp VO objects.
Definition: lwpobjhdr.hxx:71
rtl::Reference< LwpObject > obj(VO_TYPE tag=VO_INVALID) const
@descr get object from object factory per the object id
Definition: lwpobjid.cxx:183
std::unique_ptr< LwpObjectStream > m_pObjStrm
Definition: lwpobj.hxx:90
VO_ROWLIST object.
Definition: lwptblcell.hxx:102
sal_uInt16 GetRowID() const
Definition: lwptblcell.hxx:109
void QuickRead(LwpObjectStream *pStrm)
Definition: lwptblcell.cxx:229
sal_uInt16 RowID(sal_uInt16 FormulaRow)
Definition: lwptblcell.hxx:290
encapsulate XInputStream to provide SvStream like interfaces
Definition: lwpsvstream.hxx:69
VO_TABLELAYOUT object and functions for registering styles and converting tables.
XFCell * GetCellsMap(sal_uInt16 nRow, sal_uInt8 nCol)
get cell map info
@descr Table cell object.
Definition: xfcell.hxx:76
void SetFormula(const OUString &formula)
@descr Set cell formula.
Definition: xfcell.hxx:170
OUString GetCellName()
@descr Return cell name.
Definition: xfcell.cxx:136
OUString aName
#define SAL_WARN(area, stream)
For LWP filter architecture prototype - table layouts.
For LWP filter architecture prototype - table object.
For LWP filter architecture prototype - table object.
@ TK_CELLRANGE
@ TK_MINIMUM
@ TK_SUBTRACT
@ TK_END
@ TK_MAXIMUM
@ TK_GREATER
@ TK_IF
@ TK_UNARY_MINUS
@ TK_COUNT
@ TK_LESS
@ TK_AVERAGE
@ TK_MULTIPLY
@ TK_NOT
@ TK_DIVIDE
@ TK_SUM
@ TK_NOT_EQUAL
@ TK_CELLID
@ TK_ADD
@ TK_CONSTANT
@ TK_OR
@ TK_GREATER_OR_EQUAL
@ TK_EXPRESSION
@ TK_AND
@ TK_TEXT
@ TK_EQUAL
@ TK_LESS_OR_EQUAL
aBuf
TokenType
unsigned char sal_uInt8
signed char sal_Int8
Count