summaryrefslogtreecommitdiffstats
path: root/sw/source/core/edit/edattr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/edit/edattr.cxx')
-rw-r--r--sw/source/core/edit/edattr.cxx853
1 files changed, 853 insertions, 0 deletions
diff --git a/sw/source/core/edit/edattr.cxx b/sw/source/core/edit/edattr.cxx
new file mode 100644
index 000000000..20abffc64
--- /dev/null
+++ b/sw/source/core/edit/edattr.cxx
@@ -0,0 +1,853 @@
+/* -*- 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 <hintids.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <txatbase.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <editsh.hxx>
+#include <edimp.hxx>
+#include <doc.hxx>
+#include <swundo.hxx>
+#include <ndtxt.hxx>
+#include <ftnidx.hxx>
+#include <expfld.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <breakit.hxx>
+#include <fmtfld.hxx>
+#include <txtfrm.hxx>
+#include <scriptinfo.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/languageoptions.hxx>
+#include <charfmt.hxx>
+#include <numrule.hxx>
+
+/*
+ * hard Formatting (Attributes)
+ */
+
+// if selection is bigger as max nodes or more than max selections
+// => no attributes
+static sal_uInt16 getMaxLookup()
+{
+ return 10000;
+}
+
+bool SwEditShell::GetPaMAttr( SwPaM* pPaM, SfxItemSet& rSet,
+ const bool bMergeIndentValuesOfNumRule ) const
+{
+ // ??? pPaM can be different from the Cursor ???
+ if( GetCursorCnt() > getMaxLookup() )
+ {
+ rSet.InvalidateAllItems();
+ return false;
+ }
+
+ SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
+ SfxItemSet *pSet = &rSet;
+
+ for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
+ {
+ // #i27615# if the cursor is in front of the numbering label
+ // the attributes to get are those from the numbering format.
+ if (rCurrentPaM.IsInFrontOfLabel())
+ {
+ SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(),
+ rCurrentPaM.GetPoint()->nNode);
+
+ if (pTextNd)
+ {
+ SwNumRule * pNumRule = pTextNd->GetNumRule();
+
+ if (pNumRule)
+ {
+ int nListLevel = pTextNd->GetActualListLevel();
+
+ if (nListLevel < 0)
+ nListLevel = 0;
+
+ if (nListLevel >= MAXLEVEL)
+ nListLevel = MAXLEVEL - 1;
+
+ const OUString & aCharFormatName =
+ pNumRule->Get(static_cast<sal_uInt16>(nListLevel)).GetCharFormatName();
+ SwCharFormat * pCharFormat =
+ GetDoc()->FindCharFormatByName(aCharFormatName);
+
+ if (pCharFormat)
+ rSet.Put(pCharFormat->GetAttrSet());
+ }
+ }
+
+ continue;
+ }
+
+ sal_uLong nSttNd = rCurrentPaM.GetMark()->nNode.GetIndex(),
+ nEndNd = rCurrentPaM.GetPoint()->nNode.GetIndex();
+ sal_Int32 nSttCnt = rCurrentPaM.GetMark()->nContent.GetIndex();
+ sal_Int32 nEndCnt = rCurrentPaM.GetPoint()->nContent.GetIndex();
+
+ if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
+ {
+ std::swap(nSttNd, nEndNd);
+ std::swap(nSttCnt, nEndCnt);
+ }
+
+ if( nEndNd - nSttNd >= getMaxLookup() )
+ {
+ rSet.ClearItem();
+ rSet.InvalidateAllItems();
+ return false;
+ }
+
+ // at first node the node enter his values into the GetSet (Initial)
+ // all additional nodes are additional merged to GetSet
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ SwNode* pNd = GetDoc()->GetNodes()[ n ];
+ switch( pNd->GetNodeType() )
+ {
+ case SwNodeType::Text:
+ {
+ const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
+ const sal_Int32 nEnd = (n == nEndNd)
+ ? nEndCnt
+ : pNd->GetTextNode()->GetText().getLength();
+
+ static_cast<SwTextNode*>(pNd)->GetParaAttr(*pSet, nStt, nEnd,
+ false, true,
+ bMergeIndentValuesOfNumRule,
+ GetLayout());
+ }
+ break;
+ case SwNodeType::Grf:
+ case SwNodeType::Ole:
+ static_cast<SwContentNode*>(pNd)->GetAttr( *pSet );
+ break;
+
+ default:
+ pNd = nullptr;
+ }
+
+ if( pNd )
+ {
+ if( pSet != &rSet )
+ {
+ if (!GetLayout()->IsHideRedlines()
+ || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden)
+ {
+ rSet.MergeValues( aSet );
+ }
+ }
+
+ if( aSet.Count() )
+ aSet.ClearItem();
+ }
+ pSet = &aSet;
+ }
+
+ }
+
+ return true;
+}
+
+bool SwEditShell::GetCurAttr( SfxItemSet& rSet,
+ const bool bMergeIndentValuesOfNumRule ) const
+{
+ return GetPaMAttr( GetCursor(), rSet, bMergeIndentValuesOfNumRule );
+}
+
+void SwEditShell::GetCurParAttr( SfxItemSet& rSet) const
+{
+ GetPaMParAttr( GetCursor(), rSet );
+}
+
+bool SwEditShell::GetPaMParAttr( SwPaM* pPaM, SfxItemSet& rSet ) const
+{
+ // number of nodes the function has explored so far
+ sal_uInt16 numberOfLookup = 0;
+
+ SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
+ SfxItemSet* pSet = &rSet;
+
+ for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
+ { // for all the point and mark (selections)
+
+ // get the start and the end node of the current selection
+ sal_uLong nSttNd = rCurrentPaM.GetMark()->nNode.GetIndex(),
+ nEndNd = rCurrentPaM.GetPoint()->nNode.GetIndex();
+
+ // reverse start and end if there number aren't sorted correctly
+ if( nSttNd > nEndNd )
+ std::swap(nSttNd, nEndNd);
+
+ // for all the nodes in the current selection
+ // get the node (paragraph) attributes
+ // and merge them in rSet
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ // get the node
+ SwNode* pNd = GetDoc()->GetNodes()[ n ];
+
+ if (GetLayout()->IsHideRedlines()
+ && pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)
+ {
+ continue;
+ }
+
+ if( pNd->IsTextNode() )
+ {
+ // get the node (paragraph) attributes
+ sw::GetAttrMerged(*pSet, *pNd->GetTextNode(), GetLayout());
+
+ if( pSet != &rSet && aSet.Count() )
+ {
+ rSet.MergeValues( aSet );
+ aSet.ClearItem();
+ }
+
+ pSet = &aSet;
+ }
+
+ ++numberOfLookup;
+
+ // if the maximum number of node that can be inspected has been reached
+ if (numberOfLookup >= getMaxLookup())
+ return false;
+ }
+ }
+
+ return true;
+}
+
+SwTextFormatColl* SwEditShell::GetCurTextFormatColl( ) const
+{
+ return GetPaMTextFormatColl( GetCursor() );
+}
+
+SwTextFormatColl* SwEditShell::GetPaMTextFormatColl( SwPaM* pPaM ) const
+{
+ // number of nodes the function have explored so far
+ sal_uInt16 numberOfLookup = 0;
+
+ for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
+ { // for all the point and mark (selections)
+
+ // get the start and the end node of the current selection
+ sal_uLong nSttNd = rCurrentPaM.GetMark()->nNode.GetIndex(),
+ nEndNd = rCurrentPaM.GetPoint()->nNode.GetIndex();
+
+ // reverse start and end if they aren't sorted correctly
+ if( nSttNd > nEndNd )
+ std::swap(nSttNd, nEndNd);
+
+ // for all the nodes in the current Point and Mark
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ // get the node
+ SwNode* pNd = GetDoc()->GetNodes()[ n ];
+
+ ++numberOfLookup;
+
+ // if the maximum number of node that can be inspected has been reached
+ if (numberOfLookup >= getMaxLookup())
+ return nullptr;
+
+ if( pNd->IsTextNode() )
+ {
+ SwTextNode *const pTextNode(sw::GetParaPropsNode(*GetLayout(), SwNodeIndex(*pNd)));
+ // if it's a text node get its named paragraph format
+ SwTextFormatColl *const pFormat = pTextNode->GetTextColl();
+
+ // if the paragraph format exist stop here and return it
+ if( pFormat != nullptr )
+ return pFormat;
+ }
+ }
+ }
+
+ // if none of the selected node contain a named paragraph format
+ return nullptr;
+}
+
+std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> SwEditShell::GetItemWithPaM( sal_uInt16 nWhich )
+{
+ assert(isCHRATR(nWhich)); // sw_redlinehide: only thing that works
+ std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> vItem;
+ for(SwPaM& rCurrentPaM : GetCursor()->GetRingContainer())
+ { // for all the point and mark (selections)
+
+ // get the start and the end node of the current selection
+ sal_uLong nSttNd = rCurrentPaM.Start()->nNode.GetIndex(),
+ nEndNd = rCurrentPaM.End()->nNode.GetIndex();
+ sal_Int32 nSttCnt = rCurrentPaM.Start()->nContent.GetIndex();
+ sal_Int32 nEndCnt = rCurrentPaM.End()->nContent.GetIndex();
+
+ SwPaM* pNewPaM = nullptr;
+ const SfxPoolItem* pItem = nullptr;
+
+ // for all the nodes in the current selection
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ {
+ SwNode* pNd = GetDoc()->GetNodes()[ n ];
+ if( pNd->IsTextNode() )
+ {
+ SwTextNode* pTextNd = static_cast< SwTextNode* >( pNd );
+ const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
+ const sal_Int32 nEnd = (n == nEndNd)
+ ? nEndCnt : pTextNd->GetText().getLength();
+ SwTextFrame const* pFrame;
+ const SwScriptInfo *const pScriptInfo =
+ SwScriptInfo::GetScriptInfo(*pTextNd, &pFrame);
+ TextFrameIndex const iStt(pScriptInfo
+ ? pFrame->MapModelToView(pTextNd, nStt)
+ : TextFrameIndex(-1/*invalid, do not use*/));
+ sal_uInt8 nScript = pScriptInfo
+ ? pScriptInfo->ScriptType(iStt)
+ : css::i18n::ScriptType::WEAK;
+ nWhich = GetWhichOfScript( nWhich, nScript );
+
+ // item from attribute set
+ if( pTextNd->HasSwAttrSet() )
+ {
+ pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
+ pItem = pTextNd->GetSwAttrSet().GetItem( nWhich );
+ vItem.emplace_back( pItem, std::unique_ptr<SwPaM>(pNewPaM) );
+ }
+
+ if( !pTextNd->HasHints() )
+ continue;
+
+ // items with limited range
+ const size_t nSize = pTextNd->GetpSwpHints()->Count();
+ for( size_t m = 0; m < nSize; m++ )
+ {
+ const SwTextAttr* pHt = pTextNd->GetpSwpHints()->Get(m);
+ if( pHt->Which() == RES_TXTATR_AUTOFMT ||
+ pHt->Which() == RES_TXTATR_CHARFMT ||
+ pHt->Which() == RES_TXTATR_INETFMT )
+ {
+ const sal_Int32 nAttrStart = pHt->GetStart();
+ const sal_Int32* pAttrEnd = pHt->End();
+
+ // Ignore items not in selection
+ if( nAttrStart > nEnd )
+ break;
+ if( *pAttrEnd <= nStt )
+ continue;
+
+ nScript = pScriptInfo
+ ? pScriptInfo->ScriptType(iStt)
+ : css::i18n::ScriptType::WEAK;
+ nWhich = GetWhichOfScript( nWhich, nScript );
+ const SfxItemSet* pAutoSet = CharFormat::GetItemSet( pHt->GetAttr() );
+ if( pAutoSet )
+ {
+ SfxItemIter aItemIter( *pAutoSet );
+ pItem = aItemIter.GetCurItem();
+ while( pItem )
+ {
+ if( pItem->Which() == nWhich )
+ {
+ sal_Int32 nStart = 0, nStop = 0;
+ if( nAttrStart < nStt ) // Attribute starts before selection
+ nStart = nStt;
+ else
+ nStart = nAttrStart;
+ if( *pAttrEnd > nEnd ) // Attribute ends after selection
+ nStop = nEnd;
+ else
+ nStop = *pAttrEnd;
+ pNewPaM = new SwPaM(*pNd, nStart, *pNd, nStop);
+ vItem.emplace_back( pItem, std::unique_ptr<SwPaM>(pNewPaM) );
+ break;
+ }
+ pItem = aItemIter.NextItem();
+ }
+ // default item
+ if( !pItem && !pTextNd->HasSwAttrSet() )
+ {
+ pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
+ pItem = pAutoSet->GetPool()->GetPoolDefaultItem( nWhich );
+ vItem.emplace_back( pItem, std::unique_ptr<SwPaM>(pNewPaM) );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return vItem;
+}
+
+bool SwEditShell::GetCurFootnote( SwFormatFootnote* pFillFootnote )
+{
+ // The cursor must be positioned on the current footnotes anchor:
+ SwPaM* pCursor = GetCursor();
+ SwTextNode* pTextNd = pCursor->GetNode().GetTextNode();
+ if( !pTextNd )
+ return false;
+
+ SwTextAttr *const pFootnote = pTextNd->GetTextAttrForCharAt(
+ pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
+ if( pFootnote && pFillFootnote )
+ {
+ // Transfer data from the attribute
+ const SwFormatFootnote &rFootnote = static_cast<SwTextFootnote*>(pFootnote)->GetFootnote();
+ pFillFootnote->SetNumber( rFootnote );
+ pFillFootnote->SetEndNote( rFootnote.IsEndNote() );
+ }
+ return nullptr != pFootnote;
+}
+
+bool SwEditShell::SetCurFootnote( const SwFormatFootnote& rFillFootnote )
+{
+ bool bChgd = false;
+ StartAllAction();
+
+ for(const SwPaM& rCursor : GetCursor()->GetRingContainer())
+ {
+ bChgd |=
+ mxDoc->SetCurFootnote(rCursor, rFillFootnote.GetNumStr(), rFillFootnote.IsEndNote());
+
+ }
+
+ EndAllAction();
+ return bChgd;
+}
+
+bool SwEditShell::HasFootnotes( bool bEndNotes ) const
+{
+ const SwFootnoteIdxs &rIdxs = mxDoc->GetFootnoteIdxs();
+ for ( auto pIdx : rIdxs )
+ {
+ const SwFormatFootnote &rFootnote = pIdx->GetFootnote();
+ if ( bEndNotes == rFootnote.IsEndNote() )
+ return true;
+ }
+ return false;
+}
+
+/// Give a List of all footnotes and their beginning texts
+size_t SwEditShell::GetSeqFootnoteList( SwSeqFieldList& rList, bool bEndNotes )
+{
+ rList.Clear();
+
+ IDocumentRedlineAccess & rIDRA(mxDoc->getIDocumentRedlineAccess());
+
+ const size_t nFootnoteCnt = mxDoc->GetFootnoteIdxs().size();
+ SwTextFootnote* pTextFootnote;
+ for( size_t n = 0; n < nFootnoteCnt; ++n )
+ {
+ pTextFootnote = mxDoc->GetFootnoteIdxs()[ n ];
+ const SwFormatFootnote& rFootnote = pTextFootnote->GetFootnote();
+ if ( rFootnote.IsEndNote() != bEndNotes )
+ continue;
+
+ SwNodeIndex* pIdx = pTextFootnote->GetStartNode();
+ if( pIdx )
+ {
+ SwNodeIndex aIdx( *pIdx, 1 );
+ SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
+ if( !pTextNd )
+ pTextNd = static_cast<SwTextNode*>(mxDoc->GetNodes().GoNext( &aIdx ));
+
+ if( pTextNd )
+ {
+ if (GetLayout()->IsHideRedlines()
+ && sw::IsFootnoteDeleted(rIDRA, *pTextFootnote))
+ {
+ continue;
+ }
+
+ OUString sText(rFootnote.GetViewNumStr(*mxDoc, GetLayout()));
+ if( !sText.isEmpty() )
+ sText += " ";
+ sText += pTextNd->GetExpandText(GetLayout());
+
+ SeqFieldLstElem aNew( sText, pTextFootnote->GetSeqRefNo() );
+ while( rList.InsertSort( aNew ) )
+ aNew.sDlgEntry += " ";
+ }
+ }
+ }
+
+ return rList.Count();
+}
+
+/// Adjust left margin via object bar (similar to adjustment of numerations).
+bool SwEditShell::IsMoveLeftMargin( bool bRight, bool bModulus ) const
+{
+ bool bRet = true;
+
+ const SvxTabStopItem& rTabItem = GetDoc()->GetDefault( RES_PARATR_TABSTOP );
+ sal_uInt16 nDefDist = static_cast<sal_uInt16>(rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134);
+ if( !nDefDist )
+ return false;
+
+ for(SwPaM& rPaM : GetCursor()->GetRingContainer())
+ {
+ sal_uLong nSttNd = rPaM.GetMark()->nNode.GetIndex(),
+ nEndNd = rPaM.GetPoint()->nNode.GetIndex();
+
+ if( nSttNd > nEndNd )
+ std::swap(nSttNd, nEndNd);
+
+ SwContentNode* pCNd;
+ for( sal_uLong n = nSttNd; bRet && n <= nEndNd; ++n )
+ if( nullptr != ( pCNd = GetDoc()->GetNodes()[ n ]->GetTextNode() ))
+ {
+ pCNd = sw::GetParaPropsNode(*GetLayout(), *pCNd);
+ const SvxLRSpaceItem& rLS = static_cast<const SvxLRSpaceItem&>(
+ pCNd->GetAttr( RES_LR_SPACE ));
+ if( bRight )
+ {
+ long nNext = rLS.GetTextLeft() + nDefDist;
+ if( bModulus )
+ nNext = ( nNext / nDefDist ) * nDefDist;
+ SwFrame* pFrame = pCNd->getLayoutFrame( GetLayout() );
+ if ( pFrame )
+ {
+ const sal_uInt16 nFrameWidth = static_cast<sal_uInt16>( pFrame->IsVertical() ?
+ pFrame->getFrameArea().Height() :
+ pFrame->getFrameArea().Width() );
+ bRet = nFrameWidth > ( nNext + MM50 );
+ }
+ else
+ bRet = false;
+ }
+ }
+
+ if( !bRet )
+ break;
+
+ }
+ return bRet;
+}
+
+void SwEditShell::MoveLeftMargin( bool bRight, bool bModulus )
+{
+ StartAllAction();
+ StartUndo( SwUndoId::START );
+
+ SwPaM* pCursor = GetCursor();
+ if( pCursor->GetNext() != pCursor ) // Multiple selection ?
+ {
+ SwPamRanges aRangeArr( *pCursor );
+ SwPaM aPam( *pCursor->GetPoint() );
+ for( size_t n = 0; n < aRangeArr.Count(); ++n )
+ GetDoc()->MoveLeftMargin( aRangeArr.SetPam( n, aPam ),
+ bRight, bModulus, GetLayout() );
+ }
+ else
+ GetDoc()->MoveLeftMargin( *pCursor, bRight, bModulus, GetLayout() );
+
+ EndUndo( SwUndoId::END );
+ EndAllAction();
+}
+
+static SvtScriptType lcl_SetScriptFlags( sal_uInt16 nType )
+{
+ switch( nType )
+ {
+ case css::i18n::ScriptType::LATIN:
+ return SvtScriptType::LATIN;
+ case css::i18n::ScriptType::ASIAN:
+ return SvtScriptType::ASIAN;
+ case css::i18n::ScriptType::COMPLEX:
+ return SvtScriptType::COMPLEX;
+ default:
+ return SvtScriptType::NONE;
+ }
+}
+
+static bool lcl_IsNoEndTextAttrAtPos(SwRootFrame const& rLayout,
+ const SwTextNode& rTNd, sal_Int32 const nPos,
+ SvtScriptType &rScrpt, bool bInSelection, bool bNum )
+{
+ bool bRet = false;
+ OUString sExp;
+
+ // consider numbering
+ if ( bNum )
+ {
+ bRet = false;
+ SwTextNode const*const pPropsNode(sw::GetParaPropsNode(rLayout, rTNd));
+ if (pPropsNode->IsInList())
+ {
+ OSL_ENSURE( pPropsNode->GetNumRule(),
+ "<lcl_IsNoEndTextAttrAtPos(..)> - no list style found at text node. Serious defect." );
+ const SwNumRule* pNumRule = pPropsNode->GetNumRule();
+ if(pNumRule)
+ {
+ int nListLevel = pPropsNode->GetActualListLevel();
+
+ if (nListLevel < 0)
+ nListLevel = 0;
+
+ if (nListLevel >= MAXLEVEL)
+ nListLevel = MAXLEVEL - 1;
+
+ const SwNumFormat &rNumFormat = pNumRule->Get( static_cast<sal_uInt16>(nListLevel) );
+ if( SVX_NUM_BITMAP != rNumFormat.GetNumberingType() )
+ {
+ if ( SVX_NUM_CHAR_SPECIAL == rNumFormat.GetNumberingType() )
+ sExp = OUString(rNumFormat.GetBulletChar());
+ else
+ sExp = pPropsNode->GetNumString(true, MAXLEVEL, &rLayout);
+ }
+ }
+ }
+ }
+
+ // and fields
+ if (nPos < rTNd.GetText().getLength() && CH_TXTATR_BREAKWORD == rTNd.GetText()[nPos])
+ {
+ const SwTextAttr* const pAttr = rTNd.GetTextAttrForCharAt( nPos );
+ if (pAttr)
+ {
+ bRet = true; // all other than fields can be
+ // defined as weak-script ?
+ if ( RES_TXTATR_FIELD == pAttr->Which() )
+ {
+ const SwField* const pField = pAttr->GetFormatField().GetField();
+ if (pField)
+ {
+ sExp += pField->ExpandField(true, &rLayout);
+ }
+ }
+ }
+ }
+
+ const sal_Int32 nEnd = sExp.getLength();
+ if ( nEnd )
+ {
+ if( bInSelection )
+ {
+ sal_uInt16 nScript;
+ for( sal_Int32 n = 0; n < nEnd;
+ n = g_pBreakIt->GetBreakIter()->endOfScript( sExp, n, nScript ))
+ {
+ nScript = g_pBreakIt->GetBreakIter()->getScriptType( sExp, n );
+ rScrpt |= lcl_SetScriptFlags( nScript );
+ }
+ }
+ else
+ rScrpt |= lcl_SetScriptFlags( g_pBreakIt->GetBreakIter()->
+ getScriptType( sExp, nEnd-1 ));
+ }
+
+ return bRet;
+}
+
+/// returns the script type of the selection
+SvtScriptType SwEditShell::GetScriptType() const
+{
+ SvtScriptType nRet = SvtScriptType::NONE;
+
+ {
+ for(SwPaM& rPaM : GetCursor()->GetRingContainer())
+ {
+ const SwPosition *pStt = rPaM.Start(),
+ *pEnd = pStt == rPaM.GetMark()
+ ? rPaM.GetPoint()
+ : rPaM.GetMark();
+ if( pStt == pEnd || *pStt == *pEnd )
+ {
+ const SwTextNode* pTNd = pStt->nNode.GetNode().GetTextNode();
+ if( pTNd )
+ {
+ // try to get SwScriptInfo
+ SwTextFrame const* pFrame;
+ const SwScriptInfo *const pScriptInfo =
+ SwScriptInfo::GetScriptInfo(*pTNd, &pFrame);
+
+ sal_Int32 nPos = pStt->nContent.GetIndex();
+ //Task 90448: we need the scripttype of the previous
+ // position, if no selection exist!
+ if( nPos )
+ {
+ SwIndex aIdx( pStt->nContent );
+ if( pTNd->GoPrevious( &aIdx, CRSR_SKIP_CHARS ) )
+ nPos = aIdx.GetIndex();
+ }
+
+ sal_uInt16 nScript;
+
+ if (!pTNd->GetText().isEmpty())
+ {
+ nScript = pScriptInfo
+ ? pScriptInfo->ScriptType(pFrame->MapModelToView(pTNd, nPos))
+ : g_pBreakIt->GetBreakIter()->getScriptType( pTNd->GetText(), nPos );
+ }
+ else
+ nScript = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() );
+
+ if (!lcl_IsNoEndTextAttrAtPos(*GetLayout(), *pTNd, nPos, nRet, false, false))
+ nRet |= lcl_SetScriptFlags( nScript );
+ }
+ }
+ else
+ {
+ sal_uLong nEndIdx = pEnd->nNode.GetIndex();
+ SwNodeIndex aIdx( pStt->nNode );
+ for( ; aIdx.GetIndex() <= nEndIdx; ++aIdx )
+ if( aIdx.GetNode().IsTextNode() )
+ {
+ const SwTextNode* pTNd = aIdx.GetNode().GetTextNode();
+ const OUString& rText = pTNd->GetText();
+
+ // try to get SwScriptInfo
+ SwTextFrame const* pFrame;
+ const SwScriptInfo *const pScriptInfo =
+ SwScriptInfo::GetScriptInfo(*pTNd, &pFrame);
+
+ sal_Int32 nChg = aIdx == pStt->nNode
+ ? pStt->nContent.GetIndex()
+ : 0;
+ sal_Int32 nEndPos = aIdx == nEndIdx
+ ? pEnd->nContent.GetIndex()
+ : rText.getLength();
+
+ OSL_ENSURE( nEndPos <= rText.getLength(),
+ "Index outside the range - endless loop!" );
+ if (nEndPos > rText.getLength())
+ nEndPos = rText.getLength();
+
+ bool const isUntilEnd(pScriptInfo
+ ? pFrame->MapViewToModelPos(TextFrameIndex(pFrame->GetText().getLength())) <= *pEnd
+ : rText.getLength() == nEndPos);
+ sal_uInt16 nScript;
+ while( nChg < nEndPos )
+ {
+ TextFrameIndex iChg(pScriptInfo
+ ? pFrame->MapModelToView(pTNd, nChg)
+ : TextFrameIndex(-1/*invalid, do not use*/));
+ nScript = pScriptInfo ?
+ pScriptInfo->ScriptType( iChg ) :
+ g_pBreakIt->GetBreakIter()->getScriptType(
+ rText, nChg );
+
+ if (!lcl_IsNoEndTextAttrAtPos(*GetLayout(), *pTNd, nChg, nRet, true,
+ TextFrameIndex(0) == iChg && isUntilEnd))
+ {
+ nRet |= lcl_SetScriptFlags( nScript );
+ }
+
+ if( (SvtScriptType::LATIN | SvtScriptType::ASIAN |
+ SvtScriptType::COMPLEX) == nRet )
+ break;
+
+ sal_Int32 nFieldPos = nChg+1;
+
+ if (pScriptInfo)
+ {
+ iChg = pScriptInfo->NextScriptChg(iChg);
+ if (iChg == TextFrameIndex(COMPLETE_STRING))
+ {
+ nChg = pTNd->Len();
+ }
+ else
+ {
+ std::pair<SwTextNode*, sal_Int32> const tmp(
+ pFrame->MapViewToModel(iChg));
+ nChg = (tmp.first == pTNd)
+ ? tmp.second
+ : pTNd->Len();
+ }
+ }
+ else
+ {
+ nChg = g_pBreakIt->GetBreakIter()->endOfScript(
+ rText, nChg, nScript );
+ }
+
+ nFieldPos = rText.indexOf(
+ CH_TXTATR_BREAKWORD, nFieldPos);
+ if ((-1 != nFieldPos) && (nFieldPos < nChg))
+ nChg = nFieldPos;
+ }
+ if( (SvtScriptType::LATIN | SvtScriptType::ASIAN |
+ SvtScriptType::COMPLEX) == nRet )
+ break;
+ }
+ }
+ if( (SvtScriptType::LATIN | SvtScriptType::ASIAN |
+ SvtScriptType::COMPLEX) == nRet )
+ break;
+
+ }
+ }
+ if( nRet == SvtScriptType::NONE )
+ nRet = SvtLanguageOptions::GetScriptTypeOfLanguage( LANGUAGE_SYSTEM );
+ return nRet;
+}
+
+LanguageType SwEditShell::GetCurLang() const
+{
+ const SwPaM* pCursor = GetCursor();
+ const SwPosition& rPos = *pCursor->GetPoint();
+ const SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode();
+ LanguageType nLang;
+ if( pTNd )
+ {
+ //JP 24.9.2001: if exist no selection, then get the language before
+ // the current character!
+ sal_Int32 nPos = rPos.nContent.GetIndex();
+ if( nPos && !pCursor->HasMark() )
+ --nPos;
+ nLang = pTNd->GetLang( nPos );
+ }
+ else
+ nLang = LANGUAGE_DONTKNOW;
+ return nLang;
+}
+
+sal_uInt16 SwEditShell::GetScalingOfSelectedText() const
+{
+ const SwPaM* pCursor = GetCursor();
+ const SwPosition* pStt = pCursor->Start();
+ const SwTextNode* pTNd = pStt->nNode.GetNode().GetTextNode();
+ OSL_ENSURE( pTNd, "no textnode available" );
+
+ sal_uInt16 nScaleWidth;
+ if( pTNd )
+ {
+ SwTextFrame *const pFrame(static_cast<SwTextFrame *>(
+ pTNd->getLayoutFrame(GetLayout(), pStt)));
+ assert(pFrame); // shell cursor must be positioned in node with frame
+ TextFrameIndex const nStart(pFrame->MapModelToViewPos(*pStt));
+ TextFrameIndex const nEnd(
+ sw::FrameContainsNode(*pFrame, pCursor->End()->nNode.GetIndex())
+ ? pFrame->MapModelToViewPos(*pCursor->End())
+ : TextFrameIndex(pFrame->GetText().getLength()));
+ nScaleWidth = pFrame->GetScalingOfSelectedText(nStart, nEnd);
+ }
+ else
+ nScaleWidth = 100; // default are no scaling -> 100%
+ return nScaleWidth;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */