LibreOffice Module sw (master) 1
cellfml.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
24#include <float.h>
25#include <hintids.hxx>
26#include <hints.hxx>
27#include <fmtfld.hxx>
28#include <txtfld.hxx>
29#include <frmfmt.hxx>
30#include <layfrm.hxx>
31#include <cntfrm.hxx>
32#include <tabfrm.hxx>
33#include <doc.hxx>
35#include <ndtxt.hxx>
36#include <swtable.hxx>
37#include <tblsel.hxx>
38#include <cellfml.hxx>
39#include <calc.hxx>
40#include <expfld.hxx>
41#include <usrfld.hxx>
42#include <flddat.hxx>
43#include <cellatr.hxx>
44#include <ndindex.hxx>
45#include <frameformats.hxx>
46#include <comphelper/string.hxx>
47#include <o3tl/string_view.hxx>
48#include <o3tl/safeint.hxx>
49#include <osl/diagnose.h>
50#include <svl/numformat.hxx>
51#include <utility>
52
53namespace
54{
55
56const sal_Unicode cRelSeparator = ',';
57const sal_Unicode cRelIdentifier = '\x12'; // CTRL-R
58
59enum
60{
61 cMAXSTACKSIZE = 50
62};
63
64}
65
66static const SwFrame* lcl_GetBoxFrame( const SwTableBox& rBox );
67static sal_Int32 lcl_GetLongBoxNum( OUString& rStr );
68static const SwTableBox* lcl_RelToBox( const SwTable& rTable,
69 const SwTableBox* pRefBox,
70 const OUString& sGetName);
71static OUString lcl_BoxNmToRel( const SwTable& rTable,
72 const SwTableNode& rTableNd,
73 const OUString& sRefBoxNm,
74 const OUString& sGetStr,
75 bool bExtrnlNm);
76
83double SwTableBox::GetValue( SwTableCalcPara& rCalcPara ) const
84{
85 double nRet = 0;
86
87 if( rCalcPara.m_rCalc.IsCalcError() )
88 return nRet; // stop if there is already an error set
89
90 rCalcPara.m_rCalc.SetCalcError( SwCalcError::Syntax ); // default: error
91
92 // no content box?
93 if( !m_pStartNode )
94 return nRet;
95
96 if( rCalcPara.IncStackCnt() )
97 return nRet;
98
99 rCalcPara.SetLastTableBox( this );
100
101 // Does it create a recursion?
102 SwTableBox* pBox = const_cast<SwTableBox*>(this);
103 if( rCalcPara.m_pBoxStack->find( pBox ) != rCalcPara.m_pBoxStack->end() )
104 return nRet; // already on the stack: error
105
106 // re-start with this box
107 rCalcPara.SetLastTableBox( this );
108
109 rCalcPara.m_pBoxStack->insert( pBox ); // add
110 do { // Middle-Check-Loop, so that we can jump from here. Used so that the box pointer
111 // will be removed from stack at the end.
112 SwDoc* pDoc = GetFrameFormat()->GetDoc();
113
114 if( const SwTableBoxFormula* pFormulaItem = GetFrameFormat()->GetItemIfSet(
115 RES_BOXATR_FORMULA, false ) )
116 {
117 rCalcPara.m_rCalc.SetCalcError( SwCalcError::NONE ); // reset status
118 if( !pFormulaItem->IsValid() )
119 {
120 // calculate
121 const SwTable* pTmp = rCalcPara.m_pTable;
122 rCalcPara.m_pTable = &pBox->GetSttNd()->FindTableNode()->GetTable();
123 const_cast<SwTableBoxFormula*>(pFormulaItem)->Calc( rCalcPara, nRet );
124
125 if( !rCalcPara.IsStackOverflow() )
126 {
127 SwFrameFormat* pFormat = pBox->ClaimFrameFormat();
129 aTmp.Put( SwTableBoxValue( nRet ) );
130 if( SfxItemState::SET != pFormat->GetItemState( RES_BOXATR_FORMAT ))
131 aTmp.Put( SwTableBoxNumFormat( 0 ));
132 pFormat->SetFormatAttr( aTmp );
133 }
134 rCalcPara.m_pTable = pTmp;
135 }
136 else
138 break;
139 }
140 else if( const SwTableBoxValue* pBoxValueItem = pBox->GetFrameFormat()->GetItemIfSet(
141 RES_BOXATR_VALUE, false ) )
142 {
143 rCalcPara.m_rCalc.SetCalcError( SwCalcError::NONE ); // reset status
144 nRet = pBoxValueItem->GetValue();
145 break;
146 }
147
148 SwTextNode* pTextNd = pDoc->GetNodes()[ m_pStartNode->GetIndex() + 1 ]->GetTextNode();
149 if( !pTextNd )
150 break;
151
152 sal_Int32 nSttPos = 0;
153 OUString sText = pTextNd->GetText();
154
155 // use text of the tracked changes
156 if ( sText.getLength() > 0 &&
157 sText[0] != CH_TXTATR_BREAKWORD && sText[0] != CH_TXTATR_INWORD )
158 {
159 sText = pTextNd->GetRedlineText();
160 }
161
162 while ( nSttPos < sText.getLength() && ( sText[nSttPos]==' ' || sText[nSttPos]=='\t' ) )
163 ++nSttPos;
164
165 // if there is a calculation field at position 1, get the value of it
166 const bool bOK = nSttPos<sText.getLength();
167 const sal_Unicode Char = bOK ? sText[nSttPos] : 0;
168 SwTextField * pTextField = nullptr;
169 if ( bOK && (Char==CH_TXTATR_BREAKWORD || Char==CH_TXTATR_INWORD) )
170 {
171 pTextField = static_txtattr_cast<SwTextField*>(pTextNd->GetTextAttrForCharAt(nSttPos, RES_TXTATR_FIELD));
172 }
173 if ( pTextField != nullptr )
174 {
175 rCalcPara.m_rCalc.SetCalcError( SwCalcError::NONE ); // reset status
176
177 const SwField* pField = pTextField->GetFormatField().GetField();
178 switch ( pField->GetTyp()->Which() )
179 {
181 nRet = static_cast<const SwSetExpField*>(pField)->GetValue(rCalcPara.m_pLayout);
182 break;
183 case SwFieldIds::User:
184 nRet = static_cast<const SwUserField*>(pField)->GetValue();
185 break;
187 {
188 SwTableField* pTableField = const_cast<SwTableField*>(static_cast<const SwTableField*>(pField));
189 if( !pTableField->IsValid() )
190 {
191 // use the right table!
192 const SwTable* pTmp = rCalcPara.m_pTable;
193 rCalcPara.m_pTable = &pTextNd->FindTableNode()->GetTable();
194 pTableField->CalcField( rCalcPara );
195 rCalcPara.m_pTable = pTmp;
196 }
197 nRet = pTableField->GetValue();
198 }
199 break;
200
202 nRet = static_cast<const SwDateTimeField*>( pField )->GetValue();
203 break;
204
206 //JP 14.09.98: Bug 56112 - placeholder never have the right content!
207 nRet = 0;
208 break;
209
210 default:
211 nRet = rCalcPara.m_rCalc.Calculate( pField->ExpandField(true, nullptr) ).GetDouble();
212 }
213 }
214 else if ( nSttPos < sText.getLength()
216 {
217 const SwTextInputField * pTextInputField =
218 dynamic_cast< const SwTextInputField* >(
219 pTextNd->GetTextAttrAt( nSttPos, RES_TXTATR_INPUTFIELD ) );
220 if ( pTextInputField == nullptr )
221 break;
222 nRet = rCalcPara.m_rCalc.Calculate( pTextInputField->GetFieldContent() ).GetDouble();
223 }
224 else if ( Char != CH_TXTATR_BREAKWORD )
225 {
226 // result is 0 but no error!
227 rCalcPara.m_rCalc.SetCalcError( SwCalcError::NONE ); // reset status
228
229 double aNum = 0.0;
230 sText = bOK ? sText.copy( nSttPos ) : OUString();
231 sal_uInt32 nFormatIndex = GetFrameFormat()->GetTableBoxNumFormat().GetValue();
232
233 SvNumberFormatter* pNumFormatr = pDoc->GetNumberFormatter();
234
235 const SvNumFormatType nFormatType = pNumFormatr->GetType( nFormatIndex );
236 if( nFormatType == SvNumFormatType::TEXT )
237 nFormatIndex = 0;
238 // JP 22.04.98: Bug 49659 - special treatment for percentages
239 else if( !sText.isEmpty() &&
240 SvNumFormatType::PERCENT == nFormatType)
241 {
242 sal_uInt32 nTmpFormat = 0;
243 if( pDoc->IsNumberFormat( sText, nTmpFormat, aNum ) &&
244 SvNumFormatType::NUMBER == pNumFormatr->GetType( nTmpFormat ))
245 sText += "%";
246 }
247
248 if( pDoc->IsNumberFormat( sText, nFormatIndex, aNum ))
249 nRet = aNum;
250 else
251 rCalcPara.m_rCalc.SetCalcError( SwCalcError::NaN ); // set for interoperability functions
252 }
253 // ?? otherwise it is an error
254 } while( false );
255
256 if( !rCalcPara.IsStackOverflow() )
257 {
258 rCalcPara.m_pBoxStack->erase( pBox ); // remove from stack
259 rCalcPara.DecStackCnt();
260 }
261
262 //JP 12.01.99: error detection, Bug 60794
263 if( DBL_MAX == nRet )
264 rCalcPara.m_rCalc.SetCalcError( SwCalcError::Syntax ); // set error
265
266 return nRet;
267}
268
269// structure needed for calculation of tables
270
272 SwRootFrame const*const pLayout)
273 : m_pLastTableBox(nullptr)
274 , m_nStackCount( 0 )
275 , m_nMaxSize( cMAXSTACKSIZE )
276 , m_pLayout(pLayout)
277 , m_pBoxStack( new SwTableSortBoxes )
278 , m_rCalc( rCalculator )
279 , m_pTable( &rTable )
280{
281}
282
284{
285}
286
288{
289 // If a stack overflow was detected, redo with last box.
290 sal_uInt16 nSaveMaxSize = m_nMaxSize;
291
292 m_nMaxSize = cMAXSTACKSIZE - 5;
293 sal_uInt16 nCnt = 0;
294 SwTableBoxes aStackOverflows;
295 do {
296 SwTableBox* pBox = const_cast<SwTableBox*>(m_pLastTableBox);
297 m_nStackCount = 0;
299 aStackOverflows.insert( aStackOverflows.begin() + nCnt++, pBox );
300
301 m_pBoxStack->erase( pBox );
302 pBox->GetValue( *this );
303 } while( IsStackOverflow() );
304
305 m_nMaxSize = cMAXSTACKSIZE - 3; // decrease at least one level
306
307 // if recursion was detected
308 m_nStackCount = 0;
310 m_pBoxStack->clear();
311
312 while( !m_rCalc.IsCalcError() && nCnt )
313 {
314 aStackOverflows[ --nCnt ]->GetValue( *this );
316 break;
317 }
318
319 m_nMaxSize = nSaveMaxSize;
320 aStackOverflows.clear();
321 return !m_rCalc.IsCalcError();
322}
323
325: m_sFormula( std::move(aFormula) )
326, m_eNmType( EXTRNL_NAME )
327, m_bValidValue( false )
328{
329}
330
332{
333}
334
335void SwTableFormula::MakeFormula_( const SwTable& rTable, OUStringBuffer& rNewStr,
336 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
337{
338 SwTableCalcPara* pCalcPara = static_cast<SwTableCalcPara*>(pPara);
339 if( pCalcPara->m_rCalc.IsCalcError() ) // stop if there is already an error set
340 return;
341
342 SwTableBox *pEndBox = nullptr;
343
344 rFirstBox = rFirstBox.copy(1); // erase label of this box
345 // a region in this area?
346 if( pLastBox )
347 {
348 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->toInt64()));
349
350 // Is it actually a valid pointer?
351 if( rTable.GetTabSortBoxes().find( pEndBox ) == rTable.GetTabSortBoxes().end() )
352 pEndBox = nullptr;
353 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
354 }
355 SwTableBox* pSttBox = reinterpret_cast<SwTableBox*>(
356 sal::static_int_cast<sal_IntPtr>(rFirstBox.toInt64()));
357 // Is it actually a valid pointer?
358 if( rTable.GetTabSortBoxes().find( pSttBox ) == rTable.GetTabSortBoxes().end() )
359 pSttBox = nullptr;
360
361 rNewStr.append(" ");
362 if( pEndBox && pSttBox ) // area?
363 {
364 // get all selected boxes via layout and calculate their values
365 SwSelBoxes aBoxes;
366 GetBoxes( *pSttBox, *pEndBox, aBoxes );
367
368 // don't use empty cells or cells with text content as zeroes in interoperability functions
369 sal_Int16 nUseOnlyNumber = -1;
370
371 rNewStr.append("(");
372 bool bDelim = false;
373 for (size_t n = 0; n < aBoxes.size() &&
374 !pCalcPara->m_rCalc.IsCalcError(); ++n)
375 {
376 const SwTableBox* pTableBox = aBoxes[n];
377 if ( pTableBox->getRowSpan() >= 1 )
378 {
379 double fVal = pTableBox->GetValue( *pCalcPara );
380
381 if ( pCalcPara->m_rCalc.IsCalcNotANumber() )
382 {
383 if ( nUseOnlyNumber == -1 )
384 {
385 OUString sFormula = rNewStr.toString().toAsciiUpperCase();
386 nUseOnlyNumber = sal_Int16(
387 sFormula.lastIndexOf("AVERAGE") > -1 ||
388 sFormula.lastIndexOf("COUNT") > -1 ||
389 sFormula.lastIndexOf("PRODUCT") > -1 );
390 }
391 if ( nUseOnlyNumber > 0 )
392 continue;
393 }
394
395 if( bDelim )
396 rNewStr.append(cListDelim);
397 bDelim = true;
398 rNewStr.append(pCalcPara->m_rCalc.GetStrResult( fVal ));
399 }
400 }
401 rNewStr.append(")");
402 }
403 else if( pSttBox && !pLastBox ) // only the StartBox?
404 {
405 // JP 12.01.99: and no EndBox in the formula!
406 // calculate the value of the box
407 if ( pSttBox->getRowSpan() >= 1 )
408 {
409 rNewStr.append("(");
410 double fVal = pSttBox->GetValue( *pCalcPara );
411 // don't use empty cell or a cell with text content as zero in interoperability functions
412 // (except PRODUCT, where the result is correct anyway)
413 if ( !pCalcPara->m_rCalc.IsCalcNotANumber() ||
414 ( rNewStr.toString().toAsciiUpperCase().lastIndexOf("AVERAGE") == -1 &&
415 rNewStr.toString().toAsciiUpperCase().lastIndexOf("COUNT") == -1 ) )
416 {
417 rNewStr.append(pCalcPara->m_rCalc.GetStrResult( fVal ));
418 }
419 rNewStr.append(")");
420 }
421 }
422 else
423 pCalcPara->m_rCalc.SetCalcError( SwCalcError::Syntax ); // set error
424 rNewStr.append(" ");
425}
426
427void SwTableFormula::RelNmsToBoxNms( const SwTable& rTable, OUStringBuffer& rNewStr,
428 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
429{
430 // relative name w.r.t. box name (external presentation)
431 SwNode* pNd = static_cast<SwNode*>(pPara);
432 OSL_ENSURE( pNd, "Field isn't in any TextNode" );
433 const SwTableBox *pBox = rTable.GetTableBox(
435
436 rNewStr.append(rFirstBox[0]); // get label for the box
437 rFirstBox = rFirstBox.copy(1);
438 if( pLastBox )
439 {
440 const SwTableBox *pRelLastBox = lcl_RelToBox( rTable, pBox, *pLastBox );
441 if ( pRelLastBox )
442 rNewStr.append(pRelLastBox->GetName());
443 else
444 rNewStr.append("A1");
445 rNewStr.append(":");
446 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
447 }
448
449 const SwTableBox *pRelFirstBox = lcl_RelToBox( rTable, pBox, rFirstBox );
450
451 if (pRelFirstBox)
452 rNewStr.append(pRelFirstBox->GetName());
453 else
454 rNewStr.append("A1");
455
456 // get label for the box
457 rNewStr.append(rFirstBox[ rFirstBox.getLength()-1 ]);
458}
459
460void SwTableFormula::RelBoxNmsToPtr( const SwTable& rTable, OUStringBuffer& rNewStr,
461 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
462{
463 // relative name w.r.t. box name (internal presentation)
464 SwNode* pNd = static_cast<SwNode*>(pPara);
465 OSL_ENSURE( pNd, "Field not placed in any Node" );
466 const SwTableBox *pBox = rTable.GetTableBox(
468
469 rNewStr.append(rFirstBox[0]); // get label for the box
470 rFirstBox = rFirstBox.copy(1);
471 if( pLastBox )
472 {
473 const SwTableBox *pRelLastBox = lcl_RelToBox( rTable, pBox, *pLastBox );
474 if ( pRelLastBox )
475 rNewStr.append(reinterpret_cast<sal_IntPtr>(pRelLastBox));
476 else
477 rNewStr.append("0");
478 rNewStr.append(":");
479 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
480 }
481
482 const SwTableBox *pRelFirstBox = lcl_RelToBox( rTable, pBox, rFirstBox );
483 if ( pRelFirstBox )
484 rNewStr.append(reinterpret_cast<sal_IntPtr>(pRelFirstBox));
485 else
486 rNewStr.append("0");
487
488 // get label for the box
489 rNewStr.append(rFirstBox[ rFirstBox.getLength()-1 ]);
490}
491
492void SwTableFormula::BoxNmsToRelNm( const SwTable& rTable, OUStringBuffer& rNewStr,
493 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
494{
495 // box name (external presentation) w.r.t. relative name
496 SwNode* pNd = static_cast<SwNode*>(pPara);
497 OSL_ENSURE( pNd, "Field not placed in any Node" );
498 const SwTableNode* pTableNd = pNd->FindTableNode();
499
500 OUString sRefBoxNm;
501 if( &pTableNd->GetTable() == &rTable )
502 {
503 const SwTableBox *pBox = rTable.GetTableBox(
505 OSL_ENSURE( pBox, "Field not placed in any Table" );
506 sRefBoxNm = pBox->GetName();
507 }
508
509 rNewStr.append(rFirstBox[0]); // get label for the box
510 rFirstBox = rFirstBox.copy(1);
511 if( pLastBox )
512 {
513 rNewStr.append(lcl_BoxNmToRel( rTable, *pTableNd, sRefBoxNm, *pLastBox,
515 rNewStr.append(":");
516 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
517 }
518
519 rNewStr.append(lcl_BoxNmToRel( rTable, *pTableNd, sRefBoxNm, rFirstBox,
521
522 // get label for the box
523 rNewStr.append(rFirstBox[ rFirstBox.getLength()-1 ]);
524}
525
526void SwTableFormula::PtrToBoxNms( const SwTable& rTable, OUStringBuffer& rNewStr,
527 OUString& rFirstBox, OUString* pLastBox, void* ) const
528{
529 // area in these parentheses?
530 SwTableBox* pBox;
531
532 rNewStr.append(rFirstBox[0]); // get label for the box
533 rFirstBox = rFirstBox.copy(1);
534 if( pLastBox )
535 {
536 pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->toInt64()));
537
538 // Is it actually a valid pointer?
539 if( rTable.GetTabSortBoxes().find( pBox ) != rTable.GetTabSortBoxes().end() )
540 rNewStr.append(pBox->GetName());
541 else
542 rNewStr.append("?");
543 rNewStr.append(":");
544 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
545 }
546
547 pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.toInt64()));
548 // Is it actually a valid pointer?
549 if( rTable.GetTabSortBoxes().find( pBox ) != rTable.GetTabSortBoxes().end() )
550 rNewStr.append(pBox->GetName());
551 else
552 rNewStr.append("?");
553
554 // get label for the box
555 rNewStr.append(rFirstBox[ rFirstBox.getLength()-1 ]);
556}
557
558void SwTableFormula::BoxNmsToPtr( const SwTable& rTable, OUStringBuffer& rNewStr,
559 OUString& rFirstBox, OUString* pLastBox, void* ) const
560{
561 // area in these parentheses?
562 const SwTableBox* pBox;
563
564 rNewStr.append(rFirstBox[0]); // get label for the box
565 rFirstBox = rFirstBox.copy(1);
566 if( pLastBox )
567 {
568 pBox = rTable.GetTableBox( *pLastBox );
569 rNewStr.append(OUString::number(reinterpret_cast<sal_IntPtr>(pBox)) +
570 ":");
571 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
572 }
573
574 pBox = rTable.GetTableBox( rFirstBox );
575 rNewStr.append(OUString::number(reinterpret_cast<sal_IntPtr>(pBox))
576 + OUStringChar(rFirstBox[ rFirstBox.getLength()-1 ])); // get label for the box
577}
578
581{
582 const SwNode* pNd = nullptr;
583 FnScanFormula fnFormula = nullptr;
584 switch (m_eNmType)
585 {
586 case INTRNL_NAME:
587 if( pTable )
588 fnFormula = &SwTableFormula::PtrToBoxNms;
589 break;
590 case REL_NAME:
591 if( pTable )
592 {
594 pNd = GetNodeOfFormula();
595 }
596 break;
597 case EXTRNL_NAME:
598 return;
599 }
600 m_sFormula = ScanString( fnFormula, *pTable, const_cast<void*>(static_cast<void const *>(pNd)) );
602}
603
606{
607 const SwNode* pNd = nullptr;
608 FnScanFormula fnFormula = nullptr;
609 switch (m_eNmType)
610 {
611 case EXTRNL_NAME:
612 if( pTable )
613 fnFormula = &SwTableFormula::BoxNmsToPtr;
614 break;
615 case REL_NAME:
616 if( pTable )
617 {
619 pNd = GetNodeOfFormula();
620 }
621 break;
622 case INTRNL_NAME:
623 return;
624 }
625 m_sFormula = ScanString( fnFormula, *pTable, const_cast<void*>(static_cast<void const *>(pNd)) );
627}
628
631{
632 const SwNode* pNd = nullptr;
633 FnScanFormula fnFormula = nullptr;
634 switch (m_eNmType)
635 {
636 case INTRNL_NAME:
637 case EXTRNL_NAME:
638 if( pTable )
639 {
641 pNd = GetNodeOfFormula();
642 }
643 break;
644 case REL_NAME:
645 return;
646 }
647 m_sFormula = ScanString( fnFormula, *pTable, const_cast<void*>(static_cast<void const *>(pNd)) );
649}
650
651OUString SwTableFormula::ScanString( FnScanFormula fnFormula, const SwTable& rTable,
652 void* pPara ) const
653{
654 OUStringBuffer aStr;
655 sal_Int32 nFormula = 0;
656 sal_Int32 nEnd = 0;
657
658 do {
659 // If the formula is preceded by a name, use this table!
660 const SwTable* pTable = &rTable;
661
662 sal_Int32 nStt = m_sFormula.indexOf( '<', nFormula );
663 if ( nStt>=0 )
664 {
665 while ( nStt>=0 )
666 {
667 const sal_Int32 nNxt = nStt+1;
668 if (nNxt>=m_sFormula.getLength())
669 {
670 nStt = -1;
671 break;
672 }
673 if ( m_sFormula[nNxt]!=' ' && m_sFormula[nNxt]!='=' )
674 break;
675 nStt = m_sFormula.indexOf( '<', nNxt );
676 }
677
678 if ( nStt>=0 )
679 // Start searching from current position, which is valid for sure
680 nEnd = m_sFormula.indexOf( '>', nStt );
681 }
682 if (nStt<0 || nEnd<0 )
683 {
684 // set the rest and finish
685 aStr.append(m_sFormula.subView(nFormula));
686 break;
687 }
688
689 // write beginning
690 aStr.append(m_sFormula.subView(nFormula, nStt - nFormula));
691
692 if (fnFormula)
693 {
694 sal_Int32 nSeparator = 0;
695 // Is a table name preceded?
696 // JP 16.02.99: SplitMergeBoxNm take care of the name themself
697 // JP 22.02.99: Linux compiler needs cast
698 // JP 28.06.99: rel. BoxName has no preceding tablename!
699 if( fnFormula != &SwTableFormula::SplitMergeBoxNm_ &&
700 m_sFormula.getLength()>(nStt+1) && cRelIdentifier != m_sFormula[nStt+1] &&
701 (nSeparator = m_sFormula.indexOf( '.', nStt ))>=0
702 && nSeparator < nEnd )
703 {
704 OUString sTableNm( m_sFormula.copy( nStt, nEnd - nStt ));
705
706 // If there are dots in the name, then they appear in pairs (e.g. A1.1.1)!
707 if( (comphelper::string::getTokenCount(sTableNm, '.') - 1) & 1 )
708 {
709 sTableNm = sTableNm.copy( 0, nSeparator - nStt );
710
711 // when creating a formula the table name is unwanted
712 if( fnFormula != &SwTableFormula::MakeFormula_ )
713 aStr.append(sTableNm);
714 nStt = nSeparator;
715
716 sTableNm = sTableNm.copy( 1 ); // delete separator
717 if( sTableNm != rTable.GetFrameFormat()->GetName() )
718 {
719 // then search for table
720 const SwTable* pFnd = FindTable(
721 *rTable.GetFrameFormat()->GetDoc(),
722 sTableNm );
723 if( pFnd )
724 pTable = pFnd;
725 // ??
726 OSL_ENSURE( pFnd, "No table found. What now?" );
727 }
728 }
729 }
730
731 OUString sBox( m_sFormula.copy( nStt, nEnd - nStt + 1 ));
732 // area in these parentheses?
733 nSeparator = m_sFormula.indexOf( ':', nStt );
734 if ( nSeparator>=0 && nSeparator<nEnd )
735 {
736 // without opening parenthesis
737 OUString aFirstBox( m_sFormula.copy( nStt+1, nSeparator - nStt - 1 ));
738 (this->*fnFormula)( *pTable, aStr, sBox, &aFirstBox, pPara );
739 }
740 else
741 (this->*fnFormula)( *pTable, aStr, sBox, nullptr, pPara );
742 }
743
744 nFormula = nEnd+1;
745 } while( true );
746 return aStr.makeStringAndClear();
747}
748
749const SwTable* SwTableFormula::FindTable( SwDoc& rDoc, std::u16string_view rNm )
750{
751 const sw::TableFrameFormats& rTableFormats = *rDoc.GetTableFrameFormats();
752 const SwTable* pTmpTable = nullptr, *pRet = nullptr;
753 for( auto nFormatCnt = rTableFormats.size(); nFormatCnt; )
754 {
755 SwTableFormat* pFormat = rTableFormats[ --nFormatCnt ];
756 // if we are called from Sw3Writer, a number is dependent on the format name
757 SwTableBox* pFBox;
758 if ( rNm == o3tl::getToken(pFormat->GetName(), 0, 0x0a) &&
759 nullptr != ( pTmpTable = SwTable::FindTable( pFormat ) ) &&
760 nullptr != (pFBox = pTmpTable->GetTabSortBoxes()[0] ) &&
761 pFBox->GetSttNd() &&
762 pFBox->GetSttNd()->GetNodes().IsDocNodes() )
763 {
764 // a table in the normal NodesArr
765 pRet = pTmpTable;
766 break;
767 }
768 }
769 return pRet;
770}
771
772static const SwFrame* lcl_GetBoxFrame( const SwTableBox& rBox )
773{
774 SwNodeIndex aIdx( *rBox.GetSttNd() );
775 SwContentNode* pCNd = aIdx.GetNodes().GoNext( &aIdx );
776 OSL_ENSURE( pCNd, "Box has no TextNode" );
777 Point aPt; // get the first frame of the layout - table headline
778 std::pair<Point, bool> const tmp(aPt, false);
779 return pCNd->getLayoutFrame(pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp);
780}
781
782static sal_Int32 lcl_GetLongBoxNum( OUString& rStr )
783{
784 sal_Int32 nRet;
785 const sal_Int32 nPos = rStr.indexOf( cRelSeparator );
786 if ( nPos<0 )
787 {
788 nRet = rStr.toInt32();
789 rStr.clear();
790 }
791 else
792 {
793 nRet = o3tl::toInt32(rStr.subView( 0, nPos ));
794 rStr = rStr.copy( nPos+1 );
795 }
796 return nRet;
797}
798
799static const SwTableBox* lcl_RelToBox( const SwTable& rTable,
800 const SwTableBox* pRefBox,
801 const OUString& _sGetName )
802{
803 // get line
804 const SwTableBox* pBox = nullptr;
805 OUString sGetName = _sGetName;
806
807 // Is it really a relative value?
808 if ( cRelIdentifier == sGetName[0] ) // yes
809 {
810 if( !pRefBox )
811 return nullptr;
812
813 sGetName = sGetName.copy( 1 );
814
815 const SwTableLines* pLines = &rTable.GetTabLines();
816 const SwTableBoxes* pBoxes;
817 const SwTableLine* pLine;
818
819 // determine starting values of the box,...
820 pBox = pRefBox;
821 pLine = pBox->GetUpper();
822 while( pLine->GetUpper() )
823 {
824 pBox = pLine->GetUpper();
825 pLine = pBox->GetUpper();
826 }
827 sal_uInt16 nSttBox = pLine->GetBoxPos( pBox );
828 sal_uInt16 nSttLine = rTable.GetTabLines().GetPos( pLine );
829
830 const sal_Int32 nBoxOffset = lcl_GetLongBoxNum( sGetName ) + nSttBox;
831 const sal_Int32 nLineOffset = lcl_GetLongBoxNum( sGetName ) + nSttLine;
832
833 if( nBoxOffset < 0 ||
834 nLineOffset < 0 )
835 return nullptr;
836
837 if( o3tl::make_unsigned(nLineOffset) >= pLines->size() )
838 return nullptr;
839
840 pLine = (*pLines)[ nLineOffset ];
841
842 // ... then search the box
843 pBoxes = &pLine->GetTabBoxes();
844 if( o3tl::make_unsigned(nBoxOffset) >= pBoxes->size() )
845 return nullptr;
846 pBox = (*pBoxes)[ nBoxOffset ];
847
848 while (!sGetName.isEmpty())
849 {
850 nSttBox = SwTable::GetBoxNum( sGetName );
851 pLines = &pBox->GetTabLines();
852 if( nSttBox )
853 --nSttBox;
854
855 nSttLine = SwTable::GetBoxNum( sGetName );
856
857 // determine line
858 if( !nSttLine || nSttLine > pLines->size() )
859 break;
860 pLine = (*pLines)[ nSttLine-1 ];
861
862 // determine box
863 pBoxes = &pLine->GetTabBoxes();
864 if( nSttBox >= pBoxes->size() )
865 break;
866 pBox = (*pBoxes)[ nSttBox ];
867 }
868
869 if( pBox )
870 {
871 if( !pBox->GetSttNd() )
872 // "bubble up" to first box
873 while( !pBox->GetTabLines().empty() )
874 pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
875 }
876 }
877 else
878 {
879 // otherwise it is an absolute external presentation
880 pBox = rTable.GetTableBox( sGetName );
881 }
882 return pBox;
883}
884
885static OUString lcl_BoxNmToRel( const SwTable& rTable, const SwTableNode& rTableNd,
886 const OUString& _sRefBoxNm, const OUString& _sTmp, bool bExtrnlNm )
887{
888 OUString sTmp = _sTmp;
889 OUString sRefBoxNm = _sRefBoxNm;
890 if( !bExtrnlNm )
891 {
892 // convert into external presentation
893 SwTableBox* pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(sTmp.toInt64()));
894 if( rTable.GetTabSortBoxes().find( pBox ) == rTable.GetTabSortBoxes().end() )
895 return OUString('?');
896 sTmp = pBox->GetName();
897 }
898
899 // If the formula is spanning over a table then keep external presentation
900 if( &rTable == &rTableNd.GetTable() )
901 {
902 tools::Long nBox = SwTable::GetBoxNum( sTmp, true );
903 nBox -= SwTable::GetBoxNum( sRefBoxNm, true );
904 tools::Long nLine = SwTable::GetBoxNum( sTmp );
905 nLine -= SwTable::GetBoxNum( sRefBoxNm );
906
907 const OUString sCpy = sTmp; //JP 01.11.95: add rest from box name
908
909 sTmp = OUStringChar(cRelIdentifier) + OUString::number( nBox )
910 + OUStringChar(cRelSeparator) + OUString::number( nLine );
911
912 if (!sCpy.isEmpty())
913 {
914 sTmp += OUStringChar(cRelSeparator) + sCpy;
915 }
916 }
917
918 if (sTmp.endsWith(">"))
919 return sTmp.copy(0, sTmp.getLength()-1 );
920
921 return sTmp;
922}
923
925 SwSelBoxes& rBoxes )
926{
927 rBoxes.clear();
928
929 BoxNmToPtr( &rTable );
930 ScanString( &SwTableFormula::GetFormulaBoxes, rTable, &rBoxes );
931}
932
933void SwTableFormula::GetFormulaBoxes( const SwTable& rTable, OUStringBuffer& ,
934 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
935{
936 SwSelBoxes* pBoxes = static_cast<SwSelBoxes*>(pPara);
937 SwTableBox* pEndBox = nullptr;
938
939 rFirstBox = rFirstBox.copy(1); // delete box label
940 // area in these parentheses?
941 if( pLastBox )
942 {
943 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->toInt64()));
944
945 // Is it actually a valid pointer?
946 if( rTable.GetTabSortBoxes().find( pEndBox ) == rTable.GetTabSortBoxes().end() )
947 pEndBox = nullptr;
948 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
949 }
950
951 SwTableBox *pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.toInt64()));
952 // Is it actually a valid pointer?
953 if( !pSttBox || rTable.GetTabSortBoxes().find( pSttBox ) == rTable.GetTabSortBoxes().end() )
954 return;
955
956 if ( pEndBox ) // area?
957 {
958 // get all selected boxes via layout and calculate their values
959 SwSelBoxes aBoxes;
960 GetBoxes( *pSttBox, *pEndBox, aBoxes );
961 pBoxes->insert( aBoxes );
962 }
963 else // only the StartBox?
964 pBoxes->insert( pSttBox );
965}
966
968 const SwTableBox& rEndBox,
969 SwSelBoxes& rBoxes )
970{
971 // get all selected boxes via layout
972 const SwLayoutFrame *pStt, *pEnd;
973 const SwFrame* pFrame = lcl_GetBoxFrame( rSttBox );
974 pStt = pFrame ? pFrame->GetUpper() : nullptr;
975 pFrame = lcl_GetBoxFrame( rEndBox );
976 pEnd = pFrame ? pFrame->GetUpper() : nullptr;
977 if( !pStt || !pEnd )
978 return ; // no valid selection
979
980 GetTableSel( pStt, pEnd, rBoxes, nullptr );
981
982 const SwTable* pTable = pStt->FindTabFrame()->GetTable();
983
984 // filter headline boxes
985 if( pTable->GetRowsToRepeat() <= 0 )
986 return;
987
988 do { // middle-check loop
989 const SwTableLine* pLine = rSttBox.GetUpper();
990 while( pLine->GetUpper() )
991 pLine = pLine->GetUpper()->GetUpper();
992
993 if( pTable->IsHeadline( *pLine ) )
994 break; // headline in this area!
995
996 // maybe start and end are swapped
997 pLine = rEndBox.GetUpper();
998 while ( pLine->GetUpper() )
999 pLine = pLine->GetUpper()->GetUpper();
1000
1001 if( pTable->IsHeadline( *pLine ) )
1002 break; // headline in this area!
1003
1004 const SwTabFrame *pStartTable = pStt->FindTabFrame();
1005 const SwTabFrame *pEndTable = pEnd->FindTabFrame();
1006
1007 if (pStartTable == pEndTable) // no split table
1008 break;
1009
1010 // then remove table headers
1011 for (size_t n = 0; n < rBoxes.size(); ++n)
1012 {
1013 pLine = rBoxes[n]->GetUpper();
1014 while( pLine->GetUpper() )
1015 pLine = pLine->GetUpper()->GetUpper();
1016
1017 if( pTable->IsHeadline( *pLine ) )
1018 rBoxes.erase( rBoxes.begin() + n-- );
1019 }
1020 } while( false );
1021}
1022
1024void SwTableFormula::HasValidBoxes_( const SwTable& rTable, OUStringBuffer& ,
1025 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
1026{
1027 bool* pBValid = static_cast<bool*>(pPara);
1028 if( !(*pBValid) ) // wrong is wrong
1029 return;
1030
1031 SwTableBox* pSttBox = nullptr, *pEndBox = nullptr;
1032 rFirstBox = rFirstBox.copy(1); // delete identifier of box
1033
1034 // area in this parenthesis?
1035 if( pLastBox )
1036 rFirstBox = rFirstBox.copy( pLastBox->getLength()+1 );
1037
1038 switch (m_eNmType)
1039 {
1040 case INTRNL_NAME:
1041 if( pLastBox )
1042 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->toInt64()));
1043 pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.toInt64()));
1044 break;
1045
1046 case REL_NAME:
1047 {
1048 const SwNode* pNd = GetNodeOfFormula();
1049 const SwTableBox* pBox = !pNd ? nullptr
1050 : const_cast<SwTableBox *>(rTable.GetTableBox(
1051 pNd->FindTableBoxStartNode()->GetIndex() ));
1052 if( pLastBox )
1053 pEndBox = const_cast<SwTableBox*>(lcl_RelToBox( rTable, pBox, *pLastBox ));
1054 pSttBox = const_cast<SwTableBox*>(lcl_RelToBox( rTable, pBox, rFirstBox ));
1055 }
1056 break;
1057
1058 case EXTRNL_NAME:
1059 if( pLastBox )
1060 pEndBox = const_cast<SwTableBox*>(rTable.GetTableBox( *pLastBox ));
1061 pSttBox = const_cast<SwTableBox*>(rTable.GetTableBox( rFirstBox ));
1062 break;
1063 }
1064
1065 // Are these valid pointers?
1066 if( ( pLastBox &&
1067 ( !pEndBox || rTable.GetTabSortBoxes().find( pEndBox ) == rTable.GetTabSortBoxes().end() ) ) ||
1068 ( !pSttBox || rTable.GetTabSortBoxes().find( pSttBox ) == rTable.GetTabSortBoxes().end() ) )
1069 *pBValid = false;
1070}
1071
1073{
1074 bool bRet = true;
1075 const SwNode* pNd = GetNodeOfFormula();
1076 if( pNd && nullptr != ( pNd = pNd->FindTableNode() ) )
1078 static_cast<const SwTableNode*>(pNd)->GetTable(), &bRet );
1079 return bRet;
1080}
1081
1082sal_uInt16 SwTableFormula::GetLnPosInTable( const SwTable& rTable, const SwTableBox* pBox )
1083{
1084 sal_uInt16 nRet = USHRT_MAX;
1085 if( pBox )
1086 {
1087 const SwTableLine* pLn = pBox->GetUpper();
1088 while( pLn->GetUpper() )
1089 pLn = pLn->GetUpper()->GetUpper();
1090 nRet = rTable.GetTabLines().GetPos( pLn );
1091 }
1092 return nRet;
1093}
1094
1095void SwTableFormula::SplitMergeBoxNm_( const SwTable& rTable, OUStringBuffer& rNewStr,
1096 OUString& rFirstBox, OUString* pLastBox, void* pPara ) const
1097{
1098 SwTableFormulaUpdate& rTableUpd = *static_cast<SwTableFormulaUpdate*>(pPara);
1099
1100 rNewStr.append(rFirstBox[0]); // get label for the box
1101 rFirstBox = rFirstBox.copy(1);
1102
1103 OUString sTableNm;
1104 const SwTable* pTable = &rTable;
1105
1106 OUString* pTableNmBox = pLastBox ? pLastBox : &rFirstBox;
1107
1108 const sal_Int32 nLastBoxLen = pTableNmBox->getLength();
1109 const sal_Int32 nSeparator = pTableNmBox->indexOf('.');
1110 if ( nSeparator>=0 &&
1111 // If there are dots in the name, then these appear in pairs (e.g. A1.1.1)!
1112 (comphelper::string::getTokenCount(*pTableNmBox, '.') - 1) & 1 )
1113 {
1114 sTableNm = pTableNmBox->copy( 0, nSeparator );
1115 *pTableNmBox = pTableNmBox->copy( nSeparator + 1); // remove dot
1116 const SwTable* pFnd = FindTable( *rTable.GetFrameFormat()->GetDoc(), sTableNm );
1117 if( pFnd )
1118 pTable = pFnd;
1119
1120 if( TBL_MERGETBL == rTableUpd.m_eFlags )
1121 {
1122 if( pFnd )
1123 {
1124 if( pFnd == rTableUpd.m_aData.pDelTable )
1125 {
1126 if( rTableUpd.m_pTable != &rTable ) // not the current one
1127 rNewStr.append(rTableUpd.m_pTable->GetFrameFormat()->GetName() + "."); // set new table name
1128 rTableUpd.m_bModified = true;
1129 }
1130 else if( pFnd != rTableUpd.m_pTable ||
1131 ( rTableUpd.m_pTable != &rTable && &rTable != rTableUpd.m_aData.pDelTable))
1132 rNewStr.append(sTableNm + "."); // keep table name
1133 else
1134 rTableUpd.m_bModified = true;
1135 }
1136 else
1137 rNewStr.append(sTableNm + "."); // keep table name
1138 }
1139 }
1140 if( pTableNmBox == pLastBox )
1141 rFirstBox = rFirstBox.copy( nLastBoxLen + 1 );
1142
1143 SwTableBox* pSttBox = nullptr, *pEndBox = nullptr;
1144 switch (m_eNmType)
1145 {
1146 case INTRNL_NAME:
1147 if( pLastBox )
1148 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->toInt64()));
1149 pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.toInt64()));
1150 break;
1151
1152 case REL_NAME:
1153 {
1154 const SwNode* pNd = GetNodeOfFormula();
1155 const SwTableBox* pBox = pNd ? pTable->GetTableBox(
1156 pNd->FindTableBoxStartNode()->GetIndex() ) : nullptr;
1157 if( pLastBox )
1158 pEndBox = const_cast<SwTableBox*>(lcl_RelToBox( *pTable, pBox, *pLastBox ));
1159 pSttBox = const_cast<SwTableBox*>(lcl_RelToBox( *pTable, pBox, rFirstBox ));
1160 }
1161 break;
1162
1163 case EXTRNL_NAME:
1164 if( pLastBox )
1165 pEndBox = const_cast<SwTableBox*>(pTable->GetTableBox( *pLastBox ));
1166 pSttBox = const_cast<SwTableBox*>(pTable->GetTableBox( rFirstBox ));
1167 break;
1168 }
1169
1170 if( pLastBox && pTable->GetTabSortBoxes().find( pEndBox ) == pTable->GetTabSortBoxes().end() )
1171 pEndBox = nullptr;
1172 if( pTable->GetTabSortBoxes().find( pSttBox ) == pTable->GetTabSortBoxes().end() )
1173 pSttBox = nullptr;
1174
1175 if( TBL_SPLITTBL == rTableUpd.m_eFlags )
1176 {
1177 // Where are the boxes - in the old or in the new table?
1178 bool bInNewTable = false;
1179 if( pLastBox )
1180 {
1181 // It is the "first" box in this selection. It determines if the formula is placed in
1182 // the new or the old table.
1183 sal_uInt16 nEndLnPos = SwTableFormula::GetLnPosInTable( *pTable, pEndBox ),
1184 nSttLnPos = SwTableFormula::GetLnPosInTable( *pTable, pSttBox );
1185
1186 if( USHRT_MAX != nSttLnPos && USHRT_MAX != nEndLnPos &&
1187 ((rTableUpd.m_nSplitLine <= nSttLnPos) ==
1188 (rTableUpd.m_nSplitLine <= nEndLnPos)) )
1189 {
1190 // stay in same table
1191 bInNewTable = rTableUpd.m_nSplitLine <= nEndLnPos &&
1192 pTable == rTableUpd.m_pTable;
1193 }
1194 else
1195 {
1196 // this is definitely an invalid formula, also mark as modified for Undo
1197 rTableUpd.m_bModified = true;
1198 if( pEndBox )
1199 bInNewTable = USHRT_MAX != nEndLnPos &&
1200 rTableUpd.m_nSplitLine <= nEndLnPos &&
1201 pTable == rTableUpd.m_pTable;
1202 }
1203 }
1204 else
1205 {
1206 sal_uInt16 nSttLnPos = SwTableFormula::GetLnPosInTable( *pTable, pSttBox );
1207 // Put it in the new table?
1208 bInNewTable = USHRT_MAX != nSttLnPos &&
1209 rTableUpd.m_nSplitLine <= nSttLnPos &&
1210 pTable == rTableUpd.m_pTable;
1211 }
1212
1213 // formula goes into new table
1214 if( rTableUpd.m_bBehindSplitLine )
1215 {
1216 if( !bInNewTable )
1217 {
1218 rTableUpd.m_bModified = true;
1219 rNewStr.append(rTableUpd.m_pTable->GetFrameFormat()->GetName() + ".");
1220 }
1221 else if( !sTableNm.isEmpty() )
1222 rNewStr.append(sTableNm + ".");
1223 }
1224 else if( bInNewTable )
1225 {
1226 rTableUpd.m_bModified = true;
1227 rNewStr.append(*rTableUpd.m_aData.pNewTableNm + ".");
1228 }
1229 else if( !sTableNm.isEmpty() )
1230 rNewStr.append(sTableNm + ".");
1231 }
1232
1233 if( pLastBox )
1234 rNewStr.append(OUString::number(reinterpret_cast<sal_IntPtr>(pEndBox)) + ":");
1235
1236 rNewStr.append(OUString::number(reinterpret_cast<sal_IntPtr>(pSttBox))
1237 + OUStringChar(rFirstBox[ rFirstBox.getLength()-1] ));
1238}
1239
1242{
1243 const SwTable* pTable;
1244 const SwNode* pNd = GetNodeOfFormula();
1245 if( pNd && nullptr != ( pNd = pNd->FindTableNode() ))
1246 pTable = &static_cast<const SwTableNode*>(pNd)->GetTable();
1247 else
1248 pTable = rTableUpd.m_pTable;
1249
1250 m_sFormula = ScanString( &SwTableFormula::SplitMergeBoxNm_, *pTable, static_cast<void*>(&rTableUpd) );
1252}
1253
1254/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_Unicode cListDelim
Definition: calc.hxx:42
static OUString lcl_BoxNmToRel(const SwTable &rTable, const SwTableNode &rTableNd, const OUString &sRefBoxNm, const OUString &sGetStr, bool bExtrnlNm)
Definition: cellfml.cxx:885
static const SwTableBox * lcl_RelToBox(const SwTable &rTable, const SwTableBox *pRefBox, const OUString &sGetName)
Definition: cellfml.cxx:799
static sal_Int32 lcl_GetLongBoxNum(OUString &rStr)
Definition: cellfml.cxx:782
static const SwFrame * lcl_GetBoxFrame(const SwTableBox &rBox)
Definition: cellfml.cxx:772
sal_uInt32 GetValue() const
virtual const SwRootFrame * GetCurrentLayout() const =0
SvNumFormatType GetType(sal_uInt32 nFIndex) const
Definition: calc.hxx:200
OUString GetStrResult(const SwSbxValue &rValue)
Definition: calc.cxx:391
void SetCalcError(SwCalcError eErr)
Definition: calc.hxx:255
SwSbxValue Calculate(const OUString &rStr)
Definition: calc.cxx:363
bool IsCalcError() const
Definition: calc.hxx:256
bool IsCalcNotANumber() const
Definition: calc.hxx:257
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1223
Definition: doc.hxx:197
const sw::TableFrameFormats * GetTableFrameFormats() const
Definition: doc.hxx:826
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:419
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1337
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1429
bool IsNumberFormat(const OUString &aString, sal_uInt32 &F_Index, double &fOutNumber)
Definition: ndtbl.cxx:4025
SwFieldIds Which() const
Definition: fldbas.hxx:276
Base class of all fields.
Definition: fldbas.hxx:296
OUString ExpandField(bool bCached, SwRootFrame const *pLayout) const
expand the field.
Definition: fldbas.cxx:491
SwFieldType * GetTyp() const
Definition: fldbas.hxx:402
const SwField * GetField() const
Definition: fmtfld.hxx:131
const SwTableBoxNumFormat & GetTableBoxNumFormat(bool=true) const
TableBox attributes - implemented in cellatr.hxx.
Definition: cellatr.hxx:122
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const OUString & GetName() const
Definition: format.hxx:131
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:385
const SwTableBoxValue & GetTableBoxValue(bool=true) const
Definition: cellatr.hxx:126
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:447
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
Templatized version of GetItemState() to directly return the correct type.
Definition: format.hxx:111
Style of a layout element.
Definition: frmfmt.hxx:72
Base class of the Writer layout elements.
Definition: frame.hxx:315
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1105
SwLayoutFrame * GetUpper()
Definition: frame.hxx:684
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame.
Definition: layfrm.hxx:36
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNodes & GetNodes() const
Definition: ndindex.hxx:119
Base class of the Writer document model elements.
Definition: node.hxx:98
SwNodeOffset GetIndex() const
Definition: node.hxx:312
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:218
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:706
SwDoc & GetDoc()
Definition: node.hxx:233
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
bool IsDocNodes() const
Is the NodesArray the regular one of Doc? (and not the UndoNds, ...) Implementation in doc....
Definition: nodes.cxx:2555
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
The root element of a Writer document layout.
Definition: rootfrm.hxx:85
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:49
const SwTable * GetTable() const
Definition: tabfrm.hxx:162
double GetValue() const
Definition: cellatr.hxx:112
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:443
SwTableLine * GetUpper()
Definition: swtable.hxx:477
sal_Int32 getRowSpan() const
Definition: swtable.hxx:540
OUString GetName() const
Definition: swtable.cxx:2189
const SwStartNode * m_pStartNode
Definition: swtable.hxx:452
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:481
SwTableLines & GetTabLines()
Definition: swtable.hxx:474
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:495
double GetValue(SwTableCalcPara &rPara) const
Get value of this box.
Definition: cellfml.cxx:83
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:2094
SwCalc & m_rCalc
current Calculator
Definition: cellfml.hxx:47
sal_uInt16 m_nStackCount
Definition: cellfml.hxx:42
SwTableCalcPara(SwCalc &rCalculator, const SwTable &rTable, SwRootFrame const *pLayout)
Definition: cellfml.cxx:271
void SetLastTableBox(const SwTableBox *pBox)
Definition: cellfml.hxx:57
sal_uInt16 m_nMaxSize
Definition: cellfml.hxx:42
void DecStackCnt()
Definition: cellfml.hxx:56
const SwTableBox * m_pLastTableBox
Definition: cellfml.hxx:41
bool CalcWithStackOverflow()
Definition: cellfml.cxx:287
std::unique_ptr< SwTableSortBoxes > m_pBoxStack
stack for recognizing recursion
Definition: cellfml.hxx:46
const SwTable * m_pTable
current table
Definition: cellfml.hxx:48
bool IsStackOverflow() const
Definition: cellfml.hxx:54
SwRootFrame const *const m_pLayout
layout to access text field results
Definition: cellfml.hxx:45
bool IncStackCnt()
Definition: cellfml.hxx:55
void CalcField(SwTableCalcPara &rCalcPara)
Definition: tblcalc.cxx:43
sal_uInt16 m_nSplitLine
Split: from this BaseLine on will be split.
Definition: hints.hxx:315
TableFormulaUpdateFlags m_eFlags
Definition: hints.hxx:316
union SwTableFormulaUpdate::@23 m_aData
const OUString * pNewTableNm
Split: the name of the new table.
Definition: hints.hxx:313
const SwTable * m_pTable
Pointer to the current table.
Definition: hints.hxx:310
const SwTable * pDelTable
Merge: Pointer to the table to be removed.
Definition: hints.hxx:312
void RelNmsToBoxNms(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:427
static sal_uInt16 GetLnPosInTable(const SwTable &rTable, const SwTableBox *pBox)
Definition: cellfml.cxx:1082
void RelBoxNmsToPtr(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:460
void ToRelBoxNm(const SwTable *pTable)
create from the external/internal formula the relative formula
Definition: cellfml.cxx:630
OUString ScanString(FnScanFormula fnFormula, const SwTable &rTable, void *) const
Definition: cellfml.cxx:651
OUString m_sFormula
current formula
Definition: cellfml.hxx:94
void GetBoxesOfFormula(const SwTable &rTable, SwSelBoxes &rBoxes)
Definition: cellfml.cxx:924
void(SwTableFormula::* FnScanFormula)(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *) const
Definition: cellfml.hxx:62
void BoxNmsToPtr(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:558
SwTableFormula(OUString aFormula)
Definition: cellfml.cxx:324
void PtrToBoxNms(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:526
void BoxNmToPtr(const SwTable *pTable)
create from the external formula the internal
Definition: cellfml.cxx:605
void MakeFormula_(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:335
void SplitMergeBoxNm_(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:1095
bool HasValidBoxes() const
Definition: cellfml.cxx:1072
void HasValidBoxes_(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Are all boxes valid that are referenced by the formula?
Definition: cellfml.cxx:1024
void ToSplitMergeBoxNm(SwTableFormulaUpdate &rTableUpd)
gets called before/after merging/splitting of tables
Definition: cellfml.cxx:1241
NameType m_eNmType
current display method
Definition: cellfml.hxx:95
bool IsValid() const
Definition: cellfml.hxx:134
void GetFormulaBoxes(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:933
virtual ~SwTableFormula()
Definition: cellfml.cxx:331
void PtrToBoxNm(const SwTable *pTable)
create from the internal formula (for CORE) the external formula (for UI)
Definition: cellfml.cxx:580
void BoxNmsToRelNm(const SwTable &, OUStringBuffer &, OUString &, OUString *, void *pPara) const
Definition: cellfml.cxx:492
static void GetBoxes(const SwTableBox &rStt, const SwTableBox &rEnd, SwSelBoxes &rBoxes)
Definition: cellfml.cxx:967
virtual const SwNode * GetNodeOfFormula() const =0
static const SwTable * FindTable(SwDoc &rDoc, std::u16string_view rNm)
Definition: cellfml.cxx:749
SwTableLine is one table row in the document model.
Definition: swtable.hxx:376
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:386
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:388
SwTableBox * GetUpper()
Definition: swtable.hxx:394
size_type size() const
Definition: swtable.hxx:76
SwTableLine * front() const
Definition: swtable.hxx:81
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:98
bool empty() const
Definition: swtable.hxx:75
const SwTable & GetTable() const
Definition: node.hxx:542
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableLines & GetTabLines()
Definition: swtable.hxx:206
bool IsHeadline(const SwTableLine &rLine) const
Definition: tabfrm.cxx:6009
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:209
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1344
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:2308
static sal_uInt16 GetBoxNum(OUString &rStr, bool bFirst=false, const bool bPerformValidCheck=false)
Definition: swtable.cxx:1284
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:201
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:267
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
OUString GetFieldContent() const
Definition: atrfld.cxx:717
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
SwTextAttr * GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, ::sw::GetTextAttrMode const eMode=::sw::GetTextAttrMode::Default) const
get the innermost text attribute covering position nIndex.
Definition: ndtxt.cxx:1804
const OUString & GetText() const
Definition: ndtxt.hxx:244
OUString GetRedlineText() const
Definition: ndtxt.cxx:3737
SwTextAttr * GetTextAttrForCharAt(const sal_Int32 nIndex, const sal_uInt16 nWhich=RES_TXTATR_END) const
get the text attribute at position nIndex which owns the dummy character CH_TXTATR_* at that position...
Definition: ndtxt.cxx:3155
The non-shared part of a user field.
Definition: usrfld.hxx:106
virtual double GetValue() const
Definition: fldbas.cxx:799
const_iterator begin() const
const_iterator find(const Value &x) const
size_type erase(const Value &x)
const_iterator end() const
size_type size() const
std::pair< const_iterator, bool > insert(Value &&x)
size_t size() const
OString sFormula
#define CH_TXT_ATR_INPUTFIELDSTART
Definition: hintids.hxx:178
constexpr sal_uInt16 RES_BOXATR_END(159)
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(158)
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(157)
constexpr sal_uInt16 RES_BOXATR_BEGIN(RES_GRFATR_END)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:175
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:174
@ TBL_MERGETBL
Definition: hints.hxx:304
@ TBL_SPLITTBL
Definition: hints.hxx:305
sal_Int64 n
sal_uInt16 nPos
aStr
sal_Int32 getTokenCount(std::string_view rIn, char cTok)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
long Long
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:105
void GetTableSel(const SwCursorShell &rShell, SwSelBoxes &rBoxes, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:149
sal_uInt16 sal_Unicode
SvNumFormatType