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