summaryrefslogtreecommitdiffstats
path: root/sw/source/core/bastyp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/core/bastyp
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/bastyp')
-rw-r--r--sw/source/core/bastyp/SwSmartTagMgr.cxx71
-rw-r--r--sw/source/core/bastyp/bparr.cxx505
-rw-r--r--sw/source/core/bastyp/breakit.cxx184
-rw-r--r--sw/source/core/bastyp/calc.cxx1442
-rw-r--r--sw/source/core/bastyp/checkit.cxx33
-rw-r--r--sw/source/core/bastyp/index.cxx392
-rw-r--r--sw/source/core/bastyp/init.cxx811
-rw-r--r--sw/source/core/bastyp/proofreadingiterator.cxx67
-rw-r--r--sw/source/core/bastyp/swcache.cxx506
-rw-r--r--sw/source/core/bastyp/swrect.cxx202
-rw-r--r--sw/source/core/bastyp/swregion.cxx229
-rw-r--r--sw/source/core/bastyp/swtypes.cxx66
-rw-r--r--sw/source/core/bastyp/tabcol.cxx85
13 files changed, 4593 insertions, 0 deletions
diff --git a/sw/source/core/bastyp/SwSmartTagMgr.cxx b/sw/source/core/bastyp/SwSmartTagMgr.cxx
new file mode 100644
index 0000000000..3a28af822d
--- /dev/null
+++ b/sw/source/core/bastyp/SwSmartTagMgr.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <SwSmartTagMgr.hxx>
+
+#include <docsh.hxx>
+#include <swmodule.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+rtl::Reference<SwSmartTagMgr> SwSmartTagMgr::spTheSwSmartTagMgr;
+
+SwSmartTagMgr& SwSmartTagMgr::Get()
+{
+ if (!spTheSwSmartTagMgr)
+ {
+ OUString sModuleName
+ = !utl::ConfigManager::IsFuzzing() ? SwDocShell::Factory().GetModuleName() : "Writer";
+ spTheSwSmartTagMgr = new SwSmartTagMgr(sModuleName);
+ spTheSwSmartTagMgr->Init(u"Writer");
+ }
+ return *spTheSwSmartTagMgr;
+}
+
+SwSmartTagMgr::SwSmartTagMgr(const OUString& rModuleName)
+ : SmartTagMgr(rModuleName)
+{
+}
+
+SwSmartTagMgr::~SwSmartTagMgr() {}
+
+void SwSmartTagMgr::modified(const lang::EventObject& rEO)
+{
+ SolarMutexGuard aGuard;
+
+ // Installed recognizers have changed. We remove all existing smart tags:
+ SwModule::CheckSpellChanges(false, true, true, true);
+
+ SmartTagMgr::modified(rEO);
+}
+
+void SwSmartTagMgr::changesOccurred(const util::ChangesEvent& rEvent)
+{
+ SolarMutexGuard aGuard;
+
+ // Configuration has changed. We remove all existing smart tags:
+ SwModule::CheckSpellChanges(false, true, true, true);
+
+ SmartTagMgr::changesOccurred(rEvent);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/bparr.cxx b/sw/source/core/bastyp/bparr.cxx
new file mode 100644
index 0000000000..b99385bfd3
--- /dev/null
+++ b/sw/source/core/bastyp/bparr.cxx
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <bparr.hxx>
+#include <tools/long.hxx>
+#include <limits.h>
+#include <string.h>
+
+/** Resize block management by this constant.
+ As a result there are approx. 20 * MAXENTRY == 20000 entries available */
+const sal_uInt16 nBlockGrowSize = 20;
+
+#if OSL_DEBUG_LEVEL > 2
+#define CHECKIDX( p, n, i, c ) CheckIdx( p, n, i, c );
+void CheckIdx( BlockInfo** ppInf, sal_uInt16 nBlock, sal_Int32 nSize, sal_uInt16 nCur )
+{
+ assert( !nSize || nCur < nBlock ); // BigPtrArray: CurIndex invalid
+
+ sal_Int32 nIdx = 0;
+ for( sal_uInt16 nCnt = 0; nCnt < nBlock; ++nCnt, ++ppInf )
+ {
+ nIdx += (*ppInf)->nElem;
+ // Array with holes is not allowed
+ assert( !nCnt || (*(ppInf-1))->nEnd + 1 == (*ppInf)->nStart );
+ }
+ assert(nIdx == nSize); // invalid count in nSize
+}
+#else
+#define CHECKIDX( p, n, i, c )
+#endif
+
+BigPtrArray::BigPtrArray()
+{
+ m_nBlock = m_nCur = 0;
+ m_nSize = 0;
+ m_nMaxBlock = nBlockGrowSize;
+ m_ppInf.reset( new BlockInfo* [ m_nMaxBlock ] );
+}
+
+BigPtrArray::~BigPtrArray()
+{
+ if( m_nBlock )
+ {
+ BlockInfo** pp = m_ppInf.get();
+ for( sal_uInt16 n = 0; n < m_nBlock; ++n, ++pp )
+ {
+ delete *pp;
+ }
+ }
+}
+
+// Also moving is done simply here. Optimization is useless because of the
+// division of this field into multiple parts.
+void BigPtrArray::Move( sal_Int32 from, sal_Int32 to )
+{
+ if (from != to)
+ {
+ sal_uInt16 cur = Index2Block( from );
+ BlockInfo* p = m_ppInf[ cur ];
+ BigPtrEntry* pElem = p->mvData[ from - p->nStart ];
+ Insert( pElem, to ); // insert first, then delete!
+ Remove( ( to < from ) ? ( from + 1 ) : from );
+ }
+}
+
+BigPtrEntry* BigPtrArray::operator[]( sal_Int32 idx ) const
+{
+ assert(idx < m_nSize); // operator[]: Index out of bounds
+ m_nCur = Index2Block( idx );
+ BlockInfo* p = m_ppInf[ m_nCur ];
+ return p->mvData[ idx - p->nStart ];
+}
+
+/** Search a block at a given position */
+sal_uInt16 BigPtrArray::Index2Block( sal_Int32 pos ) const
+{
+ // last used block?
+ BlockInfo* p = m_ppInf[ m_nCur ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return m_nCur;
+ // Index = 0?
+ if( !pos )
+ return 0;
+
+ // following one?
+ if( m_nCur < ( m_nBlock - 1 ) )
+ {
+ p = m_ppInf[ m_nCur+1 ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return m_nCur+1;
+ }
+ // previous one?
+ else if( pos < p->nStart && m_nCur > 0 )
+ {
+ p = m_ppInf[ m_nCur-1 ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return m_nCur-1;
+ }
+
+ // binary search: always successful
+ sal_uInt16 lower = 0, upper = m_nBlock - 1;
+ sal_uInt16 cur = 0;
+ for(;;)
+ {
+ sal_uInt16 n = lower + ( upper - lower ) / 2;
+ cur = ( n == cur ) ? n+1 : n;
+ p = m_ppInf[ cur ];
+ if( p->nStart <= pos && p->nEnd >= pos )
+ return cur;
+
+ if( p->nStart > pos )
+ upper = cur;
+ else
+ lower = cur;
+ }
+}
+
+/** Update all index areas
+
+ @param pos last correct block (starting point)
+*/
+void BigPtrArray::UpdIndex( sal_uInt16 pos )
+{
+ BlockInfo** pp = m_ppInf.get() + pos;
+ sal_Int32 idx = (*pp)->nEnd + 1;
+ while( ++pos < m_nBlock )
+ {
+ BlockInfo* p = *++pp;
+ p->nStart = idx;
+ idx += p->nElem;
+ p->nEnd = idx - 1;
+ }
+}
+
+/** Create and insert new block
+
+ Existing blocks will be moved rearward.
+
+ @param pos Position at which the new block should be created.
+*/
+BlockInfo* BigPtrArray::InsBlock( sal_uInt16 pos )
+{
+ if( m_nBlock == m_nMaxBlock )
+ {
+ // than extend the array first
+ BlockInfo** ppNew = new BlockInfo* [ m_nMaxBlock + nBlockGrowSize ];
+ memcpy( ppNew, m_ppInf.get(), m_nMaxBlock * sizeof( BlockInfo* ));
+ m_nMaxBlock += nBlockGrowSize;
+ m_ppInf.reset( ppNew );
+ }
+ if( pos != m_nBlock )
+ {
+ memmove( m_ppInf.get() + pos+1, m_ppInf.get() + pos,
+ ( m_nBlock - pos ) * sizeof( BlockInfo* ));
+ }
+ ++m_nBlock;
+ BlockInfo* p = new BlockInfo;
+ m_ppInf[ pos ] = p;
+
+ if( pos )
+ p->nStart = p->nEnd = m_ppInf[ pos-1 ]->nEnd + 1;
+ else
+ p->nStart = p->nEnd = 0;
+
+ p->nEnd--; // no elements
+ p->nElem = 0;
+ p->pBigArr = this;
+ return p;
+}
+
+void BigPtrArray::BlockDel( sal_uInt16 nDel )
+{
+ m_nBlock = m_nBlock - nDel;
+ if( m_nMaxBlock - m_nBlock > nBlockGrowSize )
+ {
+ // than shrink array
+ nDel = (( m_nBlock / nBlockGrowSize ) + 1 ) * nBlockGrowSize;
+ BlockInfo** ppNew = new BlockInfo* [ nDel ];
+ memcpy( ppNew, m_ppInf.get(), m_nBlock * sizeof( BlockInfo* ));
+ m_ppInf.reset( ppNew );
+ m_nMaxBlock = nDel;
+ }
+}
+
+void BigPtrArray::Insert( BigPtrEntry* pElem, sal_Int32 pos )
+{
+ CHECKIDX( m_ppInf.get(), m_nBlock, m_nSize, m_nCur );
+
+ BlockInfo* p;
+ sal_uInt16 cur;
+ if( !m_nSize )
+ {
+ // special case: insert first element
+ cur = 0;
+ p = InsBlock( cur );
+ }
+ else if( pos == m_nSize )
+ {
+ // special case: insert at end
+ cur = m_nBlock - 1;
+ p = m_ppInf[ cur ];
+ if( p->nElem == MAXENTRY )
+ // the last block is full, create a new one
+ p = InsBlock( ++cur );
+ }
+ else
+ {
+ // standard case:
+ cur = Index2Block( pos );
+ p = m_ppInf[ cur ];
+ }
+
+ if( p->nElem == MAXENTRY )
+ {
+ // does the last entry fit into the next block?
+ BlockInfo* q;
+ if( cur < ( m_nBlock - 1 ) && m_ppInf[ cur+1 ]->nElem < MAXENTRY )
+ {
+ q = m_ppInf[ cur+1 ];
+ if( q->nElem )
+ {
+ int nCount = q->nElem;
+ auto pFrom = q->mvData.begin() + nCount;
+ auto pTo = pFrom + 1;
+ while( nCount-- )
+ {
+ *--pTo = *--pFrom;
+ ++((*pTo)->m_nOffset);
+ }
+ }
+ q->nStart--;
+ q->nEnd--;
+ }
+ else
+ {
+ // If it does not fit, then insert a new block. But if there is more
+ // than 50% space in the array then compress first.
+ if( /*nBlock == nMaxBlock &&*/
+ m_nBlock > ( m_nSize / ( MAXENTRY / 2 ) ) &&
+ cur >= Compress() )
+ {
+ // Something was moved before the current position and all
+ // pointer might be invalid. Thus restart Insert.
+ Insert( pElem, pos );
+ return ;
+ }
+
+ q = InsBlock( cur+1 );
+ }
+
+ // entry does not fit anymore - clear space
+ BigPtrEntry* pLast = p->mvData[ MAXENTRY-1 ];
+ pLast->m_nOffset = 0;
+ pLast->m_pBlock = q;
+
+ q->mvData[ 0 ] = pLast;
+ q->nElem++;
+ q->nEnd++;
+
+ p->nEnd--;
+ p->nElem--;
+ }
+ // now we have free space - insert
+ pos -= p->nStart;
+ assert(pos < MAXENTRY);
+ if( pos != p->nElem )
+ {
+ int nCount = p->nElem - sal_uInt16(pos);
+ auto pFrom = p->mvData.begin() + p->nElem;
+ auto pTo = pFrom + 1;
+ while( nCount-- )
+ {
+ *--pTo = *--pFrom;
+ ++( *pTo )->m_nOffset;
+ }
+ }
+ // insert element and update indices
+ pElem->m_nOffset = sal_uInt16(pos);
+ pElem->m_pBlock = p;
+ p->mvData[ pos ] = pElem;
+ p->nEnd++;
+ p->nElem++;
+ m_nSize++;
+ if( cur != ( m_nBlock - 1 ) ) UpdIndex( cur );
+ m_nCur = cur;
+
+ CHECKIDX( m_ppInf.get(), m_nBlock, m_nSize, m_nCur );
+}
+
+void BigPtrArray::Remove( sal_Int32 pos, sal_Int32 n )
+{
+ CHECKIDX( m_ppInf.get(), m_nBlock, m_nSize, m_nCur );
+
+ sal_uInt16 nBlkdel = 0; // deleted blocks
+ sal_uInt16 cur = Index2Block( pos ); // current block number
+ sal_uInt16 nBlk1 = cur; // 1st treated block
+ sal_uInt16 nBlk1del = USHRT_MAX; // 1st deleted block
+ BlockInfo* p = m_ppInf[ cur ];
+ pos -= p->nStart;
+
+ sal_Int32 nElem = n;
+ while( nElem )
+ {
+ sal_uInt16 nel = p->nElem - sal_uInt16(pos);
+ if( sal_Int32(nel) > nElem )
+ nel = sal_uInt16(nElem);
+ // move elements if needed
+ if( ( pos + nel ) < sal_Int32(p->nElem) )
+ {
+ auto pTo = p->mvData.begin() + pos;
+ auto pFrom = pTo + nel;
+ int nCount = p->nElem - nel - sal_uInt16(pos);
+ while( nCount-- )
+ {
+ *pTo = *pFrom++;
+ (*pTo)->m_nOffset = (*pTo)->m_nOffset - nel;
+ ++pTo;
+ }
+ }
+ p->nEnd -= nel;
+ p->nElem = p->nElem - nel;
+ // possibly delete block completely
+ if( !p->nElem )
+ {
+ nBlkdel++;
+ if( USHRT_MAX == nBlk1del )
+ nBlk1del = cur;
+ }
+ nElem -= nel;
+ if( !nElem )
+ break;
+ p = m_ppInf[ ++cur ];
+ pos = 0;
+ }
+
+ // update table if blocks were removed
+ if( nBlkdel )
+ {
+ for( sal_uInt16 i = nBlk1del; i < ( nBlk1del + nBlkdel ); i++ )
+ delete m_ppInf[ i ];
+
+ if( ( nBlk1del + nBlkdel ) < m_nBlock )
+ {
+ memmove( m_ppInf.get() + nBlk1del, m_ppInf.get() + nBlk1del + nBlkdel,
+ ( m_nBlock - nBlkdel - nBlk1del ) * sizeof( BlockInfo* ) );
+
+ // UpdateIdx updates the successor thus start before first elem
+ if( !nBlk1 )
+ {
+ p = m_ppInf[ 0 ];
+ p->nStart = 0;
+ p->nEnd = p->nElem-1;
+ }
+ else
+ {
+ --nBlk1;
+ }
+ }
+ BlockDel( nBlkdel ); // blocks were deleted
+ }
+
+ m_nSize -= n;
+ if( nBlk1 != ( m_nBlock - 1 ) && m_nSize )
+ UpdIndex( nBlk1 );
+ m_nCur = nBlk1;
+
+ // call Compress() if there is more than 50% space in the array
+ if( m_nBlock > ( m_nSize / ( MAXENTRY / 2 ) ) )
+ Compress();
+
+ CHECKIDX( m_ppInf.get(), m_nBlock, m_nSize, m_nCur );
+}
+
+void BigPtrArray::Replace( sal_Int32 idx, BigPtrEntry* pElem)
+{
+ assert(idx < m_nSize); // Index out of bounds
+ m_nCur = Index2Block( idx );
+ BlockInfo* p = m_ppInf[ m_nCur ];
+ pElem->m_nOffset = sal_uInt16(idx - p->nStart);
+ pElem->m_pBlock = p;
+ p->mvData[ idx - p->nStart ] = pElem;
+}
+
+/** Compress the array */
+sal_uInt16 BigPtrArray::Compress()
+{
+ CHECKIDX( m_ppInf.get(), m_nBlock, m_nSize, m_nCur );
+
+ // Iterate over InfoBlock array from beginning to end. If there is a deleted
+ // block in between so move all following ones accordingly. The pointer <pp>
+ // represents the "old" and <qq> the "new" array.
+ BlockInfo** pp = m_ppInf.get(), **qq = pp;
+ BlockInfo* p;
+ BlockInfo* pLast(nullptr); // last empty block
+ sal_uInt16 nLast = 0; // missing elements
+ sal_uInt16 nBlkdel = 0; // number of deleted blocks
+ sal_uInt16 nFirstChgPos = USHRT_MAX; // at which position was the 1st change?
+
+ // convert fill percentage into number of remaining elements
+ short const nMax = MAXENTRY - tools::Long(MAXENTRY) * COMPRESSLVL / 100;
+
+ for( sal_uInt16 cur = 0; cur < m_nBlock; ++cur )
+ {
+ p = *pp++;
+ sal_uInt16 n = p->nElem;
+ // Check if a not completely full block will be ignored. This happens if
+ // the current block would have to be split but the filling of the
+ // inspected block is already over its threshold value. In this case we
+ // do not fill more (it's expensive because of a double memmove() call)
+ if( nLast && ( n > nLast ) && ( nLast < nMax ) )
+ nLast = 0;
+ if( nLast )
+ {
+ if( USHRT_MAX == nFirstChgPos )
+ nFirstChgPos = cur;
+
+ // Not full yet? Then fill up.
+ if( n > nLast )
+ n = nLast;
+
+ // move elements from current to last block
+ auto pElem = pLast->mvData.begin() + pLast->nElem;
+ auto pFrom = p->mvData.begin();
+ for( sal_uInt16 nCount = n, nOff = pLast->nElem;
+ nCount; --nCount, ++pElem )
+ {
+ *pElem = *pFrom++;
+ (*pElem)->m_pBlock = pLast;
+ (*pElem)->m_nOffset = nOff++;
+ }
+
+ // adjustment
+ pLast->nElem = pLast->nElem + n;
+ nLast = nLast - n;
+ p->nElem = p->nElem - n;
+
+ // Is the current block now empty as a result?
+ if( !p->nElem )
+ {
+ // then remove
+ delete p;
+ p = nullptr;
+ ++nBlkdel;
+ }
+ else
+ {
+ pElem = p->mvData.begin();
+ pFrom = pElem + n;
+ int nCount = p->nElem;
+ while( nCount-- )
+ {
+ *pElem = *pFrom++;
+ (*pElem)->m_nOffset = (*pElem)->m_nOffset - n;
+ ++pElem;
+ }
+ }
+ }
+
+ if( p ) // BlockInfo was not deleted
+ {
+ *qq++ = p; // adjust to correct position
+
+ // keep the potentially existing last half-full block
+ if( !nLast && p->nElem < MAXENTRY )
+ {
+ pLast = p;
+ nLast = MAXENTRY - p->nElem;
+ }
+ }
+ }
+
+ // if blocks were deleted shrink BlockInfo array if needed
+ if( nBlkdel )
+ BlockDel( nBlkdel );
+
+ // and re-index
+ p = m_ppInf[ 0 ];
+ p->nEnd = p->nElem - 1;
+ UpdIndex( 0 );
+
+ if( m_nCur >= nFirstChgPos )
+ m_nCur = 0;
+
+ CHECKIDX( m_ppInf.get(), m_nBlock, m_nSize, m_nCur );
+
+ return nFirstChgPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/breakit.cxx b/sw/source/core/bastyp/breakit.cxx
new file mode 100644
index 0000000000..33f55a1d54
--- /dev/null
+++ b/sw/source/core/bastyp/breakit.cxx
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <breakit.hxx>
+#include <swtypes.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/BreakIterator.hpp>
+#include <svl/languageoptions.hxx>
+#include <unicode/uchar.h>
+#include <unotools/localedatawrapper.hxx>
+#include <algorithm>
+#include <utility>
+
+using namespace com::sun::star;
+
+SwBreakIt* g_pBreakIt = nullptr;
+
+void SwBreakIt::Create_( const uno::Reference<uno::XComponentContext> & rxContext )
+{
+ delete g_pBreakIt;
+ g_pBreakIt = new SwBreakIt( rxContext );
+}
+
+void SwBreakIt::Delete_()
+{
+ delete g_pBreakIt;
+ g_pBreakIt = nullptr;
+}
+
+SwBreakIt * SwBreakIt::Get()
+{
+ return g_pBreakIt;
+}
+
+SwBreakIt::SwBreakIt( uno::Reference<uno::XComponentContext> xContext )
+ : m_xContext(std::move(xContext))
+ , m_xBreak(i18n::BreakIterator::create(m_xContext))
+ , m_aForbiddenLang(LANGUAGE_DONTKNOW)
+{
+}
+
+void SwBreakIt::GetLocale_( const LanguageType aLang )
+{
+ if (m_xLanguageTag)
+ m_xLanguageTag->reset(aLang);
+ else
+ m_xLanguageTag.reset(new LanguageTag(aLang));
+}
+
+void SwBreakIt::GetLocale_( const LanguageTag& rLanguageTag )
+{
+ if (m_xLanguageTag)
+ *m_xLanguageTag = rLanguageTag;
+ else
+ m_xLanguageTag.reset(new LanguageTag(rLanguageTag));
+}
+
+void SwBreakIt::GetForbidden_( const LanguageType aLang )
+{
+ LocaleDataWrapper aWrap(m_xContext, GetLanguageTag(aLang));
+
+ m_aForbiddenLang = aLang;
+ m_oForbidden.emplace(aWrap.getForbiddenCharacters());
+}
+
+sal_uInt16 SwBreakIt::GetRealScriptOfText( const OUString& rText, sal_Int32 nPos ) const
+{
+ sal_uInt16 nScript = i18n::ScriptType::WEAK;
+ if (!rText.isEmpty())
+ {
+ if( nPos && nPos == rText.getLength() )
+ --nPos;
+ else if( nPos < 0)
+ nPos = 0;
+
+ nScript = m_xBreak->getScriptType(rText, nPos);
+ sal_Int32 nChgPos = 0;
+ if (i18n::ScriptType::WEAK == nScript && nPos >= 0 && nPos + 1 < rText.getLength())
+ {
+ // A weak character followed by a mark may be meant to combine with
+ // the mark, so prefer the following character's script
+ switch (u_charType(rText[nPos + 1]))
+ {
+ case U_NON_SPACING_MARK:
+ case U_ENCLOSING_MARK:
+ case U_COMBINING_SPACING_MARK:
+ nScript = m_xBreak->getScriptType(rText, nPos+1);
+ break;
+ }
+ }
+ if( i18n::ScriptType::WEAK == nScript && nPos )
+ {
+ nChgPos = m_xBreak->beginOfScript(rText, nPos, nScript);
+ if( 0 < nChgPos )
+ nScript = m_xBreak->getScriptType(rText, nChgPos-1);
+ }
+
+ if( i18n::ScriptType::WEAK == nScript )
+ {
+ nChgPos = m_xBreak->endOfScript(rText, nPos, nScript);
+ if( rText.getLength() > nChgPos && 0 <= nChgPos )
+ nScript = m_xBreak->getScriptType(rText, nChgPos);
+ }
+ }
+ if( i18n::ScriptType::WEAK == nScript )
+ nScript = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() );
+ return nScript;
+}
+
+SvtScriptType SwBreakIt::GetAllScriptsOfText( const OUString& rText ) const
+{
+ const SvtScriptType coAllScripts = SvtScriptType::LATIN |
+ SvtScriptType::ASIAN |
+ SvtScriptType::COMPLEX;
+ SvtScriptType nRet = SvtScriptType::NONE;
+ sal_uInt16 nScript = 0;
+ if (!rText.isEmpty())
+ {
+ for( sal_Int32 n = 0, nEnd = rText.getLength(); n < nEnd;
+ n = m_xBreak->endOfScript(rText, n, nScript) )
+ {
+ nScript = m_xBreak->getScriptType(rText, n);
+ switch( nScript )
+ {
+ case i18n::ScriptType::LATIN: nRet |= SvtScriptType::LATIN; break;
+ case i18n::ScriptType::ASIAN: nRet |= SvtScriptType::ASIAN; break;
+ case i18n::ScriptType::COMPLEX: nRet |= SvtScriptType::COMPLEX; break;
+ case i18n::ScriptType::WEAK:
+ if( nRet == SvtScriptType::NONE )
+ nRet |= coAllScripts;
+ break;
+ }
+ if( coAllScripts == nRet )
+ break;
+ }
+ }
+ return nRet;
+}
+
+sal_Int32 SwBreakIt::getGraphemeCount(const OUString& rText,
+ sal_Int32 nStart, sal_Int32 nEnd) const
+{
+ sal_Int32 nGraphemeCount = 0;
+
+ sal_Int32 nCurPos = std::max(static_cast<sal_Int32>(0), nStart);
+ while (nCurPos < nEnd)
+ {
+ // fdo#49208 cheat and assume that nothing can combine with a space
+ // to form a single grapheme
+ if (rText[nCurPos] == ' ')
+ {
+ ++nCurPos;
+ }
+ else
+ {
+ sal_Int32 nCount2 = 1;
+ nCurPos = m_xBreak->nextCharacters(rText, nCurPos, lang::Locale(),
+ i18n::CharacterIteratorMode::SKIPCELL, nCount2, nCount2);
+ }
+ ++nGraphemeCount;
+ }
+
+ return nGraphemeCount;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/calc.cxx b/sw/source/core/bastyp/calc.cxx
new file mode 100644
index 0000000000..0c9643317a
--- /dev/null
+++ b/sw/source/core/bastyp/calc.cxx
@@ -0,0 +1,1442 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+#include <config_fuzzers.h>
+
+#include <calc.hxx>
+#include <cfloat>
+#include <climits>
+#include <memory>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <cstdlib>
+#include <dbmgr.hxx>
+#include <docfld.hxx>
+#include <docstat.hxx>
+#include <doc.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <editeng/langitem.hxx>
+#include <expfld.hxx>
+#include <hintids.hxx>
+#include <o3tl/temporary.hxx>
+#include <osl/diagnose.h>
+#include <rtl/math.hxx>
+#include <shellres.hxx>
+#include <svl/numformat.hxx>
+#include <svl/languageoptions.hxx>
+#include <swmodule.hxx>
+#include <swtypes.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/useroptions.hxx>
+#include <usrfld.hxx>
+#include <utility>
+#include <viewsh.hxx>
+#include <com/sun/star/i18n/KParseTokens.hpp>
+#include <com/sun/star/i18n/KParseType.hpp>
+
+using namespace ::com::sun::star;
+
+const char sCalc_Add[] = "add";
+const char sCalc_Sub[] = "sub";
+const char sCalc_Mul[] = "mul";
+const char sCalc_Div[] = "div";
+const char sCalc_Phd[] = "phd";
+const char sCalc_Sqrt[] = "sqrt";
+const char sCalc_Pow[] = "pow";
+const char sCalc_Or[] = "or";
+const char sCalc_Xor[] = "xor";
+const char sCalc_And[] = "and";
+const char sCalc_Not[] = "not";
+const char sCalc_Eq[] = "eq";
+const char sCalc_Neq[] = "neq";
+const char sCalc_Leq[] = "leq";
+const char sCalc_Geq[] = "geq";
+const char sCalc_L[] = "l";
+const char sCalc_G[] = "g";
+const char sCalc_Sum[] = "sum";
+const char sCalc_Mean[] = "mean";
+const char sCalc_Min[] = "min";
+const char sCalc_Max[] = "max";
+const char sCalc_Sin[] = "sin";
+const char sCalc_Cos[] = "cos";
+const char sCalc_Tan[] = "tan";
+const char sCalc_Asin[] = "asin";
+const char sCalc_Acos[] = "acos";
+const char sCalc_Atan[] = "atan";
+const char sCalc_Round[]= "round";
+const char sCalc_Date[] = "date";
+const char sCalc_Product[] = "product";
+const char sCalc_Average[] = "average";
+const char sCalc_Count[]= "count";
+const char sCalc_Sign[] = "sign";
+const char sCalc_Abs[] = "abs";
+const char sCalc_Int[] = "int";
+
+// ATTENTION: sorted list of all operators
+struct CalcOp
+{
+ union{
+ const char* pName;
+ const OUString* pUName;
+ };
+ SwCalcOper eOp;
+};
+
+CalcOp const aOpTable[] = {
+/* ABS */ {{sCalc_Abs}, CALC_ABS}, // Abs (since LibreOffice 7.1)
+/* ACOS */ {{sCalc_Acos}, CALC_ACOS}, // Arc cosine
+/* ADD */ {{sCalc_Add}, CALC_PLUS}, // Addition
+/* AND */ {{sCalc_And}, CALC_AND}, // log. AND
+/* ASIN */ {{sCalc_Asin}, CALC_ASIN}, // Arc sine
+/* ATAN */ {{sCalc_Atan}, CALC_ATAN}, // Arc tangent
+/* AVERAGE */ {{sCalc_Average}, CALC_AVERAGE}, // Average (since LibreOffice 7.1)
+/* COS */ {{sCalc_Cos}, CALC_COS}, // Cosine
+/* COUNT */ {{sCalc_Count}, CALC_COUNT}, // Count (since LibreOffice 7.1)
+/* DATE */ {{sCalc_Date}, CALC_DATE}, // Date
+/* DIV */ {{sCalc_Div}, CALC_DIV}, // Division
+/* EQ */ {{sCalc_Eq}, CALC_EQ}, // Equality
+/* G */ {{sCalc_G}, CALC_GRE}, // Greater than
+/* GEQ */ {{sCalc_Geq}, CALC_GEQ}, // Greater or equal
+/* INT */ {{sCalc_Int}, CALC_INT}, // Int (since LibreOffice 7.4)
+/* L */ {{sCalc_L}, CALC_LES}, // Less than
+/* LEQ */ {{sCalc_Leq}, CALC_LEQ}, // Less or equal
+/* MAX */ {{sCalc_Max}, CALC_MAX}, // Maximum value
+/* MEAN */ {{sCalc_Mean}, CALC_MEAN}, // Mean
+/* MIN */ {{sCalc_Min}, CALC_MIN}, // Minimum value
+/* MUL */ {{sCalc_Mul}, CALC_MUL}, // Multiplication
+/* NEQ */ {{sCalc_Neq}, CALC_NEQ}, // Not equal
+/* NOT */ {{sCalc_Not}, CALC_NOT}, // log. NOT
+/* OR */ {{sCalc_Or}, CALC_OR}, // log. OR
+/* PHD */ {{sCalc_Phd}, CALC_PHD}, // Percentage
+/* POW */ {{sCalc_Pow}, CALC_POW}, // Exponentiation
+/* PRODUCT */ {{sCalc_Product}, CALC_PRODUCT}, // Product (since LibreOffice 7.1)
+/* ROUND */ {{sCalc_Round}, CALC_ROUND}, // Rounding
+/* SIGN */ {{sCalc_Sign}, CALC_SIGN}, // Sign (since LibreOffice 7.1)
+/* SIN */ {{sCalc_Sin}, CALC_SIN}, // Sine
+/* SQRT */ {{sCalc_Sqrt}, CALC_SQRT}, // Square root
+/* SUB */ {{sCalc_Sub}, CALC_MINUS}, // Subtraction
+/* SUM */ {{sCalc_Sum}, CALC_SUM}, // Sum
+/* TAN */ {{sCalc_Tan}, CALC_TAN}, // Tangent
+/* XOR */ {{sCalc_Xor}, CALC_XOR} // log. XOR
+};
+
+double const nRoundVal[] = {
+ 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
+ 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,
+ 0.5e-15,0.5e-16
+};
+
+// First character may be any alphabetic or underscore.
+const sal_Int32 coStartFlags =
+ i18n::KParseTokens::ANY_LETTER_OR_NUMBER |
+ i18n::KParseTokens::ASC_UNDERSCORE |
+ i18n::KParseTokens::IGNORE_LEADING_WS;
+
+// Continuing characters may be any alphanumeric, underscore, or dot.
+const sal_Int32 coContFlags =
+ (coStartFlags | i18n::KParseTokens::ASC_DOT | i18n::KParseTokens::GROUP_SEPARATOR_IN_NUMBER)
+ & ~i18n::KParseTokens::IGNORE_LEADING_WS;
+
+extern "C" {
+static int OperatorCompare( const void *pFirst, const void *pSecond)
+{
+ int nRet = 0;
+ if( CALC_NAME == static_cast<const CalcOp*>(pFirst)->eOp )
+ {
+ if( CALC_NAME == static_cast<const CalcOp*>(pSecond)->eOp )
+ nRet = static_cast<const CalcOp*>(pFirst)->pUName->compareTo(
+ *static_cast<const CalcOp*>(pSecond)->pUName );
+ else
+ nRet = static_cast<const CalcOp*>(pFirst)->pUName->compareToAscii(
+ static_cast<const CalcOp*>(pSecond)->pName );
+ }
+ else
+ {
+ if( CALC_NAME == static_cast<const CalcOp*>(pSecond)->eOp )
+ nRet = -1 * static_cast<const CalcOp*>(pSecond)->pUName->compareToAscii(
+ static_cast<const CalcOp*>(pFirst)->pName );
+ else
+ nRet = strcmp( static_cast<const CalcOp*>(pFirst)->pName,
+ static_cast<const CalcOp*>(pSecond)->pName );
+ }
+ return nRet;
+}
+}// extern "C"
+
+CalcOp* FindOperator( const OUString& rSrch )
+{
+ CalcOp aSrch;
+ aSrch.pUName = &rSrch;
+ aSrch.eOp = CALC_NAME;
+
+ return static_cast<CalcOp*>(bsearch( static_cast<void*>(&aSrch),
+ static_cast<void const *>(aOpTable),
+ SAL_N_ELEMENTS( aOpTable ),
+ sizeof( CalcOp ),
+ OperatorCompare ));
+}
+
+// static
+LanguageType SwCalc::GetDocAppScriptLang( SwDoc const & rDoc )
+{
+ TypedWhichId<SvxLanguageItem> nWhich =
+ GetWhichOfScript( RES_CHRATR_LANGUAGE,
+ SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ));
+ return rDoc.GetDefault(nWhich).GetLanguage();
+}
+
+static double lcl_ConvertToDateValue( SwDoc& rDoc, sal_Int32 nDate )
+{
+ double nRet = 0;
+ SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
+ if( pFormatter )
+ {
+ const Date& rNull = pFormatter->GetNullDate();
+ Date aDate( nDate >> 24, (nDate& 0x00FF0000) >> 16, nDate& 0x0000FFFF );
+ nRet = aDate - rNull;
+ }
+ return nRet;
+}
+
+SwCalc::SwCalc( SwDoc& rD )
+ : m_aErrExpr( SwSbxValue(), nullptr )
+ , m_nCommandPos(0)
+ , m_rDoc( rD )
+ , m_pCharClass( &GetAppCharClass() )
+ , m_nListPor( 0 )
+ , m_bHasNumber( false )
+ , m_eCurrOper( CALC_NAME )
+ , m_eCurrListOper( CALC_NAME )
+ , m_eError( SwCalcError::NONE )
+{
+ LanguageType eLang = GetDocAppScriptLang( m_rDoc );
+ LanguageTag aLanguageTag( eLang );
+
+ if( eLang != m_pCharClass->getLanguageTag().getLanguageType() )
+ {
+ m_pCharClass = new CharClass( ::comphelper::getProcessComponentContext(), aLanguageTag );
+ }
+ m_xLocaleDataWrapper.reset(new LocaleDataWrapper( std::move(aLanguageTag) ));
+
+ m_sCurrSym = comphelper::string::strip(m_xLocaleDataWrapper->getCurrSymbol(), ' ');
+ m_sCurrSym = m_pCharClass->lowercase( m_sCurrSym );
+
+ static constexpr OUString sNTypeTab[]
+ {
+ u"false"_ustr,
+ u"true"_ustr,
+ u"pi"_ustr,
+ u"e"_ustr,
+ u"tables"_ustr,
+ u"graf"_ustr,
+ u"ole"_ustr,
+ u"page"_ustr,
+ u"para"_ustr,
+ u"word"_ustr,
+ u"char"_ustr,
+
+ u"user_firstname"_ustr,
+ u"user_lastname"_ustr,
+ u"user_initials"_ustr,
+ u"user_company"_ustr,
+ u"user_street"_ustr,
+ u"user_country"_ustr,
+ u"user_zipcode"_ustr,
+ u"user_city"_ustr,
+ u"user_title"_ustr,
+ u"user_position"_ustr,
+ u"user_tel_work"_ustr,
+ u"user_tel_home"_ustr,
+ u"user_fax"_ustr,
+ u"user_email"_ustr,
+ u"user_state"_ustr,
+ u"graph"_ustr
+ };
+ static UserOptToken const aAdrToken[ 12 ] =
+ {
+ UserOptToken::Company, UserOptToken::Street, UserOptToken::Country, UserOptToken::Zip,
+ UserOptToken::City, UserOptToken::Title, UserOptToken::Position, UserOptToken::TelephoneWork,
+ UserOptToken::TelephoneHome, UserOptToken::Fax, UserOptToken::Email, UserOptToken::State
+ };
+
+ static sal_uInt16 SwDocStat::* const aDocStat1[ 3 ] =
+ {
+ &SwDocStat::nTable, &SwDocStat::nGrf, &SwDocStat::nOLE
+ };
+ static sal_uLong SwDocStat::* const aDocStat2[ 4 ] =
+ {
+ &SwDocStat::nPage, &SwDocStat::nPara,
+ &SwDocStat::nWord, &SwDocStat::nChar
+ };
+
+ const SwDocStat& rDocStat = m_rDoc.getIDocumentStatistics().GetDocStat();
+
+ SwSbxValue nVal;
+ sal_uInt16 n;
+
+ for( n = 0; n < 25; ++n )
+ m_aVarTable.insert( { sNTypeTab[n], SwCalcExp( nVal, nullptr ) } );
+
+ m_aVarTable.find( sNTypeTab[ 0 ] )->second.nValue.PutBool( false );
+ m_aVarTable.find( sNTypeTab[ 1 ] )->second.nValue.PutBool( true );
+ m_aVarTable.find( sNTypeTab[ 2 ] )->second.nValue.PutDouble( M_PI );
+ m_aVarTable.find( sNTypeTab[ 3 ] )->second.nValue.PutDouble( M_E );
+
+ for( n = 0; n < 3; ++n )
+ m_aVarTable.find( sNTypeTab[ n + 4 ] )->second.nValue.PutLong( rDocStat.*aDocStat1[ n ] );
+ for( n = 0; n < 4; ++n )
+ m_aVarTable.find( sNTypeTab[ n + 7 ] )->second.nValue.PutLong( rDocStat.*aDocStat2[ n ] );
+
+ SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions();
+
+ m_aVarTable.find( sNTypeTab[ 11 ] )->second.nValue.PutString( rUserOptions.GetFirstName() );
+ m_aVarTable.find( sNTypeTab[ 12 ] )->second.nValue.PutString( rUserOptions.GetLastName() );
+ m_aVarTable.find( sNTypeTab[ 13 ] )->second.nValue.PutString( rUserOptions.GetID() );
+
+ for( n = 0; n < 11; ++n )
+ m_aVarTable.find( sNTypeTab[ n + 14 ] )->second.nValue.PutString(
+ rUserOptions.GetToken( aAdrToken[ n ] ));
+
+ nVal.PutString( rUserOptions.GetToken( aAdrToken[ 11 ] ));
+ m_aVarTable.insert( { sNTypeTab[ 25 ], SwCalcExp( nVal, nullptr ) } );
+
+} // SwCalc::SwCalc
+
+void SwCalc::ImplDestroy()
+{
+ if( m_pCharClass != &GetAppCharClass() )
+ delete m_pCharClass;
+}
+
+SwCalc::~SwCalc()
+{
+ suppress_fun_call_w_exception(ImplDestroy());
+}
+
+SwSbxValue SwCalc::Calculate( const OUString& rStr )
+{
+ m_eError = SwCalcError::NONE;
+ SwSbxValue nResult;
+
+ if( rStr.isEmpty() )
+ return nResult;
+
+ m_nListPor = 0;
+ m_eCurrListOper = CALC_PLUS; // default: sum
+
+ m_sCommand = rStr;
+ m_nCommandPos = 0;
+
+ for (;;)
+ {
+ m_eCurrOper = GetToken();
+ if (m_eCurrOper == CALC_ENDCALC || m_eError != SwCalcError::NONE )
+ break;
+ nResult = Expr();
+ }
+
+ if( m_eError != SwCalcError::NONE)
+ nResult.PutDouble( DBL_MAX );
+
+ return nResult;
+}
+
+OUString SwCalc::GetStrResult( const SwSbxValue& rVal )
+{
+ if( !rVal.IsDouble() )
+ {
+ return rVal.GetOUString();
+ }
+ return GetStrResult( rVal.GetDouble() );
+}
+
+OUString SwCalc::GetStrResult( double nValue )
+{
+ if( nValue >= DBL_MAX )
+ switch( m_eError )
+ {
+ case SwCalcError::Syntax : return SwViewShell::GetShellRes()->aCalc_Syntax;
+ case SwCalcError::DivByZero : return SwViewShell::GetShellRes()->aCalc_ZeroDiv;
+ case SwCalcError::FaultyBrackets : return SwViewShell::GetShellRes()->aCalc_Brack;
+ case SwCalcError::OverflowInPower : return SwViewShell::GetShellRes()->aCalc_Pow;
+ case SwCalcError::Overflow : return SwViewShell::GetShellRes()->aCalc_Overflow;
+ default : return SwViewShell::GetShellRes()->aCalc_Default;
+ }
+
+ const sal_Int32 nDecPlaces = 15;
+ OUString aRetStr( ::rtl::math::doubleToUString(
+ nValue,
+ rtl_math_StringFormat_Automatic,
+ nDecPlaces,
+ m_xLocaleDataWrapper->getNumDecimalSep()[0],
+ true ));
+ return aRetStr;
+}
+
+SwCalcExp* SwCalc::VarInsert( const OUString &rStr )
+{
+ OUString aStr = m_pCharClass->lowercase( rStr );
+ return VarLook( aStr, true );
+}
+
+SwCalcExp* SwCalc::VarLook( const OUString& rStr, bool bIns )
+{
+ m_aErrExpr.nValue.SetVoidValue(false);
+
+ OUString aStr = m_pCharClass->lowercase( rStr );
+ SwCalcExp* pFnd = nullptr;
+ auto it = m_aVarTable.find(aStr);
+ if (it != m_aVarTable.end())
+ pFnd = &it->second;
+
+ if( !pFnd )
+ {
+ // then check doc
+ std::unordered_multimap<OUString, const SwFieldType*> & rDocTable
+ = m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().GetFieldTypeTable();
+ auto docIt = rDocTable.find(aStr);
+ if (docIt != rDocTable.end())
+ {
+ const SwFieldType* pFieldType = docIt->second;
+ it = m_aVarTable.insert( { aStr, SwCalcExp( SwSbxValue(), pFieldType ) } ).first;
+ pFnd = &it->second;
+ }
+ }
+
+ if( pFnd )
+ {
+ if( pFnd->pFieldType && pFnd->pFieldType->Which() == SwFieldIds::User )
+ {
+ SwUserFieldType* pUField = const_cast<SwUserFieldType*>(static_cast<const SwUserFieldType*>(pFnd->pFieldType));
+ if( nsSwGetSetExpType::GSE_STRING & pUField->GetType() )
+ {
+ pFnd->nValue.PutString( pUField->GetContent() );
+ }
+ else if( !pUField->IsValid() )
+ {
+ // Save the current values...
+ sal_uInt16 nListPor = m_nListPor;
+ bool bHasNumber = m_bHasNumber;
+ SwSbxValue nLastLeft = m_nLastLeft;
+ SwSbxValue nNumberValue = m_nNumberValue;
+ sal_Int32 nCommandPos = m_nCommandPos;
+ SwCalcOper eCurrOper = m_eCurrOper;
+ SwCalcOper eCurrListOper = m_eCurrListOper;
+ OUString sCurrCommand = m_sCommand;
+
+ pFnd->nValue.PutDouble( pUField->GetValue( *this ) );
+
+ // ...and write them back.
+ m_nListPor = nListPor;
+ m_bHasNumber = bHasNumber;
+ m_nLastLeft = nLastLeft;
+ m_nNumberValue = nNumberValue;
+ m_nCommandPos = nCommandPos;
+ m_eCurrOper = eCurrOper;
+ m_eCurrListOper = eCurrListOper;
+ m_sCommand = sCurrCommand;
+ }
+ else
+ {
+ pFnd->nValue.PutDouble( pUField->GetValue() );
+ }
+ }
+ else if ( !pFnd->pFieldType && pFnd->nValue.IsDBvalue() )
+ {
+ if ( pFnd->nValue.IsString() )
+ m_aErrExpr.nValue.PutString( pFnd->nValue.GetOUString() );
+ else if ( pFnd->nValue.IsDouble() )
+ m_aErrExpr.nValue.PutDouble( pFnd->nValue.GetDouble() );
+ pFnd = &m_aErrExpr;
+ }
+ return pFnd;
+ }
+
+ // At this point the "real" case variable has to be used
+ OUString const sTmpName( ::ReplacePoint(rStr) );
+
+ if( !bIns )
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SwDBManager *pMgr = m_rDoc.GetDBManager();
+ OUString sDBName(GetDBName( sTmpName ));
+ OUString sSourceName(sDBName.getToken(0, DB_DELIM));
+ OUString sTableName(sDBName.getToken(0, ';').getToken(1, DB_DELIM));
+ if( pMgr && !sSourceName.isEmpty() && !sTableName.isEmpty() &&
+ pMgr->OpenDataSource(sSourceName, sTableName))
+ {
+ OUString sColumnName( GetColumnName( sTmpName ));
+ OSL_ENSURE(!sColumnName.isEmpty(), "Missing DB column name");
+
+ OUString sDBNum( SwFieldType::GetTypeStr(SwFieldTypesEnum::DatabaseSetNumber) );
+ sDBNum = m_pCharClass->lowercase(sDBNum);
+
+ // Initialize again because this doesn't happen in docfld anymore for
+ // elements != SwFieldIds::Database. E.g. if there is an expression field before
+ // a DB_Field in a document.
+ const sal_uInt32 nTmpRec = pMgr->GetSelectedRecordId(sSourceName, sTableName);
+ VarChange(sDBNum, nTmpRec);
+
+ if( sDBNum.equalsIgnoreAsciiCase(sColumnName) )
+ {
+ m_aErrExpr.nValue.PutULong(nTmpRec);
+ return &m_aErrExpr;
+ }
+
+ OUString sResult;
+ double nNumber = DBL_MAX;
+
+ LanguageType nLang = m_xLocaleDataWrapper->getLanguageTag().getLanguageType();
+ if(pMgr->GetColumnCnt( sSourceName, sTableName, sColumnName,
+ nTmpRec, nLang, sResult, &nNumber ))
+ {
+ if (nNumber != DBL_MAX)
+ m_aErrExpr.nValue.PutDouble( nNumber );
+ else
+ m_aErrExpr.nValue.PutString( sResult );
+
+ return &m_aErrExpr;
+ }
+ }
+ else
+#endif
+ {
+ //data source was not available - set return to "NoValue"
+ m_aErrExpr.nValue.SetVoidValue(true);
+ }
+ // NEVER save!
+ return &m_aErrExpr;
+ }
+
+ SwCalcExp* pNewExp = &m_aVarTable.insert( { aStr, SwCalcExp( SwSbxValue(), nullptr ) } ).first->second;
+
+ OUString sColumnName( GetColumnName( sTmpName ));
+ OSL_ENSURE( !sColumnName.isEmpty(), "Missing DB column name" );
+ if( sColumnName.equalsIgnoreAsciiCase(
+ SwFieldType::GetTypeStr( SwFieldTypesEnum::DatabaseSetNumber ) ))
+ {
+#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
+ SwDBManager *pMgr = m_rDoc.GetDBManager();
+ OUString sDBName(GetDBName( sTmpName ));
+ OUString sSourceName(sDBName.getToken(0, DB_DELIM));
+ OUString sTableName(sDBName.getToken(0, ';').getToken(1, DB_DELIM));
+ if( pMgr && !sSourceName.isEmpty() && !sTableName.isEmpty() &&
+ pMgr->OpenDataSource(sSourceName, sTableName) &&
+ !pMgr->IsInMerge())
+ {
+ pNewExp->nValue.PutULong( pMgr->GetSelectedRecordId(sSourceName, sTableName));
+ }
+ else
+#endif
+ {
+ pNewExp->nValue.SetVoidValue(true);
+ }
+ }
+
+ return pNewExp;
+}
+
+void SwCalc::VarChange( const OUString& rStr, double nValue )
+{
+ SwSbxValue aVal( nValue );
+ VarChange( rStr, aVal );
+}
+
+void SwCalc::VarChange( const OUString& rStr, const SwSbxValue& rValue )
+{
+ OUString aStr = m_pCharClass->lowercase( rStr );
+
+ auto it = m_aVarTable.find( aStr );
+ if (it != m_aVarTable.end())
+ it->second.nValue = rValue;
+ else
+ m_aVarTable.insert( { aStr, SwCalcExp( rValue, nullptr ) } );
+}
+
+bool SwCalc::Push( const SwUserFieldType* pUserFieldType )
+{
+ if( m_aRekurStack.end() != std::find(m_aRekurStack.begin(), m_aRekurStack.end(), pUserFieldType ) )
+ return false;
+
+ m_aRekurStack.push_back( pUserFieldType );
+ return true;
+}
+
+void SwCalc::Pop()
+{
+ OSL_ENSURE( m_aRekurStack.size(), "SwCalc: Pop on an invalid pointer" );
+
+ m_aRekurStack.pop_back();
+}
+
+const CharClass* SwCalc::GetCharClass() const
+{
+ return m_pCharClass;
+}
+
+void SwCalc::SetCharClass(const LanguageTag& rLanguageTag)
+{
+ m_pCharClass = new CharClass( ::comphelper::getProcessComponentContext(), rLanguageTag );
+}
+
+SwCalcOper SwCalc::GetToken()
+{
+ if( m_nCommandPos >= m_sCommand.getLength() )
+ {
+ m_eCurrOper = CALC_ENDCALC;
+ return m_eCurrOper;
+ }
+
+ using namespace ::com::sun::star::i18n;
+ {
+ // Parse any token.
+ ParseResult aRes = m_pCharClass->parseAnyToken( m_sCommand, m_nCommandPos,
+ coStartFlags, OUString(),
+ coContFlags, OUString());
+
+ bool bSetError = true;
+ sal_Int32 nRealStt = m_nCommandPos + aRes.LeadingWhiteSpace;
+ if( aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER) )
+ {
+ m_nNumberValue.PutDouble( aRes.Value );
+ m_eCurrOper = CALC_NUMBER;
+ bSetError = false;
+ }
+ else if( aRes.TokenType & KParseType::IDENTNAME )
+ {
+ OUString aName( m_sCommand.copy( nRealStt,
+ aRes.EndPos - nRealStt ) );
+ //#101436#: The variable may contain a database name. It must not be
+ // converted to lower case! Instead all further comparisons must be
+ // done case-insensitive
+ OUString sLowerCaseName = m_pCharClass->lowercase( aName );
+ // catch currency symbol
+ if( sLowerCaseName == m_sCurrSym )
+ {
+ m_nCommandPos = aRes.EndPos;
+ return GetToken(); // call again
+ }
+
+ // catch operators
+ CalcOp* pFnd = ::FindOperator( sLowerCaseName );
+ if( pFnd )
+ {
+ m_eCurrOper = pFnd->eOp;
+ switch( m_eCurrOper )
+ {
+ case CALC_SUM:
+ case CALC_MEAN:
+ case CALC_AVERAGE:
+ case CALC_COUNT:
+ m_eCurrListOper = CALC_PLUS;
+ break;
+ case CALC_MIN:
+ m_eCurrListOper = CALC_MIN_IN;
+ break;
+ case CALC_MAX:
+ m_eCurrListOper = CALC_MAX_IN;
+ break;
+ case CALC_DATE:
+ m_eCurrListOper = CALC_MONTH;
+ break;
+ case CALC_PRODUCT:
+ m_eCurrListOper = CALC_MUL;
+ break;
+ default:
+ break;
+ }
+ m_nCommandPos = aRes.EndPos;
+ return m_eCurrOper;
+ }
+ m_aVarName = aName;
+ m_eCurrOper = CALC_NAME;
+ bSetError = false;
+ }
+ else if ( aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING )
+ {
+ m_nNumberValue.PutString( aRes.DequotedNameOrString );
+ m_eCurrOper = CALC_NUMBER;
+ bSetError = false;
+ }
+ else if( aRes.TokenType & KParseType::ONE_SINGLE_CHAR )
+ {
+ std::u16string_view aName( m_sCommand.subView( nRealStt,
+ aRes.EndPos - nRealStt ));
+ if( 1 == aName.size() )
+ {
+ bSetError = false;
+ sal_Unicode ch = aName[0];
+ switch( ch )
+ {
+ case ';':
+ if( CALC_MONTH == m_eCurrListOper || CALC_DAY == m_eCurrListOper )
+ {
+ m_eCurrOper = m_eCurrListOper;
+ break;
+ }
+ [[fallthrough]];
+ case '\n':
+ m_eCurrOper = CALC_PRINT;
+ break;
+
+ case '%':
+ case '^':
+ case '*':
+ case '/':
+ case '+':
+ case '-':
+ case '(':
+ case ')':
+ m_eCurrOper = SwCalcOper(ch);
+ break;
+
+ case '=':
+ case '!':
+ {
+ SwCalcOper eTmp2;
+ if( '=' == ch )
+ {
+ m_eCurrOper = SwCalcOper('=');
+ eTmp2 = CALC_EQ;
+ }
+ else
+ {
+ m_eCurrOper = CALC_NOT;
+ eTmp2 = CALC_NEQ;
+ }
+
+ if( aRes.EndPos < m_sCommand.getLength() &&
+ '=' == m_sCommand[aRes.EndPos] )
+ {
+ m_eCurrOper = eTmp2;
+ ++aRes.EndPos;
+ }
+ }
+ break;
+
+ case cListDelim:
+ m_eCurrOper = m_eCurrListOper;
+ break;
+
+ case '[':
+ if( aRes.EndPos < m_sCommand.getLength() )
+ {
+ m_aVarName.setLength(0);
+ sal_Int32 nFndPos = aRes.EndPos,
+ nSttPos = nFndPos;
+
+ do {
+ nFndPos = m_sCommand.indexOf( ']', nFndPos );
+ if( -1 != nFndPos )
+ {
+ // ignore the ]
+ if ('\\' == m_sCommand[nFndPos-1])
+ {
+ m_aVarName.append(m_sCommand.subView(nSttPos,
+ nFndPos - nSttPos - 1) );
+ nSttPos = ++nFndPos;
+ }
+ else
+ break;
+ }
+ } while( nFndPos != -1 );
+
+ if( nFndPos != -1 )
+ {
+ if( nSttPos != nFndPos )
+ m_aVarName.append(m_sCommand.subView(nSttPos,
+ nFndPos - nSttPos) );
+ aRes.EndPos = nFndPos + 1;
+ m_eCurrOper = CALC_NAME;
+ }
+ else
+ bSetError = true;
+ }
+ else
+ {
+ bSetError = true;
+ }
+ break;
+
+ default:
+ bSetError = true;
+ break;
+ }
+ }
+ }
+ else if( aRes.TokenType & KParseType::BOOLEAN )
+ {
+ std::u16string_view aName( m_sCommand.subView( nRealStt,
+ aRes.EndPos - nRealStt ));
+ if( !aName.empty() )
+ {
+ sal_Unicode ch = aName[0];
+
+ bSetError = true;
+ if ('<' == ch || '>' == ch)
+ {
+ bSetError = false;
+
+ SwCalcOper eTmp2 = ('<' == ch) ? CALC_LEQ : CALC_GEQ;
+ m_eCurrOper = ('<' == ch) ? CALC_LES : CALC_GRE;
+
+ if( 2 == aName.size() && '=' == aName[1] )
+ m_eCurrOper = eTmp2;
+ else if( 1 != aName.size() )
+ bSetError = true;
+ }
+ }
+ }
+ else if( nRealStt == m_sCommand.getLength() )
+ {
+ m_eCurrOper = CALC_ENDCALC;
+ bSetError = false;
+ }
+
+ if( bSetError )
+ {
+ m_eError = SwCalcError::Syntax;
+ m_eCurrOper = CALC_PRINT;
+ }
+ m_nCommandPos = aRes.EndPos;
+ };
+
+ return m_eCurrOper;
+}
+
+SwSbxValue SwCalc::Term()
+{
+ SwSbxValue left( Prim() );
+ m_nLastLeft = left;
+ for(;;)
+ {
+ sal_uInt16 nSbxOper = USHRT_MAX;
+
+ switch( m_eCurrOper )
+ {
+ case CALC_AND:
+ {
+ GetToken();
+ bool bB = Prim().GetBool();
+ left.PutBool( left.GetBool() && bB );
+ }
+ break;
+ case CALC_OR:
+ {
+ GetToken();
+ bool bB = Prim().GetBool();
+ left.PutBool( left.GetBool() || bB );
+ }
+ break;
+ case CALC_XOR:
+ {
+ GetToken();
+ bool bR = Prim().GetBool();
+ bool bL = left.GetBool();
+ left.PutBool(bL != bR);
+ }
+ break;
+
+ case CALC_EQ: nSbxOper = SbxEQ; break;
+ case CALC_NEQ: nSbxOper = SbxNE; break;
+ case CALC_LEQ: nSbxOper = SbxLE; break;
+ case CALC_GEQ: nSbxOper = SbxGE; break;
+ case CALC_GRE: nSbxOper = SbxGT; break;
+ case CALC_LES: nSbxOper = SbxLT; break;
+
+ case CALC_MUL: nSbxOper = SbxMUL; break;
+ case CALC_DIV: nSbxOper = SbxDIV; break;
+
+ case CALC_MIN_IN:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ left = left.GetDouble() < e.GetDouble() ? left : e;
+ }
+ break;
+ case CALC_MAX_IN:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ left = left.GetDouble() > e.GetDouble() ? left : e;
+ }
+ break;
+ case CALC_MONTH:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ sal_Int32 nYear = static_cast<sal_Int32>(floor( left.GetDouble() ));
+ nYear = nYear & 0x0000FFFF;
+ sal_Int32 nMonth = static_cast<sal_Int32>(floor( e.GetDouble() ));
+ nMonth = ( nMonth & 0x000000FF ) << 16;
+ left.PutLong( nMonth + nYear );
+ m_eCurrOper = CALC_DAY;
+ }
+ break;
+ case CALC_DAY:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+ sal_Int32 nYearMonth = static_cast<sal_Int32>(floor( left.GetDouble() ));
+ nYearMonth = nYearMonth & 0x00FFFFFF;
+ sal_Int32 nDay = static_cast<sal_Int32>(floor( e.GetDouble() ));
+ nDay = ( nDay & 0x000000FF ) << 24;
+ left = lcl_ConvertToDateValue( m_rDoc, nDay + nYearMonth );
+ }
+ break;
+ case CALC_ROUND:
+ {
+ GetToken();
+ SwSbxValue e = Prim();
+
+ double fVal = 0;
+ double fFac = 1;
+ sal_Int32 nDec = static_cast<sal_Int32>(floor( e.GetDouble() ));
+ if( nDec < -20 || nDec > 20 )
+ {
+ m_eError = SwCalcError::Overflow;
+ left.Clear();
+ return left;
+ }
+ fVal = left.GetDouble();
+ if( nDec >= 0)
+ {
+ for (sal_Int32 i = 0; i < nDec; ++i )
+ fFac *= 10.0;
+ }
+ else
+ {
+ for (sal_Int32 i = 0; i < -nDec; ++i )
+ fFac /= 10.0;
+ }
+
+ fVal *= fFac;
+ bool bSign;
+ if (fVal < 0.0)
+ {
+ fVal *= -1.0;
+ bSign = true;
+ }
+ else
+ {
+ bSign = false;
+ }
+
+ // rounding
+ double fNum = fVal; // find the exponent
+ int nExp = 0;
+ if( fNum > 0 )
+ {
+ while( fNum < 1.0 )
+ {
+ fNum *= 10.0;
+ --nExp;
+ }
+ while( fNum >= 10.0 )
+ {
+ fNum /= 10.0;
+ ++nExp;
+ }
+ }
+ nExp = 15 - nExp;
+ if( nExp > 15 )
+ nExp = 15;
+ else if( nExp <= 1 )
+ nExp = 0;
+ fVal = floor( fVal+ 0.5 + nRoundVal[ nExp ] );
+
+ if (bSign)
+ fVal *= -1.0;
+
+ fVal /= fFac;
+
+ left.PutDouble( fVal );
+ }
+ break;
+
+//#77448# (=2*3^2 != 18)
+
+ default:
+ return left;
+ }
+
+ if( USHRT_MAX != nSbxOper )
+ {
+ // #i47706: cast to SbxOperator AFTER comparing to USHRT_MAX
+ SbxOperator eSbxOper = static_cast<SbxOperator>(nSbxOper);
+
+ GetToken();
+ if( SbxEQ <= eSbxOper && eSbxOper <= SbxGE )
+ {
+ left.PutBool( left.Compare( eSbxOper, Prim() ));
+ }
+ else
+ {
+ SwSbxValue aRight( Prim() );
+ aRight.MakeDouble();
+ left.MakeDouble();
+
+ if( SbxDIV == eSbxOper && !aRight.GetDouble() )
+ m_eError = SwCalcError::DivByZero;
+ else
+ left.Compute( eSbxOper, aRight );
+ }
+ }
+ }
+}
+
+SwSbxValue SwCalc::StdFunc(pfCalc pFnc, bool bChkTrig)
+{
+ SwSbxValue nErg;
+ GetToken();
+ double nVal = Prim().GetDouble();
+ if( !bChkTrig || ( nVal > -1 && nVal < 1 ) )
+ nErg.PutDouble( (*pFnc)( nVal ) );
+ else
+ m_eError = SwCalcError::Overflow;
+ return nErg;
+}
+
+SwSbxValue SwCalc::PrimFunc(bool &rChkPow)
+{
+ rChkPow = false;
+
+ switch (m_eCurrOper)
+ {
+ case CALC_SIN:
+ SAL_INFO("sw.calc", "sin");
+ return StdFunc(&sin, false);
+ case CALC_COS:
+ SAL_INFO("sw.calc", "cos");
+ return StdFunc(&cos, false);
+ case CALC_TAN:
+ SAL_INFO("sw.calc", "tan");
+ return StdFunc(&tan, false);
+ case CALC_ATAN:
+ SAL_INFO("sw.calc", "atan");
+ return StdFunc(&atan, false);
+ case CALC_ASIN:
+ SAL_INFO("sw.calc", "asin");
+ return StdFunc(&asin, true);
+ case CALC_ACOS:
+ SAL_INFO("sw.calc", "acos");
+ return StdFunc(&acos, true);
+ case CALC_ABS:
+ SAL_INFO("sw.calc", "abs");
+ return StdFunc(&abs, false);
+ case CALC_SIGN:
+ {
+ SAL_INFO("sw.calc", "sign");
+ SwSbxValue nErg;
+ GetToken();
+ double nVal = Prim().GetDouble();
+ nErg.PutDouble( int(0 < nVal) - int(nVal < 0) );
+ return nErg;
+ }
+ case CALC_INT:
+ {
+ SAL_INFO("sw.calc", "int");
+ SwSbxValue nErg;
+ GetToken();
+ sal_Int32 nVal = static_cast<sal_Int32>( Prim().GetDouble() );
+ nErg.PutDouble( nVal );
+ return nErg;
+ }
+ case CALC_NOT:
+ {
+ SAL_INFO("sw.calc", "not");
+ GetToken();
+ SwSbxValue nErg = Prim();
+ if( SbxSTRING == nErg.GetType() )
+ {
+ nErg.PutBool( nErg.GetOUString().isEmpty() );
+ }
+ else if(SbxBOOL == nErg.GetType() )
+ {
+ nErg.PutBool(!nErg.GetBool());
+ }
+ // Evaluate arguments manually so that the binary NOT below does not
+ // get called. We want a BOOLEAN NOT.
+ else if (nErg.IsNumeric())
+ {
+ nErg.PutLong( nErg.GetDouble() == 0.0 ? 1 : 0 );
+ }
+ else
+ {
+ OSL_FAIL( "unexpected case. computing binary NOT" );
+ //!! computes a binary NOT
+ nErg.Compute( SbxNOT, nErg );
+ }
+ return nErg;
+ }
+ case CALC_NUMBER:
+ {
+ SAL_INFO("sw.calc", "number: " << m_nNumberValue.GetDouble());
+ SwSbxValue nErg;
+ m_bHasNumber = true;
+ if( GetToken() == CALC_PHD )
+ {
+ double aTmp = m_nNumberValue.GetDouble();
+ aTmp *= 0.01;
+ nErg.PutDouble( aTmp );
+ GetToken();
+ }
+ else if( m_eCurrOper == CALC_NAME )
+ {
+ m_eError = SwCalcError::Syntax;
+ }
+ else
+ {
+ nErg = m_nNumberValue;
+ rChkPow = true;
+ }
+ return nErg;
+ }
+ case CALC_NAME:
+ {
+ SAL_INFO("sw.calc", "name");
+ SwSbxValue nErg;
+ switch(SwCalcOper eOper = GetToken())
+ {
+ case CALC_ASSIGN:
+ {
+ SwCalcExp* n = VarInsert(m_aVarName.toString());
+ GetToken();
+ nErg = n->nValue = Expr();
+ break;
+ }
+ default:
+ nErg = VarLook(m_aVarName.toString())->nValue;
+ // Explicitly disallow unknown function names (followed by "("),
+ // allow unknown variable names (equal to zero)
+ if (nErg.IsVoidValue() && (eOper == CALC_LP))
+ m_eError = SwCalcError::Syntax;
+ else
+ rChkPow = true;
+ break;
+ }
+ return nErg;
+ }
+ case CALC_MINUS:
+ {
+ SAL_INFO("sw.calc", "-");
+ SwSbxValue nErg;
+ GetToken();
+ nErg.PutDouble( -(Prim().GetDouble()) );
+ return nErg;
+ }
+ case CALC_LP:
+ {
+ SAL_INFO("sw.calc", "(");
+ GetToken();
+ SwSbxValue nErg = Expr();
+ if( m_eCurrOper != CALC_RP )
+ {
+ m_eError = SwCalcError::FaultyBrackets;
+ }
+ else
+ {
+ GetToken();
+ rChkPow = true; // in order for =(7)^2 to work
+ }
+ return nErg;
+ }
+ case CALC_RP:
+ // ignore, see tdf#121962
+ SAL_INFO("sw.calc", ")");
+ break;
+ case CALC_MEAN:
+ case CALC_AVERAGE:
+ {
+ SAL_INFO("sw.calc", "mean");
+ m_nListPor = 1;
+ m_bHasNumber = CALC_MEAN == m_eCurrOper;
+ GetToken();
+ SwSbxValue nErg = Expr();
+ double aTmp = nErg.GetDouble();
+ aTmp /= m_nListPor;
+ if ( !m_bHasNumber )
+ m_eError = SwCalcError::DivByZero;
+ else
+ nErg.PutDouble( aTmp );
+ return nErg;
+ }
+ case CALC_COUNT:
+ {
+ SAL_INFO("sw.calc", "count");
+ m_nListPor = 1;
+ m_bHasNumber = false;
+ GetToken();
+ SwSbxValue nErg = Expr();
+ nErg.PutDouble( m_bHasNumber ? m_nListPor : 0 );
+ return nErg;
+ }
+ case CALC_SQRT:
+ {
+ SAL_INFO("sw.calc", "sqrt");
+ GetToken();
+ SwSbxValue nErg = Prim();
+ if( nErg.GetDouble() < 0 )
+ m_eError = SwCalcError::Overflow;
+ else
+ nErg.PutDouble( sqrt( nErg.GetDouble() ));
+ return nErg;
+ }
+ case CALC_SUM:
+ case CALC_PRODUCT:
+ case CALC_DATE:
+ case CALC_MIN:
+ case CALC_MAX:
+ {
+ SAL_INFO("sw.calc", "sum/product/date/min/max");
+ GetToken();
+ SwSbxValue nErg = Expr();
+ return nErg;
+ }
+ case CALC_ENDCALC:
+ {
+ SAL_INFO("sw.calc", "endcalc");
+ SwSbxValue nErg;
+ nErg.Clear();
+ return nErg;
+ }
+ default:
+ SAL_INFO("sw.calc", "syntax error");
+ m_eError = SwCalcError::Syntax;
+ break;
+ }
+
+ return SwSbxValue();
+}
+
+SwSbxValue SwCalc::Prim()
+{
+ bool bChkPow;
+ SwSbxValue nErg = PrimFunc(bChkPow);
+
+ if (bChkPow && m_eCurrOper == CALC_POW)
+ {
+ double dleft = nErg.GetDouble();
+ GetToken();
+ double right = Prim().GetDouble();
+
+ double fraction;
+ fraction = modf( right, &o3tl::temporary(double()) );
+ if( ( dleft < 0.0 && 0.0 != fraction ) ||
+ ( 0.0 == dleft && right < 0.0 ) )
+ {
+ m_eError = SwCalcError::Overflow;
+ nErg.Clear();
+ }
+ else
+ {
+ dleft = pow(dleft, right );
+ if( dleft == HUGE_VAL )
+ {
+ m_eError = SwCalcError::OverflowInPower;
+ nErg.Clear();
+ }
+ else
+ {
+ nErg.PutDouble( dleft );
+ }
+ }
+ }
+
+ return nErg;
+}
+
+SwSbxValue SwCalc::Expr()
+{
+ SwSbxValue left = Term();
+ m_nLastLeft = left;
+ for(;;)
+ {
+ switch(m_eCurrOper)
+ {
+ case CALC_PLUS:
+ {
+ GetToken();
+ left.MakeDouble();
+ SwSbxValue right(Term());
+ right.MakeDouble();
+ left.Compute(SbxPLUS, right);
+ m_nListPor++;
+ break;
+ }
+ case CALC_MINUS:
+ {
+ GetToken();
+ left.MakeDouble();
+ SwSbxValue right(Term());
+ right.MakeDouble();
+ left.Compute(SbxMINUS, right);
+ break;
+ }
+ default:
+ {
+ return left;
+ }
+ }
+ }
+}
+
+OUString SwCalc::GetColumnName(const OUString& rName)
+{
+ sal_Int32 nPos = rName.indexOf(DB_DELIM);
+ if( -1 != nPos )
+ {
+ nPos = rName.indexOf(DB_DELIM, nPos + 1);
+
+ if( -1 != nPos )
+ return rName.copy(nPos + 1);
+ }
+ return rName;
+}
+
+OUString SwCalc::GetDBName(std::u16string_view rName)
+{
+ size_t nPos = rName.find(DB_DELIM);
+ if( std::u16string_view::npos != nPos )
+ {
+ nPos = rName.find(DB_DELIM, nPos + 1);
+
+ if( std::u16string_view::npos != nPos )
+ return OUString(rName.substr( 0, nPos ));
+ }
+ SwDBData aData = m_rDoc.GetDBData();
+ return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
+}
+
+namespace
+{
+ bool lcl_Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
+ double& rVal,
+ const LocaleDataWrapper* const pLclData )
+ {
+ assert(pLclData);
+ const sal_Unicode nCurrCmdPos = rCommandPos;
+ rtl_math_ConversionStatus eStatus;
+ const sal_Unicode* pEnd;
+ rVal = pLclData->stringToDouble( rCommand.getStr() + rCommandPos,
+ rCommand.getStr() + rCommand.getLength(),
+ true,
+ &eStatus,
+ &pEnd );
+ rCommandPos = static_cast<sal_Int32>(pEnd - rCommand.getStr());
+
+ return rtl_math_ConversionStatus_Ok == eStatus &&
+ nCurrCmdPos != rCommandPos;
+ }
+}
+
+bool SwCalc::Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
+ double& rVal )
+{
+ const SvtSysLocale aSysLocale;
+ return lcl_Str2Double( rCommand, rCommandPos, rVal, &aSysLocale.GetLocaleData() );
+}
+
+bool SwCalc::Str2Double( const OUString& rCommand, sal_Int32& rCommandPos,
+ double& rVal, SwDoc const * const pDoc )
+{
+ const SvtSysLocale aSysLocale;
+ std::unique_ptr<const LocaleDataWrapper> pLclD;
+ if( pDoc )
+ {
+ LanguageType eLang = GetDocAppScriptLang( *pDoc );
+ if (eLang != aSysLocale.GetLanguageTag().getLanguageType())
+ {
+ pLclD.reset( new LocaleDataWrapper( LanguageTag( eLang )) );
+ }
+ }
+
+ bool const bRet = lcl_Str2Double(rCommand, rCommandPos, rVal,
+ pLclD ? pLclD.get() : &aSysLocale.GetLocaleData());
+
+ return bRet;
+}
+
+bool SwCalc::IsValidVarName( const OUString& rStr, OUString* pValidName )
+{
+ bool bRet = false;
+ using namespace ::com::sun::star::i18n;
+ {
+ // Parse any token.
+ ParseResult aRes = GetAppCharClass().parseAnyToken( rStr, 0,
+ coStartFlags, OUString(),
+ coContFlags, OUString() );
+
+ if( aRes.TokenType & KParseType::IDENTNAME )
+ {
+ bRet = aRes.EndPos == rStr.getLength();
+ if( pValidName )
+ {
+ *pValidName = rStr.copy( aRes.LeadingWhiteSpace,
+ aRes.EndPos - aRes.LeadingWhiteSpace );
+ }
+ }
+ else if( pValidName )
+ pValidName->clear();
+ }
+ return bRet;
+}
+
+SwCalcExp::SwCalcExp(SwSbxValue aVal, const SwFieldType* pType)
+ : nValue(std::move(aVal))
+ , pFieldType(pType)
+{
+}
+
+bool SwSbxValue::GetBool() const
+{
+ return SbxSTRING == GetType() ? !GetOUString().isEmpty()
+ : SbxValue::GetBool();
+}
+
+double SwSbxValue::GetDouble() const
+{
+ double nRet;
+ if( SbxSTRING == GetType() )
+ {
+ sal_Int32 nStt = 0;
+ SwCalc::Str2Double( GetOUString(), nStt, nRet );
+ }
+ else if (IsBool())
+ {
+ nRet = GetBool() ? 1.0 : 0.0;
+ }
+ else
+ {
+ nRet = SbxValue::GetDouble();
+ }
+ return nRet;
+}
+
+SwSbxValue& SwSbxValue::MakeDouble()
+{
+ if( GetType() == SbxSTRING || GetType() == SbxBOOL )
+ PutDouble( GetDouble() );
+ return *this;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/checkit.cxx b/sw/source/core/bastyp/checkit.cxx
new file mode 100644
index 0000000000..f6e00314db
--- /dev/null
+++ b/sw/source/core/bastyp/checkit.cxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <checkit.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/i18n/InputSequenceChecker.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::i18n;
+
+SwCheckIt::SwCheckIt()
+{
+ Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+ xCheck = InputSequenceChecker::create(xContext);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/index.cxx b/sw/source/core/bastyp/index.cxx
new file mode 100644
index 0000000000..c7ded156ea
--- /dev/null
+++ b/sw/source/core/bastyp/index.cxx
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <contentindex.hxx>
+
+#include <assert.h>
+#include <sal/log.hxx>
+
+#include <crossrefbookmark.hxx>
+
+SwContentIndex::SwContentIndex(const SwContentNode * pContentNode, sal_Int32 const nIdx)
+ : m_nIndex( nIdx )
+ , m_pContentNode( const_cast<SwContentNode*>(pContentNode) )
+ , m_pNext( nullptr )
+ , m_pPrev( nullptr )
+ , m_pMark( nullptr )
+{
+ Init(m_nIndex);
+}
+
+SwContentIndex::SwContentIndex( const SwContentIndex& rIdx, short nDiff )
+ : m_pContentNode( rIdx.m_pContentNode )
+ , m_pNext( nullptr )
+ , m_pPrev( nullptr )
+ , m_pMark( nullptr )
+{
+ ChgValue( rIdx, rIdx.m_nIndex + nDiff );
+}
+
+SwContentIndex::SwContentIndex( const SwContentIndex& rIdx )
+ : m_nIndex( rIdx.m_nIndex )
+ , m_pContentNode( rIdx.m_pContentNode )
+ , m_pNext( nullptr )
+ , m_pPrev( nullptr )
+ , m_pMark( nullptr )
+{
+ ChgValue( rIdx, rIdx.m_nIndex );
+}
+
+void SwContentIndex::Init(sal_Int32 const nIdx)
+{
+ if (!m_pContentNode)
+ {
+ m_nIndex = 0; // always 0 if no IndexReg
+ }
+ else if (!m_pContentNode->m_pFirst) // first Index?
+ {
+ assert(!m_pContentNode->m_pLast);
+ m_pContentNode->m_pFirst = m_pContentNode->m_pLast = this;
+ m_nIndex = nIdx;
+ }
+ else if (nIdx > ((m_pContentNode->m_pLast->m_nIndex
+ - m_pContentNode->m_pFirst->m_nIndex) / 2))
+ {
+ ChgValue( *m_pContentNode->m_pLast, nIdx );
+ }
+ else
+ {
+ ChgValue( *m_pContentNode->m_pFirst, nIdx );
+ }
+}
+
+SwContentIndex& SwContentIndex::ChgValue( const SwContentIndex& rIdx, sal_Int32 nNewValue )
+{
+ assert(m_pContentNode == rIdx.m_pContentNode);
+ if (!m_pContentNode)
+ {
+ m_nIndex = 0;
+ return *this; // no IndexReg => no list to sort into; m_nIndex is 0
+ }
+ SwContentIndex* pFnd = const_cast<SwContentIndex*>(&rIdx);
+ if (rIdx.m_nIndex > nNewValue) // move forwards
+ {
+ for (;;)
+ {
+ SwContentIndex* pPrv = pFnd->m_pPrev;
+ if (!pPrv || pPrv->m_nIndex <= nNewValue)
+ break;
+ pFnd = pPrv;
+ }
+
+ if( pFnd != this )
+ {
+ // remove from list at old position
+ Remove();
+
+ m_pNext = pFnd;
+ m_pPrev = pFnd->m_pPrev;
+ if (m_pPrev)
+ m_pPrev->m_pNext = this;
+ else
+ m_pContentNode->m_pFirst = this;
+ pFnd->m_pPrev = this;
+ }
+ }
+ else if (rIdx.m_nIndex < nNewValue)
+ {
+ for (;;)
+ {
+ SwContentIndex* pNxt = pFnd->m_pNext;
+ if (!pNxt || pNxt->m_nIndex >= nNewValue)
+ break;
+ pFnd = pNxt;
+ }
+
+ if( pFnd != this )
+ {
+ // remove from list at old position
+ Remove();
+
+ m_pPrev = pFnd;
+ m_pNext = pFnd->m_pNext;
+ if (m_pNext)
+ m_pNext->m_pPrev = this;
+ else
+ m_pContentNode->m_pLast = this;
+ pFnd->m_pNext = this;
+ }
+ }
+ else if( pFnd != this )
+ {
+ // remove from list at old position
+ Remove();
+
+ m_pPrev = pFnd; // == &rIdx here
+ m_pNext = rIdx.m_pNext;
+ m_pPrev->m_pNext = this;
+
+ if (!m_pNext) // last in the list
+ m_pContentNode->m_pLast = this;
+ else
+ m_pNext->m_pPrev = this;
+ }
+
+ if (m_pContentNode->m_pFirst == m_pNext)
+ m_pContentNode->m_pFirst = this;
+ if (m_pContentNode->m_pLast == m_pPrev)
+ m_pContentNode->m_pLast = this;
+
+ m_nIndex = nNewValue;
+
+ return *this;
+}
+
+void SwContentIndex::Remove()
+{
+ if (!m_pContentNode)
+ {
+ assert(!m_pPrev && !m_pNext);
+ return;
+ }
+
+ if (m_pPrev)
+ {
+ m_pPrev->m_pNext = m_pNext;
+ }
+ else if (m_pContentNode->m_pFirst == this)
+ {
+ m_pContentNode->m_pFirst = m_pNext;
+ }
+
+ if (m_pNext)
+ {
+ m_pNext->m_pPrev = m_pPrev;
+ }
+ else if (m_pContentNode->m_pLast == this)
+ {
+ m_pContentNode->m_pLast = m_pPrev;
+ }
+}
+
+SwContentIndex& SwContentIndex::operator=( const SwContentIndex& rIdx )
+{
+ bool bEqual;
+ if (rIdx.m_pContentNode != m_pContentNode) // unregister!
+ {
+ Remove();
+ m_pContentNode = rIdx.m_pContentNode;
+ m_pNext = m_pPrev = nullptr;
+ bEqual = false;
+ }
+ else
+ bEqual = rIdx.m_nIndex == m_nIndex;
+
+ if( !bEqual )
+ ChgValue( rIdx, rIdx.m_nIndex );
+ return *this;
+}
+
+SwContentIndex& SwContentIndex::Assign( const SwContentNode* pArr, sal_Int32 nIdx )
+{
+ if (pArr != m_pContentNode) // unregister!
+ {
+ Remove();
+ m_pContentNode = const_cast<SwContentNode*>(pArr);
+ m_pNext = m_pPrev = nullptr;
+ Init(nIdx);
+ }
+ else if (m_nIndex != nIdx)
+ {
+ ChgValue( *this, nIdx );
+ }
+ return *this;
+}
+
+void SwContentIndex::SetMark(const sw::mark::IMark* pMark)
+{
+ m_pMark = pMark;
+}
+
+SwContentIndexReg::SwContentIndexReg()
+ : m_pFirst( nullptr ), m_pLast( nullptr )
+{
+}
+
+SwContentIndexReg::~SwContentIndexReg()
+{
+ assert(!m_pFirst && !m_pLast && "There are still indices registered");
+}
+
+void SwContentIndexReg::Update(
+ SwContentIndex const & rIdx,
+ const sal_Int32 nDiff,
+ UpdateMode const eMode)
+{
+ SwContentIndex* pStt = const_cast<SwContentIndex*>(&rIdx);
+ const sal_Int32 nNewVal = rIdx.m_nIndex;
+ if (eMode & UpdateMode::Negative)
+ {
+ const sal_Int32 nLast = rIdx.m_nIndex + nDiff;
+ pStt = rIdx.m_pNext;
+ // skip over the ones that already have the right value
+ while (pStt && pStt->m_nIndex == nNewVal)
+ pStt = pStt->m_pNext;
+ while (pStt && pStt->m_nIndex <= nLast)
+ {
+ pStt->m_nIndex = nNewVal;
+ pStt = pStt->m_pNext;
+ }
+ while( pStt )
+ {
+ pStt->m_nIndex = pStt->m_nIndex - nDiff;
+ pStt = pStt->m_pNext;
+ }
+ }
+ else
+ {
+ while (pStt && pStt->m_nIndex == nNewVal)
+ {
+ pStt->m_nIndex = pStt->m_nIndex + nDiff;
+ pStt = pStt->m_pPrev;
+ }
+ pStt = rIdx.m_pNext;
+ while( pStt )
+ {
+ // HACK: avoid updating position of cross-ref bookmarks
+ if (!pStt->m_pMark || nullptr == dynamic_cast<
+ ::sw::mark::CrossRefBookmark const*>(pStt->m_pMark))
+ {
+ pStt->m_nIndex = pStt->m_nIndex + nDiff;
+ }
+ pStt = pStt->m_pNext;
+ }
+ }
+}
+
+void SwContentIndexReg::MoveTo( SwContentNode& rArr )
+{
+ if (!(this != &rArr && m_pFirst))
+ return;
+
+ SwContentIndex * pIdx = const_cast<SwContentIndex*>(m_pFirst);
+ SwContentIndex * pNext;
+ while( pIdx )
+ {
+ pNext = pIdx->m_pNext;
+ pIdx->Assign( &rArr, pIdx->GetIndex() );
+ pIdx = pNext;
+ }
+ m_pFirst = nullptr;
+ m_pLast = nullptr;
+}
+
+#ifdef DBG_UTIL
+
+// SwContentIndex
+
+sal_Int32 SwContentIndex::operator++()
+{
+ SAL_WARN_IF( !(m_nIndex < SAL_MAX_INT32), "sw.core",
+ "SwContentIndex::operator++() wraps around" );
+
+ ChgValue( *this, m_nIndex+1 );
+ return m_nIndex;
+}
+
+sal_Int32 SwContentIndex::operator--(int)
+{
+ SAL_WARN_IF( !(m_nIndex > 0), "sw.core",
+ "SwContentIndex::operator--(int) wraps around" );
+
+ const sal_Int32 nOldIndex = m_nIndex;
+ ChgValue( *this, m_nIndex-1 );
+ return nOldIndex;
+}
+
+sal_Int32 SwContentIndex::operator--()
+{
+ SAL_WARN_IF( !( m_nIndex > 0), "sw.core",
+ "SwContentIndex::operator--() wraps around" );
+ return ChgValue( *this, m_nIndex-1 ).m_nIndex;
+}
+
+sal_Int32 SwContentIndex::operator+=( sal_Int32 const nVal )
+{
+ SAL_WARN_IF( !(nVal > 0 ? m_nIndex <= SAL_MAX_INT32 - nVal : m_nIndex >= nVal), "sw.core",
+ "SwContentIndex SwContentIndex::operator+=(sal_Int32) wraps around" );
+ return ChgValue( *this, m_nIndex + nVal ).m_nIndex;
+}
+
+sal_Int32 SwContentIndex::operator-=( sal_Int32 const nVal )
+{
+ SAL_WARN_IF( !(m_nIndex >= nVal), "sw.core",
+ "SwContentIndex::operator-=(sal_Int32) wraps around" );
+ return ChgValue( *this, m_nIndex - nVal ).m_nIndex;
+}
+
+bool SwContentIndex::operator< ( const SwContentIndex & rIndex ) const
+{
+ // Attempt to compare indices into different arrays
+ assert(m_pContentNode == rIndex.m_pContentNode);
+ return m_nIndex < rIndex.m_nIndex;
+}
+
+bool SwContentIndex::operator<=( const SwContentIndex & rIndex ) const
+{
+ // Attempt to compare indices into different arrays
+ assert(m_pContentNode == rIndex.m_pContentNode);
+ return m_nIndex <= rIndex.m_nIndex;
+}
+
+bool SwContentIndex::operator> ( const SwContentIndex & rIndex ) const
+{
+ // Attempt to compare indices into different arrays
+ assert(m_pContentNode == rIndex.m_pContentNode);
+ return m_nIndex > rIndex.m_nIndex;
+}
+
+bool SwContentIndex::operator>=( const SwContentIndex & rIndex ) const
+{
+ // Attempt to compare indices into different arrays
+ assert(m_pContentNode == rIndex.m_pContentNode);
+ return m_nIndex >= rIndex.m_nIndex;
+}
+
+SwContentIndex& SwContentIndex::operator= ( sal_Int32 const nVal )
+{
+ if (m_nIndex != nVal)
+ ChgValue( *this, nVal );
+
+ return *this;
+}
+
+#endif
+
+std::ostream& operator <<(std::ostream& s, const SwContentIndex& index)
+{
+ return s << "SwContentIndex offset (" << index.GetIndex() << ")";
+}
+
+std::ostream& operator <<(std::ostream& s, const SwNodeOffset& index)
+{
+ return s << sal_Int32(index);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
new file mode 100644
index 0000000000..ce14c81e4d
--- /dev/null
+++ b/sw/source/core/bastyp/init.cxx
@@ -0,0 +1,811 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <acmplwrd.hxx>
+#include <breakit.hxx>
+#include <cellatr.hxx>
+#include <checkit.hxx>
+#include <cmdid.h>
+#include <comphelper/processfactory.hxx>
+#include <doc.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <editeng/autokernitem.hxx>
+#include <editeng/blinkitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/emphasismarkitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/forbiddenruleitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/hngpnctitem.hxx>
+#include <editeng/hyphenzoneitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/nhypitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/prntitem.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/rsiditem.hxx>
+#include <svl/grabbagitem.hxx>
+#include <svl/voiditem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/swafopt.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <i18nutil/transliteration.hxx>
+#include <editsh.hxx>
+#include <fchrfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtautofmt.hxx>
+#include <fmtclbl.hxx>
+#include <fmtclds.hxx>
+#include <fmtcnct.hxx>
+#include <fmtcntnt.hxx>
+#include <fmteiro.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtfld.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <fmtfordr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtftn.hxx>
+#include <fmtftntx.hxx>
+#include <formatlinebreak.hxx>
+#include <fmthdft.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtline.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtmeta.hxx>
+#include <formatcontentcontrol.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtrfmrk.hxx>
+#include <fmtrowsplt.hxx>
+#include <formatflysplit.hxx>
+#include <formatwraptextatflystart.hxx>
+#include <fmtruby.hxx>
+#include <fmtsrnd.hxx>
+#include <fmturl.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <fntcache.hxx>
+#include <grfatr.hxx>
+#include <hfspacingitem.hxx>
+#include <hintids.hxx>
+#include <init.hxx>
+#include <paratr.hxx>
+#include <proofreadingiterator.hxx>
+#include <editeng/editids.hrc>
+#include <svl/macitem.hxx>
+#include <svx/sdtaitm.hxx>
+#include <swcalwrp.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <tblafmt.hxx>
+#include <tgrditem.hxx>
+#include <tools/globname.hxx>
+#include <tox.hxx>
+#include <unotools/charclass.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <salhelper/singletonref.hxx>
+#include <viscrs.hxx>
+
+using namespace ::com::sun::star;
+
+// some ranges for sets in collections/ nodes
+
+// AttrSet range for the 2 break attributes
+WhichRangesContainer const aBreakSetRange(svl::Items<
+ RES_PAGEDESC, RES_BREAK
+>);
+
+// AttrSet range for TextFormatColl
+// list attributes ( RES_PARATR_LIST_BEGIN - RES_PARATR_LIST_END ) are not
+// included in the paragraph style's itemset.
+WhichRangesContainer const aTextFormatCollSetRange(svl::Items<
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_LEVEL, RES_PARATR_LIST_LEVEL,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+
+ // FillAttribute support
+ XATTR_FILL_FIRST, XATTR_FILL_LAST
+
+>);
+
+// AttrSet range for GrfFormatColl
+WhichRangesContainer const aGrfFormatCollSetRange(svl::Items<
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+// AttrSet range for TextNode
+WhichRangesContainer const aTextNodeSetRange(svl::Items<
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_PARATR_BEGIN, RES_PARATR_END-1,
+ RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+
+ // FillAttribute support (paragraph FillStyle)
+ XATTR_FILL_FIRST, XATTR_FILL_LAST
+
+>);
+
+// AttrSet range for NoTextNode
+WhichRangesContainer const aNoTextNodeSetRange(svl::Items<
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_GRFATR_BEGIN, RES_GRFATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+WhichRangesContainer const aTableSetRange(svl::Items<
+ RES_FILL_ORDER, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_BREAK,
+ RES_HORI_ORIENT, RES_HORI_ORIENT,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_KEEP, RES_KEEP,
+ RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ // #i29550#
+ RES_COLLAPSING_BORDERS, RES_COLLAPSING_BORDERS,
+ // <-- collapsing
+ RES_FRMATR_GRABBAG, RES_FRMATR_GRABBAG,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+WhichRangesContainer const aTableLineSetRange(svl::Items<
+ RES_FILL_ORDER, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_UL_SPACE,
+ // HasTextChangesOnly
+ RES_PRINT, RES_PRINT,
+ RES_PROTECT, RES_PROTECT,
+ RES_VERT_ORIENT, RES_VERT_ORIENT,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_ROW_SPLIT, RES_ROW_SPLIT,
+ RES_FRMATR_GRABBAG, RES_FRMATR_GRABBAG,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+WhichRangesContainer const aTableBoxSetRange(svl::Items<
+ RES_FILL_ORDER, RES_FRM_SIZE,
+ RES_LR_SPACE, RES_UL_SPACE,
+ // HasTextChangesOnly
+ RES_PRINT, RES_PRINT,
+ RES_PROTECT, RES_PROTECT,
+ RES_VERT_ORIENT, RES_VERT_ORIENT,
+ RES_BACKGROUND, RES_SHADOW,
+ RES_FRAMEDIR, RES_FRAMEDIR,
+ RES_FRMATR_GRABBAG, RES_FRMATR_GRABBAG,
+ RES_BOXATR_BEGIN, RES_BOXATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+// AttrSet range for SwFrameFormat
+WhichRangesContainer const aFrameFormatSetRange(svl::Items<
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
+
+ // FillAttribute support (TextFrame, OLE, Writer GraphicObject)
+ XATTR_FILL_FIRST, XATTR_FILL_LAST
+
+>);
+
+// AttrSet range for SwCharFormat
+WhichRangesContainer const aCharFormatSetRange(svl::Items<
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+// AttrSet range for character autostyles
+WhichRangesContainer const aCharAutoFormatSetRange(svl::Items<
+ RES_CHRATR_BEGIN, RES_CHRATR_END-1,
+ RES_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+// AttrSet range for SwPageDescFormat
+WhichRangesContainer const aPgFrameFormatSetRange(svl::Items<
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1
+>);
+
+// create table for accessing default format attributes
+SwDfltAttrTab aAttrTab( POOLATTR_END - POOLATTR_BEGIN, nullptr );
+
+SfxItemInfo aSlotTab[] =
+{
+ // _nSID, _bNeedsPoolRegistration, _bShareable
+ { SID_ATTR_CHAR_CASEMAP, false, true }, // RES_CHRATR_CASEMAP
+ { SID_ATTR_CHAR_CHARSETCOLOR, false, true }, // RES_CHRATR_CHARSETCOLOR
+ { SID_ATTR_CHAR_COLOR, true, true }, // RES_CHRATR_COLOR
+ { SID_ATTR_CHAR_CONTOUR, false, true }, // RES_CHRATR_CONTOUR
+ { SID_ATTR_CHAR_STRIKEOUT, false, true }, // RES_CHRATR_CROSSEDOUT
+ { SID_ATTR_CHAR_ESCAPEMENT, false, true }, // RES_CHRATR_ESCAPEMENT
+ { SID_ATTR_CHAR_FONT, true, true }, // RES_CHRATR_FONT
+ { SID_ATTR_CHAR_FONTHEIGHT, false, true }, // RES_CHRATR_FONTSIZE
+ { SID_ATTR_CHAR_KERNING, false, true }, // RES_CHRATR_KERNING
+ { SID_ATTR_CHAR_LANGUAGE, false, true }, // RES_CHRATR_LANGUAGE
+ { SID_ATTR_CHAR_POSTURE, false, true }, // RES_CHRATR_POSTURE
+ { 0, false, true }, // RES_CHRATR_UNUSED1
+ { SID_ATTR_CHAR_SHADOWED, false, true }, // RES_CHRATR_SHADOWED
+ { SID_ATTR_CHAR_UNDERLINE, true, true }, // RES_CHRATR_UNDERLINE
+ { SID_ATTR_CHAR_WEIGHT, false, true }, // RES_CHRATR_WEIGHT
+ { SID_ATTR_CHAR_WORDLINEMODE, false, true }, // RES_CHRATR_WORDLINEMODE
+ { SID_ATTR_CHAR_AUTOKERN, false, true }, // RES_CHRATR_AUTOKERN
+ { SID_ATTR_FLASH, false, true }, // RES_CHRATR_BLINK
+ { 0, false, true }, // RES_CHRATR_UNUSED2
+ { 0, false, true }, // RES_CHRATR_NOHYPHEN
+ { SID_ATTR_BRUSH_CHAR, true, true }, // RES_CHRATR_BACKGROUND
+ { SID_ATTR_CHAR_CJK_FONT, true, true }, // RES_CHRATR_CJK_FONT
+ { SID_ATTR_CHAR_CJK_FONTHEIGHT, false, true }, // RES_CHRATR_CJK_FONTSIZE
+ { SID_ATTR_CHAR_CJK_LANGUAGE, false, true }, // RES_CHRATR_CJK_LANGUAGE
+ { SID_ATTR_CHAR_CJK_POSTURE, false, true }, // RES_CHRATR_CJK_POSTURE
+ { SID_ATTR_CHAR_CJK_WEIGHT, false, true }, // RES_CHRATR_CJK_WEIGHT
+ { SID_ATTR_CHAR_CTL_FONT, true, true }, // RES_CHRATR_CTL_FONT
+ { SID_ATTR_CHAR_CTL_FONTHEIGHT, false, true }, // RES_CHRATR_CTL_FONTSIZE
+ { SID_ATTR_CHAR_CTL_LANGUAGE, false, true }, // RES_CHRATR_CTL_LANGUAGE
+ { SID_ATTR_CHAR_CTL_POSTURE, false, true }, // RES_CHRATR_CTL_POSTURE
+ { SID_ATTR_CHAR_CTL_WEIGHT, false, true }, // RES_CHRATR_CTL_WEIGHT
+ { SID_ATTR_CHAR_ROTATED, false, true }, // RES_CHRATR_ROTATE
+ { SID_ATTR_CHAR_EMPHASISMARK, false, true }, // RES_CHRATR_EMPHASIS_MARK
+ { SID_ATTR_CHAR_TWO_LINES, false, true }, // RES_CHRATR_TWO_LINES
+ { SID_ATTR_CHAR_SCALEWIDTH, false, true }, // RES_CHRATR_SCALEW
+ { SID_ATTR_CHAR_RELIEF, false, true }, // RES_CHRATR_RELIEF
+ { SID_ATTR_CHAR_HIDDEN, false, true }, // RES_CHRATR_HIDDEN
+ { SID_ATTR_CHAR_OVERLINE, true, true }, // RES_CHRATR_OVERLINE
+ { 0, false, true }, // RES_CHRATR_RSID
+ { SID_ATTR_CHAR_BOX, true, true }, // RES_CHRATR_BOX
+ { SID_ATTR_CHAR_SHADOW, false, true }, // RES_CHRATR_SHADOW
+ { 0, true, true }, // RES_CHRATR_HIGHLIGHT
+ { SID_ATTR_CHAR_GRABBAG, false, true }, // RES_CHRATR_GRABBAG
+ { 0, false, true }, // RES_CHRATR_BIDIRTL
+ { 0, false, true }, // RES_CHRATR_IDCTHINT
+
+ { 0, true, false }, // RES_TXTATR_REFMARK
+ { 0, true, false }, // RES_TXTATR_TOXMARK
+ { 0, false, false }, // RES_TXTATR_META
+ { 0, false, false }, // RES_TXTATR_METAFIELD
+ { 0, false, true }, // RES_TXTATR_AUTOFMT
+ { FN_TXTATR_INET, true, false }, // RES_TXTATR_INETFMT
+ { 0, false, false }, // RES_TXTATR_CHARFMT
+ { SID_ATTR_CHAR_CJK_RUBY, true, false }, // RES_TXTATR_CJK_RUBY
+ { 0, true, true }, // RES_TXTATR_UNKNOWN_CONTAINER
+ { 0, true, false }, // RES_TXTATR_INPUTFIELD
+ { 0, false, false }, // RES_TXTATR_CONTENTCONTROL
+
+ { 0, true, false }, // RES_TXTATR_FIELD
+ { 0, false, false }, // RES_TXTATR_FLYCNT
+ { 0, false, false }, // RES_TXTATR_FTN
+ { 0, false, false }, // RES_TXTATR_ANNOTATION
+ { 0, false, false }, // RES_TXTATR_LINEBREAK
+ { 0, false, true }, // RES_TXTATR_DUMMY1
+
+ { SID_ATTR_PARA_LINESPACE, false, true }, // RES_PARATR_LINESPACING
+ { SID_ATTR_PARA_ADJUST, false, true }, // RES_PARATR_ADJUST
+ { SID_ATTR_PARA_SPLIT, false, true }, // RES_PARATR_SPLIT
+ { SID_ATTR_PARA_ORPHANS, false, true }, // RES_PARATR_ORPHANS
+ { SID_ATTR_PARA_WIDOWS, false, true }, // RES_PARATR_WIDOWS
+ { SID_ATTR_TABSTOP, true, true }, // RES_PARATR_TABSTOP
+ { SID_ATTR_PARA_HYPHENZONE, false, true }, // RES_PARATR_HYPHENZONE
+ { FN_FORMAT_DROPCAPS, false, false }, // RES_PARATR_DROP
+ { SID_ATTR_PARA_REGISTER, false, true }, // RES_PARATR_REGISTER
+ { SID_ATTR_PARA_NUMRULE, false, true }, // RES_PARATR_NUMRULE
+ { SID_ATTR_PARA_SCRIPTSPACE, false, true }, // RES_PARATR_SCRIPTSPACE
+ { SID_ATTR_PARA_HANGPUNCTUATION, false, true }, // RES_PARATR_HANGINGPUNCTUATION
+
+ { SID_ATTR_PARA_FORBIDDEN_RULES, false, true }, // RES_PARATR_FORBIDDEN_RULES
+ { SID_PARA_VERTALIGN, false, true }, // RES_PARATR_VERTALIGN
+ { SID_ATTR_PARA_SNAPTOGRID, false, true }, // RES_PARATR_SNAPTOGRID
+ { SID_ATTR_BORDER_CONNECT, false, true }, // RES_PARATR_CONNECT_BORDER
+
+ { SID_ATTR_PARA_OUTLINE_LEVEL, false, true }, // RES_PARATR_OUTLINELEVEL //#outline level
+ { 0, false, true }, // RES_PARATR_RSID
+ { SID_ATTR_PARA_GRABBAG, false, true }, // RES_PARATR_GRABBAG
+ { 0, false, true }, // RES_PARATR_LIST_ID
+ { 0, false, true }, // RES_PARATR_LIST_LEVEL
+ { 0, false, true }, // RES_PARATR_LIST_ISRESTART
+ { 0, false, true }, // RES_PARATR_LIST_RESTARTVALUE
+ { 0, false, true }, // RES_PARATR_LIST_ISCOUNTED
+ { 0, false, true }, // RES_PARATR_LIST_AUTOFMT
+
+ { 0, false, true }, // RES_FILL_ORDER
+ { 0, false, true }, // RES_FRM_SIZE
+ { SID_ATTR_PAGE_PAPERBIN, false, true }, // RES_PAPER_BIN
+ { SID_ATTR_PARA_FIRSTLINESPACE, false, true }, // RES_MARGIN_FIRSTLINE
+ { SID_ATTR_PARA_LEFTSPACE, false, true }, // RES_MARGIN_TEXTLEFT
+ { SID_ATTR_PARA_RIGHTSPACE, false, true }, // RES_MARGIN_RIGHT
+ { 0, false, true }, // RES_MARGIN_LEFT
+ { 0, false, true }, // RES_MARGIN_GUTTER
+ { 0, false, true }, // RES_MARGIN_GUTTER_RIGHT
+ { SID_ATTR_LRSPACE, false, true }, // RES_LR_SPACE
+ { SID_ATTR_ULSPACE, false, true }, // RES_UL_SPACE
+ { 0, true, false }, // RES_PAGEDESC
+ { SID_ATTR_PARA_PAGEBREAK, false, true }, // RES_BREAK
+ { 0, false, false }, // RES_CNTNT
+ { 0, false, true }, // RES_HEADER
+ { 0, false, true }, // RES_FOOTER
+ { 0, false, true }, // RES_PRINT
+ { FN_OPAQUE, false, true }, // RES_OPAQUE
+ { FN_SET_PROTECT, false, true }, // RES_PROTECT
+ { FN_SURROUND, false, true }, // RES_SURROUND
+ { FN_VERT_ORIENT, false, true }, // RES_VERT_ORIENT
+ { FN_HORI_ORIENT, false, true }, // RES_HORI_ORIENT
+ { 0, false, false }, // RES_ANCHOR
+ { SID_ATTR_BRUSH, true, true }, // RES_BACKGROUND
+ { SID_ATTR_BORDER_OUTER, true, true }, // RES_BOX
+ { SID_ATTR_BORDER_SHADOW, true, true }, // RES_SHADOW
+ { SID_ATTR_MACROITEM, false, true }, // RES_FRMMACRO
+ { FN_ATTR_COLUMNS, false, true }, // RES_COL
+ { SID_ATTR_PARA_KEEP, false, true }, // RES_KEEP
+ { 0, true, true }, // RES_URL
+ { 0, false, true }, // RES_EDIT_IN_READONLY
+
+ { 0, false, true }, // RES_LAYOUT_SPLIT
+ { 0, false, false }, // RES_CHAIN
+ { 0, false, true }, // RES_TEXTGRID
+ { FN_FORMAT_LINENUMBER, false, true }, // RES_LINENUMBER
+ { 0, false, true }, // RES_FTN_AT_TXTEND
+ { 0, false, true }, // RES_END_AT_TXTEND
+ { 0, false, true }, // RES_COLUMNBALANCE
+
+ { SID_ATTR_FRAMEDIRECTION, false, true }, // RES_FRAMEDIR
+
+ { SID_ATTR_HDFT_DYNAMIC_SPACING, false, true }, // RES_HEADER_FOOTER_EAT_SPACING
+ { FN_TABLE_ROW_SPLIT, false, true }, // RES_ROW_SPLIT
+ { 0, false, true }, // RES_FLY_SPLIT
+ // #i18732# - use slot-id define in svx
+ { SID_SW_FOLLOW_TEXT_FLOW, false, true }, // RES_FOLLOW_TEXT_FLOW
+ // #i29550#
+ { SID_SW_COLLAPSING_BORDERS, false, true }, // RES_COLLAPSING_BORDERS
+ // #i28701#
+ { SID_SW_WRAP_INFLUENCE_ON_OBJPOS, false, true }, // RES_WRAP_INFLUENCE_ON_OBJPOS
+ { 0, false, false }, // RES_AUTO_STYLE
+ { 0, false, true }, // RES_FRMATR_STYLE_NAME
+ { 0, false, true }, // RES_FRMATR_CONDITIONAL_STYLE_NAME
+ { 0, false, true }, // RES_FRMATR_GRABBAG
+ { 0, false, true }, // RES_TEXT_VERT_ADJUST
+ { 0, false, true }, // RES_BACKGROUND_FULL_SIZE
+ { 0, false, true }, // RES_RTL_GUTTER
+ { 0, false, true }, // RES_DECORATIVE
+ { 0, false, true }, // RES_WRAP_TEXT_AT_FLY_START
+
+ { 0, false, true }, // RES_GRFATR_MIRRORGRF
+ { SID_ATTR_GRAF_CROP, false, true }, // RES_GRFATR_CROPGRF
+ { 0, false, true }, // RES_GRFATR_ROTATION,
+ { 0, false, true }, // RES_GRFATR_LUMINANCE,
+ { 0, false, true }, // RES_GRFATR_CONTRAST,
+ { 0, false, true }, // RES_GRFATR_CHANNELR,
+ { 0, false, true }, // RES_GRFATR_CHANNELG,
+ { 0, false, true }, // RES_GRFATR_CHANNELB,
+ { 0, false, true }, // RES_GRFATR_GAMMA,
+ { 0, false, true }, // RES_GRFATR_INVERT,
+ { 0, false, true }, // RES_GRFATR_TRANSPARENCY,
+ { 0, false, true }, // RES_GRFATR_DUMMY4,
+ { 0, false, true }, // RES_GRFATR_DUMMY5,
+ { 0, false, true }, // RES_GRFATR_DUMMY6,
+
+ { 0, false, true }, // RES_BOXATR_FORMAT
+ { 0, true, false }, // RES_BOXATR_FORMULA,
+ { 0, false, true }, // RES_BOXATR_VALUE
+
+ { 0, true, true } // RES_UNKNOWNATR_CONTAINER
+};
+
+std::vector<SvGlobalName> *pGlobalOLEExcludeList = nullptr;
+
+SwAutoCompleteWord* SwDoc::s_pAutoCompleteWords = nullptr;
+SwDoc* SwDoc::s_pLast = nullptr;
+
+SwCheckIt* pCheckIt = nullptr;
+static CharClass* pAppCharClass = nullptr;
+
+static CollatorWrapper* pCollator = nullptr,
+ *pCaseCollator = nullptr;
+
+SwCalendarWrapper& s_getCalendarWrapper()
+{
+ static SwCalendarWrapper aCalendarWrapper;
+ return aCalendarWrapper;
+}
+
+void InitCore()
+{
+ SfxPoolItem* pItem;
+
+ aAttrTab[ RES_CHRATR_CASEMAP- POOLATTR_BEGIN ] = new SvxCaseMapItem( SvxCaseMap::NotMapped, RES_CHRATR_CASEMAP);
+ aAttrTab[ RES_CHRATR_CHARSETCOLOR- POOLATTR_BEGIN ] = new SvxColorItem(RES_CHRATR_CHARSETCOLOR);
+ aAttrTab[ RES_CHRATR_COLOR- POOLATTR_BEGIN ] = new SvxColorItem(RES_CHRATR_COLOR);
+ aAttrTab[ RES_CHRATR_CONTOUR- POOLATTR_BEGIN ] = new SvxContourItem( false, RES_CHRATR_CONTOUR );
+ aAttrTab[ RES_CHRATR_CROSSEDOUT- POOLATTR_BEGIN ] = new SvxCrossedOutItem( STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT );
+ aAttrTab[ RES_CHRATR_ESCAPEMENT- POOLATTR_BEGIN ] = new SvxEscapementItem( RES_CHRATR_ESCAPEMENT );
+ aAttrTab[ RES_CHRATR_FONT- POOLATTR_BEGIN ] = new SvxFontItem( RES_CHRATR_FONT );
+
+ aAttrTab[ RES_CHRATR_FONTSIZE- POOLATTR_BEGIN ] = new SvxFontHeightItem( 240, 100, RES_CHRATR_FONTSIZE );
+ aAttrTab[ RES_CHRATR_KERNING- POOLATTR_BEGIN ] = new SvxKerningItem( 0, RES_CHRATR_KERNING );
+ aAttrTab[ RES_CHRATR_LANGUAGE- POOLATTR_BEGIN ] = new SvxLanguageItem(LANGUAGE_DONTKNOW, RES_CHRATR_LANGUAGE );
+ aAttrTab[ RES_CHRATR_POSTURE- POOLATTR_BEGIN ] = new SvxPostureItem( ITALIC_NONE, RES_CHRATR_POSTURE );
+ aAttrTab[ RES_CHRATR_UNUSED1- POOLATTR_BEGIN ] = new SfxVoidItem( RES_CHRATR_UNUSED1 );
+ aAttrTab[ RES_CHRATR_SHADOWED- POOLATTR_BEGIN ] = new SvxShadowedItem( false, RES_CHRATR_SHADOWED );
+ aAttrTab[ RES_CHRATR_UNDERLINE- POOLATTR_BEGIN ] = new SvxUnderlineItem( LINESTYLE_NONE, RES_CHRATR_UNDERLINE );
+ aAttrTab[ RES_CHRATR_WEIGHT- POOLATTR_BEGIN ] = new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_WEIGHT );
+ aAttrTab[ RES_CHRATR_RSID - POOLATTR_BEGIN ] = new SvxRsidItem( 0, RES_CHRATR_RSID );
+ aAttrTab[ RES_CHRATR_WORDLINEMODE- POOLATTR_BEGIN ] = new SvxWordLineModeItem( false, RES_CHRATR_WORDLINEMODE );
+ aAttrTab[ RES_CHRATR_AUTOKERN- POOLATTR_BEGIN ] = new SvxAutoKernItem( false, RES_CHRATR_AUTOKERN );
+ aAttrTab[ RES_CHRATR_BLINK - POOLATTR_BEGIN ] = new SvxBlinkItem( false, RES_CHRATR_BLINK );
+ aAttrTab[ RES_CHRATR_NOHYPHEN - POOLATTR_BEGIN ] = new SvxNoHyphenItem( RES_CHRATR_NOHYPHEN );
+ aAttrTab[ RES_CHRATR_UNUSED2- POOLATTR_BEGIN ] = new SfxVoidItem( RES_CHRATR_UNUSED2 );
+ aAttrTab[ RES_CHRATR_BACKGROUND - POOLATTR_BEGIN ] = new SvxBrushItem( RES_CHRATR_BACKGROUND );
+
+ // CJK-Attributes
+ aAttrTab[ RES_CHRATR_CJK_FONT - POOLATTR_BEGIN ] = new SvxFontItem( RES_CHRATR_CJK_FONT );
+ aAttrTab[ RES_CHRATR_CJK_FONTSIZE - POOLATTR_BEGIN ] = new SvxFontHeightItem( 240, 100, RES_CHRATR_CJK_FONTSIZE );
+ aAttrTab[ RES_CHRATR_CJK_LANGUAGE - POOLATTR_BEGIN ] = new SvxLanguageItem(LANGUAGE_DONTKNOW, RES_CHRATR_CJK_LANGUAGE);
+ aAttrTab[ RES_CHRATR_CJK_POSTURE - POOLATTR_BEGIN ] = new SvxPostureItem(ITALIC_NONE, RES_CHRATR_CJK_POSTURE );
+ aAttrTab[ RES_CHRATR_CJK_WEIGHT - POOLATTR_BEGIN ] = new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_CJK_WEIGHT );
+
+ // CTL-Attributes
+ aAttrTab[ RES_CHRATR_CTL_FONT - POOLATTR_BEGIN ] = new SvxFontItem( RES_CHRATR_CTL_FONT );
+ aAttrTab[ RES_CHRATR_CTL_FONTSIZE - POOLATTR_BEGIN ] = new SvxFontHeightItem( 240, 100, RES_CHRATR_CTL_FONTSIZE );
+ aAttrTab[ RES_CHRATR_CTL_LANGUAGE - POOLATTR_BEGIN ] = new SvxLanguageItem(LANGUAGE_DONTKNOW, RES_CHRATR_CTL_LANGUAGE);
+ aAttrTab[ RES_CHRATR_CTL_POSTURE - POOLATTR_BEGIN ] = new SvxPostureItem(ITALIC_NONE, RES_CHRATR_CTL_POSTURE );
+ aAttrTab[ RES_CHRATR_CTL_WEIGHT - POOLATTR_BEGIN ] = new SvxWeightItem( WEIGHT_NORMAL, RES_CHRATR_CTL_WEIGHT );
+
+ aAttrTab[ RES_CHRATR_ROTATE - POOLATTR_BEGIN ] = new SvxCharRotateItem( 0_deg10, false, RES_CHRATR_ROTATE );
+ aAttrTab[ RES_CHRATR_EMPHASIS_MARK - POOLATTR_BEGIN ] = new SvxEmphasisMarkItem( FontEmphasisMark::NONE, RES_CHRATR_EMPHASIS_MARK );
+ aAttrTab[ RES_CHRATR_TWO_LINES - POOLATTR_BEGIN ] = new SvxTwoLinesItem( false, 0, 0, RES_CHRATR_TWO_LINES );
+ aAttrTab[ RES_CHRATR_SCALEW - POOLATTR_BEGIN ] = new SvxCharScaleWidthItem( 100, RES_CHRATR_SCALEW );
+ aAttrTab[ RES_CHRATR_RELIEF - POOLATTR_BEGIN ] = new SvxCharReliefItem( FontRelief::NONE, RES_CHRATR_RELIEF );
+ aAttrTab[ RES_CHRATR_HIDDEN - POOLATTR_BEGIN ] = new SvxCharHiddenItem( false, RES_CHRATR_HIDDEN );
+ aAttrTab[ RES_CHRATR_OVERLINE- POOLATTR_BEGIN ] = new SvxOverlineItem( LINESTYLE_NONE, RES_CHRATR_OVERLINE );
+ aAttrTab[ RES_CHRATR_BOX - POOLATTR_BEGIN ] = new SvxBoxItem( RES_CHRATR_BOX );
+ aAttrTab[ RES_CHRATR_SHADOW - POOLATTR_BEGIN ] = new SvxShadowItem( RES_CHRATR_SHADOW );
+ aAttrTab[ RES_CHRATR_HIGHLIGHT - POOLATTR_BEGIN ] = new SvxBrushItem( RES_CHRATR_HIGHLIGHT );
+ aAttrTab[ RES_CHRATR_GRABBAG - POOLATTR_BEGIN ] = new SfxGrabBagItem( RES_CHRATR_GRABBAG );
+
+// CharacterAttr - MSWord weak char direction/script override emulation
+ aAttrTab[ RES_CHRATR_BIDIRTL - POOLATTR_BEGIN ] = new SfxInt16Item( RES_CHRATR_BIDIRTL, sal_Int16(-1) );
+ aAttrTab[ RES_CHRATR_IDCTHINT - POOLATTR_BEGIN ] = new SfxInt16Item( RES_CHRATR_IDCTHINT, sal_Int16(-1) );
+
+ aAttrTab[ RES_TXTATR_REFMARK - POOLATTR_BEGIN ] = new SwFormatRefMark( OUString() );
+ aAttrTab[ RES_TXTATR_TOXMARK - POOLATTR_BEGIN ] = new SwTOXMark;
+ aAttrTab[ RES_TXTATR_META - POOLATTR_BEGIN ] = SwFormatMeta::CreatePoolDefault(RES_TXTATR_META);
+ aAttrTab[ RES_TXTATR_METAFIELD - POOLATTR_BEGIN ] = SwFormatMeta::CreatePoolDefault(RES_TXTATR_METAFIELD);
+ aAttrTab[ RES_TXTATR_AUTOFMT- POOLATTR_BEGIN ] = new SwFormatAutoFormat;
+ aAttrTab[ RES_TXTATR_INETFMT - POOLATTR_BEGIN ] = new SwFormatINetFormat( OUString(), OUString() );
+ aAttrTab[ RES_TXTATR_CHARFMT- POOLATTR_BEGIN ] = new SwFormatCharFormat( nullptr );
+ aAttrTab[ RES_TXTATR_CJK_RUBY - POOLATTR_BEGIN ] = new SwFormatRuby( OUString() );
+ aAttrTab[ RES_TXTATR_UNKNOWN_CONTAINER - POOLATTR_BEGIN ] = new SvXMLAttrContainerItem( RES_TXTATR_UNKNOWN_CONTAINER );
+ aAttrTab[ RES_TXTATR_INPUTFIELD - POOLATTR_BEGIN ] = new SwFormatField( RES_TXTATR_INPUTFIELD );
+ aAttrTab[ RES_TXTATR_CONTENTCONTROL - POOLATTR_BEGIN ] = new SwFormatContentControl( RES_TXTATR_CONTENTCONTROL );
+
+ aAttrTab[ RES_TXTATR_FIELD- POOLATTR_BEGIN ] = new SwFormatField( RES_TXTATR_FIELD );
+ aAttrTab[ RES_TXTATR_FLYCNT - POOLATTR_BEGIN ] = new SwFormatFlyCnt( nullptr );
+ aAttrTab[ RES_TXTATR_FTN - POOLATTR_BEGIN ] = new SwFormatFootnote;
+ aAttrTab[ RES_TXTATR_ANNOTATION - POOLATTR_BEGIN ] = new SwFormatField( RES_TXTATR_ANNOTATION );
+ aAttrTab[RES_TXTATR_LINEBREAK - POOLATTR_BEGIN] = new SwFormatLineBreak(SwLineBreakClear::NONE);
+
+// TextAttr - Dummies
+ aAttrTab[ RES_TXTATR_DUMMY1 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_TXTATR_DUMMY1 );
+
+ aAttrTab[ RES_PARATR_LINESPACING- POOLATTR_BEGIN ] = new SvxLineSpacingItem( LINE_SPACE_DEFAULT_HEIGHT, RES_PARATR_LINESPACING );
+ aAttrTab[ RES_PARATR_ADJUST- POOLATTR_BEGIN ] = new SvxAdjustItem( SvxAdjust::Left, RES_PARATR_ADJUST );
+ aAttrTab[ RES_PARATR_SPLIT- POOLATTR_BEGIN ] = new SvxFormatSplitItem( true, RES_PARATR_SPLIT );
+ aAttrTab[ RES_PARATR_WIDOWS- POOLATTR_BEGIN ] = new SvxWidowsItem( 0, RES_PARATR_WIDOWS );
+ aAttrTab[ RES_PARATR_ORPHANS- POOLATTR_BEGIN ] = new SvxOrphansItem( 0, RES_PARATR_ORPHANS );
+ aAttrTab[ RES_PARATR_TABSTOP- POOLATTR_BEGIN ] = new SvxTabStopItem( 1, SVX_TAB_DEFDIST, SvxTabAdjust::Default, RES_PARATR_TABSTOP );
+
+ pItem = new SvxHyphenZoneItem( false, RES_PARATR_HYPHENZONE );
+ static_cast<SvxHyphenZoneItem*>(pItem)->GetMaxHyphens() = 0; // Default: 0
+ aAttrTab[ RES_PARATR_HYPHENZONE- POOLATTR_BEGIN ] = pItem;
+
+ aAttrTab[ RES_PARATR_DROP- POOLATTR_BEGIN ] = new SwFormatDrop;
+ aAttrTab[ RES_PARATR_REGISTER - POOLATTR_BEGIN ] = new SwRegisterItem( false );
+ aAttrTab[ RES_PARATR_NUMRULE - POOLATTR_BEGIN ] = new SwNumRuleItem( OUString() );
+
+ aAttrTab[ RES_PARATR_SCRIPTSPACE - POOLATTR_BEGIN ] = new SvxScriptSpaceItem( true, RES_PARATR_SCRIPTSPACE );
+ aAttrTab[ RES_PARATR_HANGINGPUNCTUATION - POOLATTR_BEGIN ] = new SvxHangingPunctuationItem( true, RES_PARATR_HANGINGPUNCTUATION );
+ aAttrTab[ RES_PARATR_FORBIDDEN_RULES - POOLATTR_BEGIN ] = new SvxForbiddenRuleItem( true, RES_PARATR_FORBIDDEN_RULES );
+ aAttrTab[ RES_PARATR_VERTALIGN - POOLATTR_BEGIN ] = new SvxParaVertAlignItem( SvxParaVertAlignItem::Align::Automatic, RES_PARATR_VERTALIGN );
+ aAttrTab[ RES_PARATR_SNAPTOGRID - POOLATTR_BEGIN ] = new SvxParaGridItem( true, RES_PARATR_SNAPTOGRID );
+ aAttrTab[ RES_PARATR_CONNECT_BORDER - POOLATTR_BEGIN ] = new SwParaConnectBorderItem;
+
+ aAttrTab[ RES_PARATR_OUTLINELEVEL - POOLATTR_BEGIN ] = new SfxUInt16Item( RES_PARATR_OUTLINELEVEL, 0 );
+ aAttrTab[ RES_PARATR_RSID - POOLATTR_BEGIN ] = new SvxRsidItem( 0, RES_PARATR_RSID );
+ aAttrTab[ RES_PARATR_GRABBAG - POOLATTR_BEGIN ] = new SfxGrabBagItem( RES_PARATR_GRABBAG );
+
+ aAttrTab[ RES_PARATR_LIST_ID - POOLATTR_BEGIN ] = new SfxStringItem( RES_PARATR_LIST_ID, OUString() );
+ aAttrTab[ RES_PARATR_LIST_LEVEL - POOLATTR_BEGIN ] = new SfxInt16Item( RES_PARATR_LIST_LEVEL, 0 );
+ aAttrTab[ RES_PARATR_LIST_ISRESTART - POOLATTR_BEGIN ] = new SfxBoolItem( RES_PARATR_LIST_ISRESTART, false );
+ aAttrTab[ RES_PARATR_LIST_RESTARTVALUE - POOLATTR_BEGIN ] = new SfxInt16Item( RES_PARATR_LIST_RESTARTVALUE, 1 );
+ aAttrTab[ RES_PARATR_LIST_ISCOUNTED - POOLATTR_BEGIN ] = new SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, true );
+ aAttrTab[ RES_PARATR_LIST_AUTOFMT - POOLATTR_BEGIN ] = new SwFormatAutoFormat(RES_PARATR_LIST_AUTOFMT);//new SfxSetItem(RES_PARATR_LIST_AUTOFMT, std::make_unique<SfxItemSet>(aCharAutoFormatSetRange));
+
+ aAttrTab[ RES_FILL_ORDER- POOLATTR_BEGIN ] = new SwFormatFillOrder;
+ aAttrTab[ RES_FRM_SIZE- POOLATTR_BEGIN ] = new SwFormatFrameSize;
+ aAttrTab[ RES_PAPER_BIN- POOLATTR_BEGIN ] = new SvxPaperBinItem( RES_PAPER_BIN );
+ aAttrTab[ RES_MARGIN_FIRSTLINE - POOLATTR_BEGIN ] = new SvxFirstLineIndentItem(RES_MARGIN_FIRSTLINE);
+ aAttrTab[ RES_MARGIN_TEXTLEFT - POOLATTR_BEGIN ] = new SvxTextLeftMarginItem(RES_MARGIN_TEXTLEFT);
+ aAttrTab[ RES_MARGIN_RIGHT - POOLATTR_BEGIN ] = new SvxRightMarginItem(RES_MARGIN_RIGHT);
+ aAttrTab[ RES_MARGIN_LEFT - POOLATTR_BEGIN ] = new SvxLeftMarginItem(RES_MARGIN_LEFT);
+ aAttrTab[ RES_MARGIN_GUTTER - POOLATTR_BEGIN ] = new SvxGutterLeftMarginItem(RES_MARGIN_GUTTER);
+ aAttrTab[ RES_MARGIN_GUTTER_RIGHT - POOLATTR_BEGIN ] = new SvxGutterRightMarginItem(RES_MARGIN_GUTTER_RIGHT);
+ aAttrTab[ RES_LR_SPACE- POOLATTR_BEGIN ] = new SvxLRSpaceItem( RES_LR_SPACE );
+ aAttrTab[ RES_UL_SPACE- POOLATTR_BEGIN ] = new SvxULSpaceItem( RES_UL_SPACE );
+ aAttrTab[ RES_PAGEDESC- POOLATTR_BEGIN ] = new SwFormatPageDesc;
+ aAttrTab[ RES_BREAK- POOLATTR_BEGIN ] = new SvxFormatBreakItem( SvxBreak::NONE, RES_BREAK);
+ aAttrTab[ RES_CNTNT- POOLATTR_BEGIN ] = new SwFormatContent;
+ aAttrTab[ RES_HEADER- POOLATTR_BEGIN ] = new SwFormatHeader;
+ aAttrTab[ RES_FOOTER- POOLATTR_BEGIN ] = new SwFormatFooter;
+ aAttrTab[ RES_PRINT- POOLATTR_BEGIN ] = new SvxPrintItem( RES_PRINT );
+ aAttrTab[ RES_OPAQUE- POOLATTR_BEGIN ] = new SvxOpaqueItem( RES_OPAQUE );
+ aAttrTab[ RES_PROTECT- POOLATTR_BEGIN ] = new SvxProtectItem( RES_PROTECT );
+ aAttrTab[ RES_SURROUND- POOLATTR_BEGIN ] = new SwFormatSurround;
+ aAttrTab[ RES_VERT_ORIENT- POOLATTR_BEGIN ] = new SwFormatVertOrient;
+ aAttrTab[ RES_HORI_ORIENT- POOLATTR_BEGIN ] = new SwFormatHoriOrient;
+ aAttrTab[ RES_ANCHOR- POOLATTR_BEGIN ] = new SwFormatAnchor;
+ aAttrTab[ RES_BACKGROUND- POOLATTR_BEGIN ] = new SvxBrushItem( RES_BACKGROUND );
+ aAttrTab[ RES_BOX- POOLATTR_BEGIN ] = new SvxBoxItem( RES_BOX );
+ aAttrTab[ RES_SHADOW- POOLATTR_BEGIN ] = new SvxShadowItem( RES_SHADOW );
+ aAttrTab[ RES_FRMMACRO- POOLATTR_BEGIN ] = new SvxMacroItem( RES_FRMMACRO );
+ aAttrTab[ RES_COL- POOLATTR_BEGIN ] = new SwFormatCol;
+ aAttrTab[ RES_KEEP - POOLATTR_BEGIN ] = new SvxFormatKeepItem( false, RES_KEEP );
+ aAttrTab[ RES_URL - POOLATTR_BEGIN ] = new SwFormatURL();
+ aAttrTab[ RES_EDIT_IN_READONLY - POOLATTR_BEGIN ] = new SwFormatEditInReadonly;
+ aAttrTab[ RES_LAYOUT_SPLIT - POOLATTR_BEGIN ] = new SwFormatLayoutSplit;
+ aAttrTab[ RES_CHAIN - POOLATTR_BEGIN ] = new SwFormatChain;
+ aAttrTab[ RES_TEXTGRID - POOLATTR_BEGIN ] = new SwTextGridItem;
+ aAttrTab[ RES_HEADER_FOOTER_EAT_SPACING - POOLATTR_BEGIN ] = new SwHeaderAndFooterEatSpacingItem;
+ aAttrTab[ RES_LINENUMBER - POOLATTR_BEGIN ] = new SwFormatLineNumber;
+ aAttrTab[ RES_FTN_AT_TXTEND - POOLATTR_BEGIN ] = new SwFormatFootnoteAtTextEnd;
+ aAttrTab[ RES_END_AT_TXTEND - POOLATTR_BEGIN ] = new SwFormatEndAtTextEnd;
+ aAttrTab[ RES_COLUMNBALANCE - POOLATTR_BEGIN ] = new SwFormatNoBalancedColumns;
+ aAttrTab[ RES_FRAMEDIR - POOLATTR_BEGIN ] = new SvxFrameDirectionItem( SvxFrameDirection::Environment, RES_FRAMEDIR );
+ aAttrTab[ RES_ROW_SPLIT - POOLATTR_BEGIN ] = new SwFormatRowSplit;
+ aAttrTab[ RES_FLY_SPLIT - POOLATTR_BEGIN ] = new SwFormatFlySplit;
+
+ // #i18732#
+ aAttrTab[ RES_FOLLOW_TEXT_FLOW - POOLATTR_BEGIN ] = new SwFormatFollowTextFlow(false);
+ // collapsing borders #i29550#
+ aAttrTab[ RES_COLLAPSING_BORDERS - POOLATTR_BEGIN ] = new SfxBoolItem( RES_COLLAPSING_BORDERS, false );
+ // #i28701#
+ // #i35017# - constant name has changed
+ aAttrTab[ RES_WRAP_INFLUENCE_ON_OBJPOS - POOLATTR_BEGIN ] = new SwFormatWrapInfluenceOnObjPos( text::WrapInfluenceOnPosition::ONCE_CONCURRENT );
+
+ aAttrTab[ RES_AUTO_STYLE - POOLATTR_BEGIN ] = new SwFormatAutoFormat( RES_AUTO_STYLE );
+ aAttrTab[ RES_FRMATR_STYLE_NAME - POOLATTR_BEGIN ] = new SfxStringItem( RES_FRMATR_STYLE_NAME, OUString());
+ aAttrTab[ RES_FRMATR_CONDITIONAL_STYLE_NAME - POOLATTR_BEGIN ] = new SfxStringItem( RES_FRMATR_CONDITIONAL_STYLE_NAME, OUString() );
+ aAttrTab[ RES_FRMATR_GRABBAG - POOLATTR_BEGIN ] = new SfxGrabBagItem(RES_FRMATR_GRABBAG);
+ aAttrTab[ RES_TEXT_VERT_ADJUST - POOLATTR_BEGIN ] = new SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP,RES_TEXT_VERT_ADJUST);
+ aAttrTab[ RES_BACKGROUND_FULL_SIZE - POOLATTR_BEGIN ] = new SfxBoolItem(RES_BACKGROUND_FULL_SIZE, true);
+ aAttrTab[ RES_RTL_GUTTER - POOLATTR_BEGIN ] = new SfxBoolItem(RES_RTL_GUTTER, false);
+ aAttrTab[ RES_DECORATIVE - POOLATTR_BEGIN ] = new SfxBoolItem(RES_DECORATIVE, false);
+ aAttrTab[ RES_WRAP_TEXT_AT_FLY_START - POOLATTR_BEGIN ] = new SwFormatWrapTextAtFlyStart;
+
+ aAttrTab[ RES_GRFATR_MIRRORGRF- POOLATTR_BEGIN ] = new SwMirrorGrf;
+ aAttrTab[ RES_GRFATR_CROPGRF- POOLATTR_BEGIN ] = new SwCropGrf;
+ aAttrTab[ RES_GRFATR_ROTATION - POOLATTR_BEGIN ] = new SwRotationGrf;
+ aAttrTab[ RES_GRFATR_LUMINANCE - POOLATTR_BEGIN ] = new SwLuminanceGrf;
+ aAttrTab[ RES_GRFATR_CONTRAST - POOLATTR_BEGIN ] = new SwContrastGrf;
+ aAttrTab[ RES_GRFATR_CHANNELR - POOLATTR_BEGIN ] = new SwChannelRGrf;
+ aAttrTab[ RES_GRFATR_CHANNELG - POOLATTR_BEGIN ] = new SwChannelGGrf;
+ aAttrTab[ RES_GRFATR_CHANNELB - POOLATTR_BEGIN ] = new SwChannelBGrf;
+ aAttrTab[ RES_GRFATR_GAMMA - POOLATTR_BEGIN ] = new SwGammaGrf;
+ aAttrTab[ RES_GRFATR_INVERT - POOLATTR_BEGIN ] = new SwInvertGrf;
+ aAttrTab[ RES_GRFATR_TRANSPARENCY - POOLATTR_BEGIN ] = new SwTransparencyGrf;
+ aAttrTab[ RES_GRFATR_DRAWMODE - POOLATTR_BEGIN ] = new SwDrawModeGrf;
+
+// GraphicAttr - Dummies
+ aAttrTab[ RES_GRFATR_DUMMY4 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY4 );
+ aAttrTab[ RES_GRFATR_DUMMY5 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY5 );
+
+ aAttrTab[ RES_BOXATR_FORMAT- POOLATTR_BEGIN ] = new SwTableBoxNumFormat;
+ aAttrTab[ RES_BOXATR_FORMULA- POOLATTR_BEGIN ] = new SwTableBoxFormula( OUString() );
+ aAttrTab[ RES_BOXATR_VALUE- POOLATTR_BEGIN ] = new SwTableBoxValue;
+
+ aAttrTab[ RES_UNKNOWNATR_CONTAINER- POOLATTR_BEGIN ] =
+ new SvXMLAttrContainerItem( RES_UNKNOWNATR_CONTAINER );
+
+ // get the correct fonts:
+ ::GetDefaultFonts( (aAttrTab[ RES_CHRATR_FONT- POOLATTR_BEGIN ])->StaticWhichCast(RES_CHRATR_FONT),
+ (aAttrTab[ RES_CHRATR_CJK_FONT - POOLATTR_BEGIN ])->StaticWhichCast(RES_CHRATR_CJK_FONT),
+ (aAttrTab[ RES_CHRATR_CTL_FONT - POOLATTR_BEGIN ])->StaticWhichCast(RES_CHRATR_CTL_FONT) );
+
+ SwBreakIt::Create_( ::comphelper::getProcessComponentContext() );
+ pCheckIt = nullptr;
+
+ FrameInit();
+ TextInit_();
+
+ SwSelPaintRects::s_pMapMode = new MapMode;
+ SwFntObj::s_pPixMap = new MapMode;
+
+ pGlobalOLEExcludeList = new std::vector<SvGlobalName>;
+
+ if (!utl::ConfigManager::IsFuzzing())
+ {
+ const SvxSwAutoFormatFlags& rAFlags = SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags();
+ SwDoc::s_pAutoCompleteWords = new SwAutoCompleteWord( rAFlags.nAutoCmpltListLen,
+ rAFlags.nAutoCmpltWordLen );
+ }
+ else
+ {
+ SwDoc::s_pAutoCompleteWords = new SwAutoCompleteWord( 0, 0 );
+ }
+}
+
+void FinitCore()
+{
+ FrameFinit();
+ TextFinit();
+
+ sw::proofreadingiterator::dispose();
+ SwBreakIt::Delete_();
+ delete pCheckIt;
+ delete pAppCharClass;
+ delete pCollator;
+ delete pCaseCollator;
+
+ // destroy default TableAutoFormat
+ delete SwTableAutoFormat::s_pDefaultBoxAutoFormat;
+
+ delete SwSelPaintRects::s_pMapMode;
+ delete SwFntObj::s_pPixMap;
+
+ delete SwEditShell::s_pAutoFormatFlags;
+
+#if OSL_DEBUG_LEVEL > 0
+ // free defaults to prevent assertions
+ if ( aAttrTab[0]->GetRefCount() )
+ SfxItemPool::ReleaseDefaults( &aAttrTab );
+#endif
+ delete SwDoc::s_pAutoCompleteWords;
+
+ // delete all default attributes
+ for(SfxPoolItem* pHt : aAttrTab)
+ {
+ delete pHt;
+ }
+
+ delete pGlobalOLEExcludeList;
+}
+
+// returns the APP - CharClass instance - used for all ToUpper/ToLower/...
+CharClass& GetAppCharClass()
+{
+ if ( !pAppCharClass )
+ {
+ pAppCharClass = new CharClass(
+ ::comphelper::getProcessComponentContext(),
+ SwBreakIt::Get()->GetLanguageTag( GetAppLanguageTag() ));
+ }
+ return *pAppCharClass;
+}
+
+void SwCalendarWrapper::LoadDefaultCalendar( LanguageType eLang )
+{
+ if( eLang != m_nLang )
+ {
+ m_nLang = eLang;
+ loadDefaultCalendar( LanguageTag::convertToLocale( m_nLang ));
+ }
+}
+
+LanguageType GetAppLanguage()
+{
+ if (!utl::ConfigManager::IsFuzzing())
+ return Application::GetSettings().GetLanguageTag().getLanguageType();
+ return LANGUAGE_ENGLISH_US;
+}
+
+const LanguageTag& GetAppLanguageTag()
+{
+ return Application::GetSettings().GetLanguageTag();
+}
+
+CollatorWrapper& GetAppCollator()
+{
+ if( !pCollator )
+ {
+ const lang::Locale& rLcl = g_pBreakIt->GetLocale( GetAppLanguage() );
+
+ pCollator = new CollatorWrapper( ::comphelper::getProcessComponentContext() );
+ pCollator->loadDefaultCollator( rLcl, SW_COLLATOR_IGNORES );
+ }
+ return *pCollator;
+}
+
+CollatorWrapper& GetAppCaseCollator()
+{
+ if( !pCaseCollator )
+ {
+ const lang::Locale& rLcl = g_pBreakIt->GetLocale( GetAppLanguage() );
+
+ pCaseCollator = new CollatorWrapper( ::comphelper::getProcessComponentContext() );
+ pCaseCollator->loadDefaultCollator( rLcl, 0 );
+ }
+ return *pCaseCollator;
+}
+
+namespace
+{
+ class TransWrp
+ {
+ private:
+ std::unique_ptr<utl::TransliterationWrapper> m_xTransWrp;
+ public:
+ TransWrp()
+ {
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+
+ m_xTransWrp.reset(new ::utl::TransliterationWrapper( xContext,
+ TransliterationFlags::IGNORE_CASE |
+ TransliterationFlags::IGNORE_KANA |
+ TransliterationFlags::IGNORE_WIDTH ));
+
+ m_xTransWrp->loadModuleIfNeeded( GetAppLanguage() );
+ }
+ const ::utl::TransliterationWrapper& getTransliterationWrapper() const
+ {
+ return *m_xTransWrp;
+ }
+ };
+}
+
+const ::utl::TransliterationWrapper& GetAppCmpStrIgnore()
+{
+ static TransWrp theTransWrp;
+ return theTransWrp.getTransliterationWrapper();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/proofreadingiterator.cxx b/sw/source/core/bastyp/proofreadingiterator.cxx
new file mode 100644
index 0000000000..64c0ac2b1d
--- /dev/null
+++ b/sw/source/core/bastyp/proofreadingiterator.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/linguistic2/ProofreadingIterator.hpp>
+#include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <vcl/svapp.hxx>
+
+#include <proofreadingiterator.hxx>
+
+namespace
+{
+css::uno::Reference<css::linguistic2::XProofreadingIterator> instance;
+bool disposed = false;
+
+void doDispose(css::uno::Reference<css::linguistic2::XProofreadingIterator> const& inst)
+{
+ css::uno::Reference<css::lang::XComponent> comp(inst, css::uno::UNO_QUERY);
+ if (comp.is())
+ {
+ SolarMutexReleaser r;
+ comp->dispose();
+ }
+}
+}
+
+css::uno::Reference<css::linguistic2::XProofreadingIterator>
+sw::proofreadingiterator::get(css::uno::Reference<css::uno::XComponentContext> const& context)
+{
+ css::uno::Reference<css::linguistic2::XProofreadingIterator> inst(
+ css::linguistic2::ProofreadingIterator::create(context));
+ bool disp;
+ {
+ SolarMutexGuard g;
+ instance = inst;
+ disp = disposed;
+ }
+ if (disp)
+ {
+ doDispose(inst);
+ }
+ return inst;
+}
+
+void sw::proofreadingiterator::dispose()
+{
+ css::uno::Reference<css::linguistic2::XProofreadingIterator> inst;
+ {
+ SolarMutexGuard g;
+ inst = instance;
+ instance.clear();
+ disposed = true;
+ }
+ doDispose(inst);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swcache.cxx b/sw/source/core/bastyp/swcache.cxx
new file mode 100644
index 0000000000..531ce2de44
--- /dev/null
+++ b/sw/source/core/bastyp/swcache.cxx
@@ -0,0 +1,506 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swcache.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <utility>
+
+#include <limits.h>
+
+#ifdef DBG_UTIL
+void SwCache::Check()
+{
+ if ( !m_pRealFirst )
+ {
+ assert(m_pFirst == nullptr && m_pLast == nullptr);
+ return;
+ }
+
+ // consistency check
+ assert(m_pLast->GetNext() == nullptr);
+ assert(m_pRealFirst->GetPrev() == nullptr);
+ sal_uInt16 nCnt = 0;
+ bool bFirstFound = false;
+ SwCacheObj *pObj = m_pRealFirst;
+ SwCacheObj *const pOldRealFirst = m_pRealFirst;
+ while ( pObj )
+ {
+ ++nCnt;
+ if ( pObj == m_pFirst )
+ bFirstFound = true;
+ SwCacheObj* pNext = pObj->GetNext();
+ if ( !pNext )
+ {
+ assert(pObj == m_pLast);
+ }
+ else
+ {
+ assert(pObj == pNext->GetPrev());
+ }
+ pObj = pNext;
+ assert(pObj != pOldRealFirst); (void) pOldRealFirst;
+ }
+ assert(bFirstFound);
+ SAL_WARN_IF( nCnt + m_aFreePositions.size() != size(), "sw.core", "Lost Chain." );
+ SAL_WARN_IF(
+ size() == m_nCurMax && m_nCurMax != m_aFreePositions.size() + nCnt, "sw.core",
+ "Lost FreePositions." );
+}
+
+#define INCREMENT( nVar ) ++nVar
+#define CHECK Check();
+
+#else
+#define INCREMENT( nVar )
+#define CHECK
+#endif
+
+SwCache::SwCache( const sal_uInt16 nInitSize
+#ifdef DBG_UTIL
+ , OString aNm
+#endif
+ ) :
+ m_pRealFirst( nullptr ),
+ m_pFirst( nullptr ),
+ m_pLast( nullptr ),
+ m_nCurMax( nInitSize )
+#ifdef DBG_UTIL
+ , m_aName(std::move( aNm ))
+ , m_nAppend( 0 )
+ , m_nInsertFree( 0 )
+ , m_nReplace( 0 )
+ , m_nGetSuccess( 0 )
+ , m_nGetFail( 0 )
+ , m_nToTop( 0 )
+ , m_nDelete( 0 )
+ , m_nGetSeek( 0 )
+ , m_nAverageSeekCnt( 0 )
+ , m_nFlushCnt( 0 )
+ , m_nFlushedObjects( 0 )
+ , m_nIncreaseMax( 0 )
+ , m_nDecreaseMax( 0 )
+#endif
+{
+ m_aCacheObjects.reserve( nInitSize );
+}
+
+SwCache::~SwCache()
+{
+#ifdef DBG_UTIL
+ SAL_INFO(
+ "sw.core",
+ m_aName << "; number of new entries: " << m_nAppend
+ << "; number of insert on free places: " << m_nInsertFree
+ << "; number of replacements: " << m_nReplace
+ << "; number of successful Gets: " << m_nGetSuccess
+ << "; number of failed Gets: " << m_nGetFail
+ << "; number or reordering (LRU): " << m_nToTop
+ << "; number of suppressions: " << m_nDelete
+ << "; number of Gets without Index: " << m_nGetSeek
+ << "; number of Seek for Get without Index: " << m_nAverageSeekCnt
+ << "; number of Flush calls: " << m_nFlushCnt
+ << "; number of flushed objects: " << m_nFlushedObjects
+ << "; number of Cache expansions: " << m_nIncreaseMax
+ << "; number of Cache reductions: " << m_nDecreaseMax);
+ Check();
+#endif
+}
+
+void SwCache::IncreaseMax( const sal_uInt16 nAdd )
+{
+ if (o3tl::checked_add(m_nCurMax, nAdd, m_nCurMax))
+ {
+ std::abort();
+ }
+#ifdef DBG_UTIL
+ ++m_nIncreaseMax;
+#endif
+}
+
+void SwCache::DecreaseMax( const sal_uInt16 nSub )
+{
+ if ( m_nCurMax > nSub )
+ m_nCurMax = m_nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
+#ifdef DBG_UTIL
+ ++m_nDecreaseMax;
+#endif
+}
+
+void SwCache::Flush()
+{
+ INCREMENT( m_nFlushCnt );
+ SwCacheObj *pObj = m_pRealFirst;
+ m_pRealFirst = m_pFirst = m_pLast = nullptr;
+ while ( pObj )
+ {
+ assert(!pObj->IsLocked());
+ SwCacheObj *pTmp = pObj;
+ pObj = pTmp->GetNext();
+ m_aFreePositions.push_back( pTmp->GetCachePos() );
+ m_aCacheObjects[pTmp->GetCachePos()].reset(); // deletes pTmp
+ INCREMENT( m_nFlushedObjects );
+ }
+}
+
+void SwCache::ToTop( SwCacheObj *pObj )
+{
+ INCREMENT( m_nToTop );
+
+ // cut object out of chain and insert at beginning
+ if ( m_pRealFirst == pObj ) // pFirst was checked by caller
+ {
+ CHECK;
+ return;
+ }
+
+ if ( !m_pRealFirst )
+ {
+ // the first will be inserted
+ assert(!m_pFirst && !m_pLast);
+ m_pRealFirst = m_pFirst = m_pLast = pObj;
+ CHECK;
+ return;
+ }
+
+ assert(m_pFirst && m_pLast);
+
+ // cut
+ if ( pObj == m_pLast )
+ {
+ assert(pObj->GetPrev());
+ m_pLast = pObj->GetPrev();
+ m_pLast->SetNext( nullptr );
+ }
+ else
+ {
+ if ( pObj->GetNext() )
+ pObj->GetNext()->SetPrev( pObj->GetPrev() );
+ if ( pObj->GetPrev() )
+ pObj->GetPrev()->SetNext( pObj->GetNext() );
+ }
+
+ // paste at the (virtual) beginning
+ if ( m_pRealFirst == m_pFirst )
+ {
+ m_pRealFirst->SetPrev( pObj );
+ pObj->SetNext( m_pRealFirst );
+ pObj->SetPrev( nullptr );
+ m_pRealFirst = m_pFirst = pObj;
+ CHECK;
+ }
+ else
+ {
+ if ( m_pFirst->GetPrev() )
+ {
+ m_pFirst->GetPrev()->SetNext( pObj );
+ pObj->SetPrev( m_pFirst->GetPrev() );
+ }
+ else
+ pObj->SetPrev( nullptr );
+ m_pFirst->SetPrev( pObj );
+ pObj->SetNext( m_pFirst );
+ m_pFirst = pObj;
+ CHECK;
+ }
+}
+
+SwCacheObj *SwCache::Get( const void *pOwner, const sal_uInt16 nIndex,
+ const bool bToTop )
+{
+ SwCacheObj *pRet = (nIndex < m_aCacheObjects.size()) ? m_aCacheObjects[ nIndex ].get() : nullptr;
+ if ( pRet )
+ {
+ if ( !pRet->IsOwner( pOwner ) )
+ pRet = nullptr;
+ else if ( bToTop && pRet != m_pFirst )
+ ToTop( pRet );
+ }
+
+#ifdef DBG_UTIL
+ if ( pRet )
+ ++m_nGetSuccess;
+ else
+ ++m_nGetFail;
+#endif
+
+ return pRet;
+}
+
+SwCacheObj *SwCache::Get( const void *pOwner, const bool bToTop )
+{
+ SwCacheObj *pRet = m_pRealFirst;
+ while ( pRet && !pRet->IsOwner( pOwner ) )
+ {
+ INCREMENT( m_nAverageSeekCnt );
+ pRet = pRet->GetNext();
+ }
+
+ if ( bToTop && pRet && pRet != m_pFirst )
+ ToTop( pRet );
+
+#ifdef DBG_UTIL
+ if ( pRet )
+ ++m_nGetSuccess;
+ else
+ ++m_nGetFail;
+ ++m_nGetSeek;
+#endif
+ return pRet;
+}
+
+void SwCache::DeleteObj( SwCacheObj *pObj )
+{
+ CHECK;
+ OSL_ENSURE( !pObj->IsLocked(), "SwCache::Delete: object is locked." );
+ if ( pObj->IsLocked() )
+ return;
+
+ if ( m_pFirst == pObj )
+ {
+ if ( m_pFirst->GetNext() )
+ m_pFirst = m_pFirst->GetNext();
+ else
+ m_pFirst = m_pFirst->GetPrev();
+ }
+ if ( m_pRealFirst == pObj )
+ m_pRealFirst = m_pRealFirst->GetNext();
+ if ( m_pLast == pObj )
+ m_pLast = m_pLast->GetPrev();
+ if ( pObj->GetPrev() )
+ pObj->GetPrev()->SetNext( pObj->GetNext() );
+ if ( pObj->GetNext() )
+ pObj->GetNext()->SetPrev( pObj->GetPrev() );
+
+ m_aFreePositions.push_back( pObj->GetCachePos() );
+ assert(m_aCacheObjects[pObj->GetCachePos()].get() == pObj);
+ m_aCacheObjects[pObj->GetCachePos()] = nullptr; // deletes pObj
+
+ CHECK;
+ if ( m_aCacheObjects.size() > m_nCurMax &&
+ (m_nCurMax <= (m_aCacheObjects.size() - m_aFreePositions.size())) )
+ {
+ // Shrink if possible.To do so we need enough free positions.
+ // Unpleasant side effect: positions will be moved and the owner of
+ // these might not find them afterwards
+ for ( size_t i = 0; i < m_aCacheObjects.size(); ++i )
+ {
+ SwCacheObj *pTmpObj = m_aCacheObjects[i].get();
+ if ( !pTmpObj )
+ {
+ m_aCacheObjects.erase( m_aCacheObjects.begin() + i );
+ --i;
+ }
+ else
+ {
+ pTmpObj->SetCachePos( i );
+ }
+ }
+ m_aFreePositions.clear();
+ }
+ CHECK;
+}
+
+void SwCache::Delete(void const*const pOwner, sal_uInt16 const nIndex)
+{
+ INCREMENT( m_nDelete );
+ if (SwCacheObj *const pObj = Get(pOwner, nIndex, false))
+ DeleteObj(pObj);
+}
+
+void SwCache::Delete( const void *pOwner )
+{
+ INCREMENT( m_nDelete );
+ SwCacheObj *pObj = Get( pOwner, false );
+ if ( pObj )
+ DeleteObj( pObj );
+}
+
+bool SwCache::Insert(SwCacheObj *const pNew, bool const isDuplicateOwnerAllowed)
+{
+ CHECK;
+ OSL_ENSURE( !pNew->GetPrev() && !pNew->GetNext(), "New but not new." );
+ if (!isDuplicateOwnerAllowed)
+ {
+ for (auto const & rpObj : m_aCacheObjects)
+ { // check owner doesn't have a cache object yet; required for SwTextLine
+ assert(!rpObj || rpObj->GetOwner() != pNew->GetOwner());
+ (void) rpObj;
+ }
+ }
+
+ sal_uInt16 nPos;
+ if ( m_aCacheObjects.size() < m_nCurMax )
+ {
+ // there is still space; insert directly
+ INCREMENT( m_nAppend );
+ nPos = m_aCacheObjects.size();
+ m_aCacheObjects.emplace_back(pNew);
+ }
+ else if ( !m_aFreePositions.empty() )
+ {
+ // there are placeholders; use the last of those
+ INCREMENT( m_nInsertFree );
+ const sal_uInt16 nFreePos = m_aFreePositions.size() - 1;
+ nPos = m_aFreePositions[ nFreePos ];
+ m_aCacheObjects[nPos].reset(pNew);
+ m_aFreePositions.erase( m_aFreePositions.begin() + nFreePos );
+ }
+ else
+ {
+ INCREMENT( m_nReplace );
+ // the last of the LRU has to go
+ SwCacheObj *pObj = m_pLast;
+
+ while ( pObj && pObj->IsLocked() )
+ pObj = pObj->GetPrev();
+ if ( !pObj )
+ {
+ SAL_WARN("sw.core", "SwCache overflow.");
+ IncreaseMax(100); // embiggen & try again
+ return Insert(pNew, isDuplicateOwnerAllowed);
+ }
+
+ nPos = pObj->GetCachePos();
+ if ( pObj == m_pLast )
+ {
+ m_pLast = pObj->GetPrev();
+ assert(m_pLast); // must have capacity > 1
+ }
+ if (pObj == m_pFirst)
+ {
+ if (pObj->GetNext())
+ {
+ m_pFirst = pObj->GetNext();
+ }
+ else
+ {
+ m_pFirst = pObj->GetPrev();
+ }
+ assert(m_pFirst); // must have capacity > 1
+ }
+ if (pObj == m_pRealFirst)
+ {
+ m_pRealFirst = pObj->GetNext();
+ assert(m_pRealFirst); // must have capacity > 1
+ }
+ if (pObj->GetPrev())
+ {
+ pObj->GetPrev()->SetNext( pObj->GetNext() );
+ }
+ if (pObj->GetNext())
+ {
+ pObj->GetNext()->SetPrev( pObj->GetPrev() );
+ }
+ m_aCacheObjects[nPos].reset(pNew);
+ }
+ pNew->SetCachePos( nPos );
+
+ if ( m_pFirst )
+ {
+ if ( m_pFirst->GetPrev() )
+ { m_pFirst->GetPrev()->SetNext( pNew );
+ pNew->SetPrev( m_pFirst->GetPrev() );
+ }
+ m_pFirst->SetPrev( pNew );
+ pNew->SetNext( m_pFirst );
+ }
+ else
+ {
+ assert(!m_pLast);
+ m_pLast = pNew;
+ }
+ if ( m_pFirst == m_pRealFirst )
+ m_pRealFirst = pNew;
+ m_pFirst = pNew;
+
+ CHECK;
+ return true;
+}
+
+void SwCache::SetLRUOfst( const sal_uInt16 nOfst )
+{
+ assert(nOfst < m_nCurMax);
+ if ( !m_pRealFirst || ((m_aCacheObjects.size() - m_aFreePositions.size()) < nOfst) )
+ return;
+
+ CHECK;
+ m_pFirst = m_pRealFirst;
+ for ( sal_uInt16 i = 0; i < m_aCacheObjects.size() && i < nOfst; ++i )
+ {
+ if ( m_pFirst->GetNext() && m_pFirst->GetNext()->GetNext() )
+ m_pFirst = m_pFirst->GetNext();
+ else
+ break;
+ }
+ CHECK;
+}
+
+SwCacheObj::SwCacheObj( const void *pOwn ) :
+ m_pNext( nullptr ),
+ m_pPrev( nullptr ),
+ m_nCachePos( USHRT_MAX ),
+ m_nLock( 0 ),
+ m_pOwner( pOwn )
+{
+}
+
+SwCacheObj::~SwCacheObj()
+{
+}
+
+#ifdef DBG_UTIL
+void SwCacheObj::Lock()
+{
+ assert( m_nLock < UCHAR_MAX && "Too many Locks for CacheObject." );
+ ++m_nLock;
+}
+
+void SwCacheObj::Unlock()
+{
+ assert( m_nLock && "No more Locks available." );
+ --m_nLock;
+}
+#endif
+
+SwCacheAccess::~SwCacheAccess()
+{
+ if ( m_pObj )
+ m_pObj->Unlock();
+}
+
+void SwCacheAccess::Get_(bool const isDuplicateOwnerAllowed)
+{
+ OSL_ENSURE( !m_pObj, "SwCacheAcces Obj already available." );
+
+ m_pObj = NewObj();
+ if (!m_rCache.Insert(m_pObj, isDuplicateOwnerAllowed))
+ {
+ delete m_pObj;
+ m_pObj = nullptr;
+ }
+ else
+ {
+ m_pObj->Lock();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swrect.cxx b/sw/source/core/bastyp/swrect.cxx
new file mode 100644
index 0000000000..97e9683a59
--- /dev/null
+++ b/sw/source/core/bastyp/swrect.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swrect.hxx>
+
+#include <libxml/xmlwriter.h>
+
+#ifdef DBG_UTIL
+#include <tools/stream.hxx>
+#endif
+
+SwRect::SwRect( const tools::Rectangle &rRect ) :
+ m_Point( rRect.Left(), rRect.Top() )
+{
+ m_Size.setWidth( rRect.IsWidthEmpty() ? 0 : rRect.Right() - rRect.Left() + 1);
+ m_Size.setHeight(rRect.IsHeightEmpty() ? 0 : rRect.Bottom() - rRect.Top() + 1);
+}
+
+SwRect& SwRect::Union( const SwRect& rRect )
+{
+ if( rRect.IsEmpty())
+ return *this;
+ if( IsEmpty())
+ {
+ *this = rRect;
+ return *this;
+ }
+ if ( Top() > rRect.Top() )
+ Top( rRect.Top() );
+ if ( Left() > rRect.Left() )
+ Left( rRect.Left() );
+ tools::Long n = rRect.Right();
+ if ( Right() < n )
+ Right( n );
+ n = rRect.Bottom();
+ if ( Bottom() < n )
+ Bottom( n );
+ return *this;
+}
+
+SwRect& SwRect::Intersection( const SwRect& rRect )
+{
+ // any similarity between me and given element?
+ if ( Overlaps( rRect ) )
+ {
+ // get smaller right and lower, and greater left and upper edge
+ if ( Left() < rRect.Left() )
+ Left( rRect.Left() );
+ if ( Top() < rRect.Top() )
+ Top( rRect.Top() );
+ tools::Long n = rRect.Right();
+ if ( Right() > n )
+ Right( n );
+ n = rRect.Bottom();
+ if ( Bottom() > n )
+ Bottom( n );
+ }
+ else
+ // Def.: if intersection is empty, set only SSize to 0
+ SSize(0, 0);
+
+ return *this;
+}
+
+SwRect& SwRect::Intersection_( const SwRect& rOther )
+{
+ // get smaller right and lower, and greater left and upper edge
+ auto left = std::max( m_Point.X(), rOther.m_Point.X() );
+ auto top = std::max( m_Point.Y(), rOther.m_Point.Y() );
+ tools::Long right = std::min( m_Point.X() + m_Size.Width(), rOther.m_Point.X() + rOther.m_Size.Width() );
+ auto bottom = std::min( m_Point.Y() + m_Size.Height(), rOther.m_Point.Y() + rOther.m_Size.Height() );
+
+ *this = SwRect( left, top, right - left, bottom - top );
+
+ return *this;
+}
+
+void SwRect::Justify()
+{
+ if ( m_Size.getHeight() < 0 )
+ {
+ m_Point.setY(m_Point.getY() + m_Size.getHeight() + 1);
+ m_Size.setHeight(-m_Size.getHeight());
+ }
+ if ( m_Size.getWidth() < 0 )
+ {
+ m_Point.setX(m_Point.getX() + m_Size.getWidth() + 1);
+ m_Size.setWidth(-m_Size.getWidth());
+ }
+}
+
+// Similar to the inline methods, but we need the function pointers
+void SwRect::Width_( const tools::Long nNew ) { m_Size.setWidth(nNew); }
+void SwRect::Height_( const tools::Long nNew ) { m_Size.setHeight(nNew); }
+void SwRect::Left_( const tools::Long nLeft ){ m_Size.AdjustWidth(m_Point.getX() - nLeft ); m_Point.setX(nLeft); }
+void SwRect::Right_( const tools::Long nRight ){ m_Size.setWidth(nRight - m_Point.getX()); }
+void SwRect::Top_( const tools::Long nTop ){ m_Size.AdjustHeight(m_Point.getY() - nTop ); m_Point.setY(nTop); }
+void SwRect::Bottom_( const tools::Long nBottom ){ m_Size.setHeight(nBottom - m_Point.getY()); }
+
+tools::Long SwRect::Width_() const{ return m_Size.getWidth(); }
+tools::Long SwRect::Height_() const{ return m_Size.getHeight(); }
+tools::Long SwRect::Left_() const{ return m_Point.getX(); }
+tools::Long SwRect::Right_() const{ return m_Point.getX() + m_Size.getWidth(); }
+tools::Long SwRect::Top_() const{ return m_Point.getY(); }
+tools::Long SwRect::Bottom_() const{ return m_Point.getY() + m_Size.getHeight(); }
+
+void SwRect::AddWidth( const tools::Long nAdd ) { m_Size.AdjustWidth(nAdd ); }
+void SwRect::AddHeight( const tools::Long nAdd ) { m_Size.AdjustHeight(nAdd ); }
+void SwRect::AddLeft( const tools::Long nAdd ){ m_Size.AdjustWidth(-nAdd ); m_Point.setX(m_Point.getX() + nAdd); }
+void SwRect::SubLeft( const tools::Long nSub ){ m_Size.AdjustWidth(nSub ); m_Point.setX(m_Point.getX() - nSub); }
+void SwRect::AddRight( const tools::Long nAdd ){ m_Size.AdjustWidth(nAdd ); }
+void SwRect::AddTop( const tools::Long nAdd ){ m_Size.AdjustHeight(-nAdd ); m_Point.setY(m_Point.getY() + nAdd); }
+void SwRect::SubTop( const tools::Long nSub ){ m_Size.AdjustHeight(nSub ); m_Point.setY(m_Point.getY() - nSub); }
+void SwRect::AddBottom( const tools::Long nAdd ){ m_Size.AdjustHeight(nAdd ); }
+void SwRect::SetPosX( const tools::Long nNew ){ m_Point.setX(nNew); }
+void SwRect::SetPosY( const tools::Long nNew ){ m_Point.setY(nNew); }
+
+Size SwRect::Size_() const { return SSize(); }
+Size SwRect::SwappedSize() const { return Size( m_Size.getHeight(), m_Size.getWidth() ); }
+
+tools::Long SwRect::GetLeftDistance( tools::Long nLimit ) const { return m_Point.getX() - nLimit; }
+tools::Long SwRect::GetBottomDistance( tools::Long nLim ) const { return nLim - m_Point.getY() - m_Size.getHeight();}
+tools::Long SwRect::GetTopDistance( tools::Long nLimit ) const { return m_Point.getY() - nLimit; }
+tools::Long SwRect::GetRightDistance( tools::Long nLim ) const { return nLim - m_Point.getX() - m_Size.getWidth(); }
+
+bool SwRect::OverStepLeft( tools::Long nLimit ) const
+ { return nLimit > m_Point.getX() && m_Point.getX() + m_Size.getWidth() > nLimit; }
+bool SwRect::OverStepBottom( tools::Long nLimit ) const
+ { return nLimit > m_Point.getY() && m_Point.getY() + m_Size.getHeight() > nLimit; }
+bool SwRect::OverStepTop( tools::Long nLimit ) const
+ { return nLimit > m_Point.getY() && m_Point.getY() + m_Size.getHeight() > nLimit; }
+bool SwRect::OverStepRight( tools::Long nLimit ) const
+ { return nLimit > m_Point.getX() && m_Point.getX() + m_Size.getWidth() > nLimit; }
+
+void SwRect::SetLeftAndWidth( tools::Long nLeft, tools::Long nNew )
+{
+ m_Point.setX(nLeft);
+ m_Size.setWidth(nNew);
+}
+void SwRect::SetTopAndHeight( tools::Long nTop, tools::Long nNew )
+{
+ m_Point.setY(nTop);
+ m_Size.setHeight(nNew);
+}
+void SwRect::SetRightAndWidth( tools::Long nRight, tools::Long nNew )
+{
+ m_Point.setX(nRight - nNew);
+ m_Size.setWidth(nNew);
+}
+void SwRect::SetBottomAndHeight( tools::Long nBottom, tools::Long nNew )
+{
+ m_Point.setY(nBottom - nNew);
+ m_Size.setHeight(nNew);
+}
+void SwRect::SetUpperLeftCorner( const Point& rNew )
+ { m_Point = rNew; }
+void SwRect::SetUpperRightCorner( const Point& rNew )
+ { m_Point = Point(rNew.X() - m_Size.getWidth(), rNew.Y()); }
+void SwRect::SetLowerLeftCorner( const Point& rNew )
+ { m_Point = Point(rNew.X(), rNew.Y() - m_Size.getHeight()); }
+
+void SwRect::dumpAsXmlAttributes(xmlTextWriterPtr writer) const
+{
+ (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("left"), "%li", Left());
+ (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("top"), "%li", Top());
+ (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("width"), "%li", Width());
+ (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("height"), "%li", Height());
+ (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("bottom"), "%li", Bottom());
+ (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("right"), "%li", Right());
+}
+
+#ifdef DBG_UTIL
+SvStream& WriteSwRect(SvStream &rStream, const SwRect &rRect)
+{
+ rStream.WriteChar('[').WriteInt32(rRect.Top()).
+ WriteChar('/').WriteInt32(rRect.Left()).
+ WriteChar(',').WriteInt32(rRect.Width()).
+ WriteChar('x').WriteInt32(rRect.Height()).
+ WriteOString("] ");
+ return rStream;
+}
+#endif
+
+static_assert( std::is_trivially_copyable< SwRect >::value );
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swregion.cxx b/sw/source/core/bastyp/swregion.cxx
new file mode 100644
index 0000000000..b790bf1476
--- /dev/null
+++ b/sw/source/core/bastyp/swregion.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swrect.hxx>
+#include <swregion.hxx>
+#include <swtypes.hxx>
+
+SwRegionRects::SwRegionRects( const SwRect &rStartRect, sal_uInt16 nInit ) :
+ m_aOrigin( rStartRect )
+{
+ reserve(nInit);
+ push_back( m_aOrigin );
+}
+
+SwRegionRects::SwRegionRects( sal_uInt16 nInit ) :
+ m_aOrigin()
+{
+ reserve(nInit);
+}
+
+// If <rDel> is true then this Rect will be overwritten by <rRect> at
+// position <nPos>. Otherwise <rRect> is attached at the end.
+inline void SwRegionRects::InsertRect( const SwRect &rRect,
+ const sal_uInt16 nPos, bool &rDel )
+{
+ if( rDel )
+ {
+ (*this)[nPos] = rRect;
+ rDel = false;
+ }
+ else
+ {
+ push_back( rRect );
+ }
+}
+
+void SwRegionRects::operator+=( const SwRect &rRect )
+{
+ push_back( rRect );
+}
+
+/** Delete all overlaps of the Rects in array with the given <rRect>
+
+ To do so, all existing rectangles have to be either split or deleted.
+
+ @param rRect rectangle with the area that should be deleted
+*/
+void SwRegionRects::operator-=( const SwRect &rRect )
+{
+ sal_uInt16 nMax = size();
+ for ( sal_uInt16 i = 0; i < nMax; ++i )
+ {
+ if ( rRect.Overlaps( (*this)[i] ) )
+ {
+ SwRect aTmp( (*this)[i] );
+ SwRect aInter( aTmp );
+ aInter.Intersection_( rRect );
+
+ // The first Rect that should be inserted takes position of i.
+ // This avoids one Delete() call.
+ bool bDel = true;
+
+ // now split; only those rectangles should be left over that are in
+ // the "old" but not in the "new" area; hence, not in intersection.
+ tools::Long nTmp = aInter.Top() - aTmp.Top();
+ if ( 0 < nTmp )
+ {
+ const tools::Long nOldVal = aTmp.Height();
+ aTmp.Height(nTmp);
+ InsertRect( aTmp, i, bDel );
+ aTmp.Height( nOldVal );
+ }
+
+ aTmp.Top( aInter.Top() + aInter.Height() );
+ if ( aTmp.Height() > 0 )
+ InsertRect( aTmp, i, bDel );
+
+ aTmp.Top( aInter.Top() );
+ aTmp.Bottom( aInter.Bottom() );
+ nTmp = aInter.Left() - aTmp.Left();
+ if ( 0 < nTmp )
+ {
+ const tools::Long nOldVal = aTmp.Width();
+ aTmp.Width( nTmp );
+ InsertRect( aTmp, i, bDel );
+ aTmp.Width( nOldVal );
+ }
+
+ aTmp.Left( aInter.Left() + aInter.Width() ); //+1?
+ if ( aTmp.Width() > 0 )
+ InsertRect( aTmp, i, bDel );
+
+ if( bDel )
+ {
+ erase( begin() + i );
+ --i; // so that we don't forget any
+ --nMax; // so that we don't check too much
+ }
+ }
+ }
+}
+
+/** invert current rectangle
+
+ Change the shape, such that holes with be areas and areas are holes now.
+
+ Note: If no rects were removed, then the shape is identical to the original
+ shape. As a result, it will be a NULL-SRectangle after inverting.
+*/
+void SwRegionRects::Invert()
+{
+ // not very elegant and fast, but efficient:
+ // Create a new region and remove all areas that are left over. Afterwards
+ // copy all values.
+
+ // To avoid unnecessary memory requirements, create a "useful" initial size:
+ // Number of rectangles in this area * 2 + 2 for the special case of a
+ // single hole (so four Rects in the inverse case).
+ SwRegionRects aInvRegion( m_aOrigin, size()*2+2 );
+ for( const_iterator it = begin(); it != end(); ++it )
+ aInvRegion -= *it;
+
+ // overwrite all existing
+ swap( aInvRegion );
+}
+
+static inline SwTwips CalcArea( const SwRect &rRect )
+{
+ return rRect.Width() * rRect.Height();
+}
+
+void SwRegionRects::LimitToOrigin()
+{
+ for (size_type i = 0; i < size(); ++i )
+ (*this)[ i ].Intersection( m_aOrigin );
+}
+
+// combine all adjacent rectangles
+void SwRegionRects::Compress( CompressType type )
+{
+ bool bAgain;
+ do
+ {
+ sort( begin(), end(), []( const SwRect& l, const SwRect& r ) { return l.Top() < r.Top(); } );
+ bAgain = false;
+ bool bRemoved = false;
+ for (size_type i = 0; i < size(); ++i )
+ {
+ if( (*this)[i].IsEmpty())
+ continue;
+ // Rectangles are sorted by Y axis, so check only pairs of rectangles
+ // that are possibly overlapping or adjacent or close enough to be grouped by the fuzzy
+ // code below.
+ const tools::Long nFuzzy = type == CompressFuzzy ? 1361513 : 0;
+ const tools::Long yMax = (*this)[i].Top() + (*this)[i].Height() + nFuzzy
+ / std::max<tools::Long>( 1, (*this)[i].Width());
+ for(size_type j = i+1; j < size(); ++j)
+ {
+ if( (*this)[j].IsEmpty())
+ continue;
+ if( (*this)[j].Top() > yMax )
+ break;
+ // If one rectangle contains a second completely than the latter
+ // does not need to be stored and can be deleted
+ else if ( (*this)[i].Contains( (*this)[j] ) )
+ {
+ (*this)[j].Width(0); // = erase(), see below
+ bRemoved = true;
+ }
+ else if ( (*this)[j].Contains( (*this)[i] ) )
+ {
+ (*this)[i] = (*this)[j];
+ (*this)[j].Width(0);
+ bRemoved = true;
+ bAgain = true;
+ }
+ else
+ {
+ // Merge adjacent rectangles (possibly overlapping), such rectangles can be
+ // detected by their merged areas being equal to the area of the union
+ // (which is obviously the case if they share one side, and using
+ // the nFuzzy extra allows merging also rectangles that do not quite cover
+ // the entire union but it's close enough).
+
+ // For combining as much as possible (and for having less single
+ // paints), the area of the union can be a little bit larger:
+ // ( 9622 * 141.5 = 1361513 ~= a quarter (1/4) centimeter wider
+ // than the width of an A4 page
+ SwRect aUnion = (*this)[i].GetUnion( (*this)[j] );
+ SwRect aInter = (*this)[i].GetIntersection( (*this)[j] );
+ if ( CalcArea( (*this)[i] ) + CalcArea( (*this)[j] ) - CalcArea( aInter )
+ + nFuzzy >= CalcArea( aUnion ) )
+ {
+ (*this)[i] = aUnion;
+ (*this)[j].Width(0);
+ bRemoved = true;
+ bAgain = true;
+ }
+ }
+ }
+ }
+ // Instead of repeated erase() we Width(0) the elements, and now erase
+ // all empty elements just once.
+ if( bRemoved )
+ resize( std::remove_if(begin(), end(), [](const SwRect& rect) { return rect.IsEmpty(); }) - begin());
+ // Code paths setting bAgain alter elements of the vector, possibly breaking
+ // the Y-axis optimization, so run another pass just to make sure. The adjacent-rects
+ // merging code may possibly benefit from a repeated pass also if two pairs of merged
+ // rects might get merged again and this pass skipped that.
+ } while(bAgain);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/swtypes.cxx b/sw/source/core/bastyp/swtypes.cxx
new file mode 100644
index 0000000000..507804363e
--- /dev/null
+++ b/sw/source/core/bastyp/swtypes.cxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <swtypes.hxx>
+
+#include <editeng/unolingu.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/graph.hxx>
+
+using namespace com::sun::star;
+
+Size GetGraphicSizeTwip(const Graphic& rGraphic, vcl::RenderContext* pOutDev)
+{
+ const MapMode aMapTwip(MapUnit::MapTwip);
+ Size aSize(rGraphic.GetPrefSize());
+
+ if (!aSize.getWidth() && !aSize.getHeight())
+ {
+ const_cast<Graphic&>(rGraphic).makeAvailable();
+ aSize = rGraphic.GetPrefSize();
+ }
+
+ if (MapUnit::MapPixel == rGraphic.GetPrefMapMode().GetMapUnit())
+ {
+ if (!pOutDev)
+ pOutDev = Application::GetDefaultDevice();
+ aSize = pOutDev->PixelToLogic(aSize, aMapTwip);
+ }
+ else
+ {
+ aSize = OutputDevice::LogicToLogic(aSize, rGraphic.GetPrefMapMode(), aMapTwip);
+ }
+ return aSize;
+}
+
+uno::Reference<linguistic2::XSpellChecker1> GetSpellChecker()
+{
+ return LinguMgr::GetSpellChecker();
+}
+
+uno::Reference<linguistic2::XHyphenator> GetHyphenator() { return LinguMgr::GetHyphenator(); }
+
+uno::Reference<linguistic2::XThesaurus> GetThesaurus() { return LinguMgr::GetThesaurus(); }
+
+uno::Reference<linguistic2::XLinguProperties> GetLinguPropertySet()
+{
+ return LinguMgr::GetLinguPropertySet();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/bastyp/tabcol.cxx b/sw/source/core/bastyp/tabcol.cxx
new file mode 100644
index 0000000000..4efc9d8ef8
--- /dev/null
+++ b/sw/source/core/bastyp/tabcol.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tabcol.hxx>
+#include <limits.h>
+
+SwTabCols::SwTabCols( sal_uInt16 nSize ) :
+ m_nLeftMin( 0 ),
+ m_nLeft( 0 ),
+ m_nRight( 0 ),
+ m_nRightMax( 0 ),
+ m_bLastRowAllowedToChange( true )
+{
+ if ( nSize )
+ m_aData.reserve( nSize );
+}
+
+SwTabCols::SwTabCols( const SwTabCols& rCpy ) :
+ m_nLeftMin( rCpy.GetLeftMin() ),
+ m_nLeft( rCpy.GetLeft() ),
+ m_nRight( rCpy.GetRight() ),
+ m_nRightMax( rCpy.GetRightMax() ),
+ m_bLastRowAllowedToChange( rCpy.IsLastRowAllowedToChange() ),
+ m_aData( rCpy.GetData() )
+{
+}
+
+SwTabCols &SwTabCols::operator=( const SwTabCols& rCpy )
+{
+ m_nLeftMin = rCpy.GetLeftMin();
+ m_nLeft = rCpy.GetLeft();
+ m_nRight = rCpy.GetRight();
+ m_nRightMax= rCpy.GetRightMax();
+ m_bLastRowAllowedToChange = rCpy.IsLastRowAllowedToChange();
+
+ Remove( 0, Count() );
+ m_aData = rCpy.GetData();
+
+ return *this;
+}
+
+void SwTabCols::Insert( tools::Long nValue, tools::Long nMin, tools::Long nMax,
+ bool bValue, size_t nPos )
+{
+ SwTabColsEntry aEntry;
+ aEntry.nPos = nValue;
+ aEntry.nMin = nMin;
+ aEntry.nMax = nMax;
+ aEntry.bHidden = bValue;
+ m_aData.insert( m_aData.begin() + nPos, aEntry );
+}
+
+void SwTabCols::Insert( tools::Long nValue, bool bValue, size_t nPos )
+{
+ SwTabColsEntry aEntry;
+ aEntry.nPos = nValue;
+ aEntry.nMin = 0;
+ aEntry.nMax = LONG_MAX;
+ aEntry.bHidden = bValue;
+ m_aData.insert( m_aData.begin() + nPos, aEntry );
+}
+
+void SwTabCols::Remove( size_t nPos, size_t nCount )
+{
+ SwTabColsEntries::iterator aStart = m_aData.begin() + nPos;
+ m_aData.erase( aStart, aStart + nCount );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */