nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / edit / edattr.cxx
blob58bb555c2e083bbe575070bf529940ea9ef8d6d7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <hintids.hxx>
22 #include <editeng/tstpitem.hxx>
23 #include <editeng/lrspitem.hxx>
24 #include <com/sun/star/i18n/ScriptType.hpp>
25 #include <com/sun/star/i18n/XBreakIterator.hpp>
26 #include <txatbase.hxx>
27 #include <txtftn.hxx>
28 #include <fmtftn.hxx>
29 #include <editsh.hxx>
30 #include <edimp.hxx>
31 #include <doc.hxx>
32 #include <swundo.hxx>
33 #include <ndtxt.hxx>
34 #include <ftnidx.hxx>
35 #include <expfld.hxx>
36 #include <rootfrm.hxx>
37 #include <cntfrm.hxx>
38 #include <breakit.hxx>
39 #include <fmtfld.hxx>
40 #include <txtfrm.hxx>
41 #include <scriptinfo.hxx>
42 #include <svl/itemiter.hxx>
43 #include <svl/languageoptions.hxx>
44 #include <charfmt.hxx>
45 #include <numrule.hxx>
48 * hard Formatting (Attributes)
51 // if selection is bigger as max nodes or more than max selections
52 // => no attributes
53 static sal_uInt16 getMaxLookup()
55 return 10000;
58 bool SwEditShell::GetPaMAttr( SwPaM* pPaM, SfxItemSet& rSet,
59 const bool bMergeIndentValuesOfNumRule ) const
61 // ??? pPaM can be different from the Cursor ???
62 if( GetCursorCnt() > getMaxLookup() )
64 rSet.InvalidateAllItems();
65 return false;
68 SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
69 SfxItemSet *pSet = &rSet;
71 for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
73 // #i27615# if the cursor is in front of the numbering label
74 // the attributes to get are those from the numbering format.
75 if (rCurrentPaM.IsInFrontOfLabel())
77 SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(),
78 rCurrentPaM.GetPoint()->nNode);
80 if (pTextNd)
82 SwNumRule * pNumRule = pTextNd->GetNumRule();
84 if (pNumRule)
86 int nListLevel = pTextNd->GetActualListLevel();
88 if (nListLevel < 0)
89 nListLevel = 0;
91 if (nListLevel >= MAXLEVEL)
92 nListLevel = MAXLEVEL - 1;
94 const OUString & aCharFormatName =
95 pNumRule->Get(static_cast<sal_uInt16>(nListLevel)).GetCharFormatName();
96 SwCharFormat * pCharFormat =
97 GetDoc()->FindCharFormatByName(aCharFormatName);
99 if (pCharFormat)
100 rSet.Put(pCharFormat->GetAttrSet());
104 continue;
107 sal_uLong nSttNd = rCurrentPaM.GetMark()->nNode.GetIndex(),
108 nEndNd = rCurrentPaM.GetPoint()->nNode.GetIndex();
109 sal_Int32 nSttCnt = rCurrentPaM.GetMark()->nContent.GetIndex();
110 sal_Int32 nEndCnt = rCurrentPaM.GetPoint()->nContent.GetIndex();
112 if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
114 std::swap(nSttNd, nEndNd);
115 std::swap(nSttCnt, nEndCnt);
118 if( nEndNd - nSttNd >= getMaxLookup() )
120 rSet.ClearItem();
121 rSet.InvalidateAllItems();
122 return false;
125 // at first node the node enter his values into the GetSet (Initial)
126 // all additional nodes are additional merged to GetSet
127 for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
129 SwNode* pNd = GetDoc()->GetNodes()[ n ];
130 switch( pNd->GetNodeType() )
132 case SwNodeType::Text:
134 const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
135 const sal_Int32 nEnd = (n == nEndNd)
136 ? nEndCnt
137 : pNd->GetTextNode()->GetText().getLength();
139 static_cast<SwTextNode*>(pNd)->GetParaAttr(*pSet, nStt, nEnd,
140 false, true,
141 bMergeIndentValuesOfNumRule,
142 GetLayout());
144 break;
145 case SwNodeType::Grf:
146 case SwNodeType::Ole:
147 static_cast<SwContentNode*>(pNd)->GetAttr( *pSet );
148 break;
150 default:
151 pNd = nullptr;
154 if( pNd )
156 if( pSet != &rSet )
158 if (!GetLayout()->HasMergedParas()
159 || pNd->GetRedlineMergeFlag() != SwNode::Merge::Hidden)
161 rSet.MergeValues( aSet );
165 if( aSet.Count() )
166 aSet.ClearItem();
168 pSet = &aSet;
173 return true;
176 bool SwEditShell::GetCurAttr( SfxItemSet& rSet,
177 const bool bMergeIndentValuesOfNumRule ) const
179 return GetPaMAttr( GetCursor(), rSet, bMergeIndentValuesOfNumRule );
182 void SwEditShell::GetCurParAttr( SfxItemSet& rSet) const
184 GetPaMParAttr( GetCursor(), rSet );
187 bool SwEditShell::GetPaMParAttr( SwPaM* pPaM, SfxItemSet& rSet ) const
189 // number of nodes the function has explored so far
190 sal_uInt16 numberOfLookup = 0;
192 SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
193 SfxItemSet* pSet = &rSet;
195 for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
196 { // for all the point and mark (selections)
198 // get the start and the end node of the current selection
199 sal_uLong nSttNd = rCurrentPaM.GetMark()->nNode.GetIndex(),
200 nEndNd = rCurrentPaM.GetPoint()->nNode.GetIndex();
202 // reverse start and end if there number aren't sorted correctly
203 if( nSttNd > nEndNd )
204 std::swap(nSttNd, nEndNd);
206 // for all the nodes in the current selection
207 // get the node (paragraph) attributes
208 // and merge them in rSet
209 for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
211 // get the node
212 SwNode* pNd = GetDoc()->GetNodes()[ n ];
214 if (GetLayout()->HasMergedParas()
215 && pNd->GetRedlineMergeFlag() == SwNode::Merge::Hidden)
217 continue;
220 if( pNd->IsTextNode() )
222 // get the node (paragraph) attributes
223 sw::GetAttrMerged(*pSet, *pNd->GetTextNode(), GetLayout());
225 if( pSet != &rSet && aSet.Count() )
227 rSet.MergeValues( aSet );
228 aSet.ClearItem();
231 pSet = &aSet;
234 ++numberOfLookup;
236 // if the maximum number of node that can be inspected has been reached
237 if (numberOfLookup >= getMaxLookup())
238 return false;
242 return true;
245 SwTextFormatColl* SwEditShell::GetCurTextFormatColl( ) const
247 return GetPaMTextFormatColl( GetCursor() );
250 SwTextFormatColl* SwEditShell::GetPaMTextFormatColl( SwPaM* pPaM ) const
252 // number of nodes the function have explored so far
253 sal_uInt16 numberOfLookup = 0;
255 for(SwPaM& rCurrentPaM : pPaM->GetRingContainer())
256 { // for all the point and mark (selections)
258 // get the start and the end node of the current selection
259 sal_uLong nSttNd = rCurrentPaM.GetMark()->nNode.GetIndex(),
260 nEndNd = rCurrentPaM.GetPoint()->nNode.GetIndex();
262 // reverse start and end if they aren't sorted correctly
263 if( nSttNd > nEndNd )
264 std::swap(nSttNd, nEndNd);
266 // for all the nodes in the current Point and Mark
267 for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
269 // get the node
270 SwNode* pNd = GetDoc()->GetNodes()[ n ];
272 ++numberOfLookup;
274 // if the maximum number of node that can be inspected has been reached
275 if (numberOfLookup >= getMaxLookup())
276 return nullptr;
278 if( pNd->IsTextNode() )
280 SwTextNode *const pTextNode(sw::GetParaPropsNode(*GetLayout(), SwNodeIndex(*pNd)));
281 // if it's a text node get its named paragraph format
282 SwTextFormatColl *const pFormat = pTextNode->GetTextColl();
284 // if the paragraph format exist stop here and return it
285 if( pFormat != nullptr )
286 return pFormat;
291 // if none of the selected node contain a named paragraph format
292 return nullptr;
295 std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> SwEditShell::GetItemWithPaM( sal_uInt16 nWhich )
297 assert(isCHRATR(nWhich)); // sw_redlinehide: only thing that works
298 std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> vItem;
299 for(SwPaM& rCurrentPaM : GetCursor()->GetRingContainer())
300 { // for all the point and mark (selections)
302 // get the start and the end node of the current selection
303 sal_uLong nSttNd = rCurrentPaM.Start()->nNode.GetIndex(),
304 nEndNd = rCurrentPaM.End()->nNode.GetIndex();
305 sal_Int32 nSttCnt = rCurrentPaM.Start()->nContent.GetIndex();
306 sal_Int32 nEndCnt = rCurrentPaM.End()->nContent.GetIndex();
308 SwPaM* pNewPaM = nullptr;
309 const SfxPoolItem* pItem = nullptr;
311 // for all the nodes in the current selection
312 for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
314 SwNode* pNd = GetDoc()->GetNodes()[ n ];
315 if( pNd->IsTextNode() )
317 SwTextNode* pTextNd = static_cast< SwTextNode* >( pNd );
318 const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
319 const sal_Int32 nEnd = (n == nEndNd)
320 ? nEndCnt : pTextNd->GetText().getLength();
321 SwTextFrame const* pFrame;
322 const SwScriptInfo *const pScriptInfo =
323 SwScriptInfo::GetScriptInfo(*pTextNd, &pFrame);
324 TextFrameIndex const iStt(pScriptInfo
325 ? pFrame->MapModelToView(pTextNd, nStt)
326 : TextFrameIndex(-1/*invalid, do not use*/));
327 sal_uInt8 nScript = pScriptInfo
328 ? pScriptInfo->ScriptType(iStt)
329 : css::i18n::ScriptType::WEAK;
330 nWhich = GetWhichOfScript( nWhich, nScript );
332 // item from attribute set
333 if( pTextNd->HasSwAttrSet() )
335 pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
336 pItem = pTextNd->GetSwAttrSet().GetItem( nWhich );
337 vItem.emplace_back( pItem, std::unique_ptr<SwPaM>(pNewPaM) );
340 if( !pTextNd->HasHints() )
341 continue;
343 // items with limited range
344 const size_t nSize = pTextNd->GetpSwpHints()->Count();
345 for( size_t m = 0; m < nSize; m++ )
347 const SwTextAttr* pHt = pTextNd->GetpSwpHints()->Get(m);
348 if( pHt->Which() == RES_TXTATR_AUTOFMT ||
349 pHt->Which() == RES_TXTATR_CHARFMT ||
350 pHt->Which() == RES_TXTATR_INETFMT )
352 const sal_Int32 nAttrStart = pHt->GetStart();
353 const sal_Int32* pAttrEnd = pHt->End();
355 // Ignore items not in selection
356 if( nAttrStart > nEnd )
357 break;
358 if( *pAttrEnd <= nStt )
359 continue;
361 nScript = pScriptInfo
362 ? pScriptInfo->ScriptType(iStt)
363 : css::i18n::ScriptType::WEAK;
364 nWhich = GetWhichOfScript( nWhich, nScript );
365 const SfxItemSet* pAutoSet = CharFormat::GetItemSet( pHt->GetAttr() );
366 if( pAutoSet )
368 SfxItemIter aItemIter( *pAutoSet );
369 pItem = aItemIter.GetCurItem();
370 while( pItem )
372 if( pItem->Which() == nWhich )
374 sal_Int32 nStart = 0, nStop = 0;
375 if( nAttrStart < nStt ) // Attribute starts before selection
376 nStart = nStt;
377 else
378 nStart = nAttrStart;
379 if( *pAttrEnd > nEnd ) // Attribute ends after selection
380 nStop = nEnd;
381 else
382 nStop = *pAttrEnd;
383 pNewPaM = new SwPaM(*pNd, nStart, *pNd, nStop);
384 vItem.emplace_back( pItem, std::unique_ptr<SwPaM>(pNewPaM) );
385 break;
387 pItem = aItemIter.NextItem();
389 // default item
390 if( !pItem && !pTextNd->HasSwAttrSet() )
392 pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
393 pItem = pAutoSet->GetPool()->GetPoolDefaultItem( nWhich );
394 vItem.emplace_back( pItem, std::unique_ptr<SwPaM>(pNewPaM) );
402 return vItem;
405 bool SwEditShell::GetCurFootnote( SwFormatFootnote* pFillFootnote )
407 // The cursor must be positioned on the current footnotes anchor:
408 SwPaM* pCursor = GetCursor();
409 SwTextNode* pTextNd = pCursor->GetNode().GetTextNode();
410 if( !pTextNd )
411 return false;
413 SwTextAttr *const pFootnote = pTextNd->GetTextAttrForCharAt(
414 pCursor->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
415 if( pFootnote && pFillFootnote )
417 // Transfer data from the attribute
418 const SwFormatFootnote &rFootnote = static_cast<SwTextFootnote*>(pFootnote)->GetFootnote();
419 pFillFootnote->SetNumber( rFootnote );
420 pFillFootnote->SetEndNote( rFootnote.IsEndNote() );
422 return nullptr != pFootnote;
425 bool SwEditShell::SetCurFootnote( const SwFormatFootnote& rFillFootnote )
427 bool bChgd = false;
428 StartAllAction();
430 for(const SwPaM& rCursor : GetCursor()->GetRingContainer())
432 bChgd |=
433 mxDoc->SetCurFootnote(rCursor, rFillFootnote.GetNumStr(), rFillFootnote.IsEndNote());
437 EndAllAction();
438 return bChgd;
441 bool SwEditShell::HasFootnotes( bool bEndNotes ) const
443 const SwFootnoteIdxs &rIdxs = mxDoc->GetFootnoteIdxs();
444 for ( auto pIdx : rIdxs )
446 const SwFormatFootnote &rFootnote = pIdx->GetFootnote();
447 if ( bEndNotes == rFootnote.IsEndNote() )
448 return true;
450 return false;
453 /// Give a List of all footnotes and their beginning texts
454 size_t SwEditShell::GetSeqFootnoteList( SwSeqFieldList& rList, bool bEndNotes )
456 rList.Clear();
458 IDocumentRedlineAccess & rIDRA(mxDoc->getIDocumentRedlineAccess());
460 const size_t nFootnoteCnt = mxDoc->GetFootnoteIdxs().size();
461 SwTextFootnote* pTextFootnote;
462 for( size_t n = 0; n < nFootnoteCnt; ++n )
464 pTextFootnote = mxDoc->GetFootnoteIdxs()[ n ];
465 const SwFormatFootnote& rFootnote = pTextFootnote->GetFootnote();
466 if ( rFootnote.IsEndNote() != bEndNotes )
467 continue;
469 SwNodeIndex* pIdx = pTextFootnote->GetStartNode();
470 if( pIdx )
472 SwNodeIndex aIdx( *pIdx, 1 );
473 SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
474 if( !pTextNd )
475 pTextNd = static_cast<SwTextNode*>(mxDoc->GetNodes().GoNext( &aIdx ));
477 if( pTextNd )
479 if (GetLayout()->IsHideRedlines()
480 && sw::IsFootnoteDeleted(rIDRA, *pTextFootnote))
482 continue;
485 OUString sText(rFootnote.GetViewNumStr(*mxDoc, GetLayout()));
486 if( !sText.isEmpty() )
487 sText += " ";
488 sText += pTextNd->GetExpandText(GetLayout());
490 SeqFieldLstElem aNew( sText, pTextFootnote->GetSeqRefNo() );
491 while( rList.InsertSort( aNew ) )
492 aNew.sDlgEntry += " ";
497 return rList.Count();
500 /// Adjust left margin via object bar (similar to adjustment of numerations).
501 bool SwEditShell::IsMoveLeftMargin( bool bRight, bool bModulus ) const
503 bool bRet = true;
505 const SvxTabStopItem& rTabItem = GetDoc()->GetDefault( RES_PARATR_TABSTOP );
506 sal_uInt16 nDefDist = static_cast<sal_uInt16>(rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134);
507 if( !nDefDist )
508 return false;
510 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
512 sal_uLong nSttNd = rPaM.GetMark()->nNode.GetIndex(),
513 nEndNd = rPaM.GetPoint()->nNode.GetIndex();
515 if( nSttNd > nEndNd )
516 std::swap(nSttNd, nEndNd);
518 SwContentNode* pCNd;
519 for( sal_uLong n = nSttNd; bRet && n <= nEndNd; ++n )
521 pCNd = GetDoc()->GetNodes()[ n ]->GetTextNode();
522 if( nullptr != pCNd )
524 pCNd = sw::GetParaPropsNode(*GetLayout(), *pCNd);
525 const SvxLRSpaceItem& rLS = static_cast<const SvxLRSpaceItem&>(
526 pCNd->GetAttr( RES_LR_SPACE ));
527 if( bRight )
529 tools::Long nNext = rLS.GetTextLeft() + nDefDist;
530 if( bModulus )
531 nNext = ( nNext / nDefDist ) * nDefDist;
532 SwFrame* pFrame = pCNd->getLayoutFrame( GetLayout() );
533 if ( pFrame )
535 const sal_uInt16 nFrameWidth = static_cast<sal_uInt16>( pFrame->IsVertical() ?
536 pFrame->getFrameArea().Height() :
537 pFrame->getFrameArea().Width() );
538 bRet = nFrameWidth > ( nNext + MM50 );
540 else
541 bRet = false;
546 if( !bRet )
547 break;
550 return bRet;
553 void SwEditShell::MoveLeftMargin( bool bRight, bool bModulus )
555 StartAllAction();
556 StartUndo( SwUndoId::START );
558 SwPaM* pCursor = GetCursor();
559 if( pCursor->GetNext() != pCursor ) // Multiple selection ?
561 SwPamRanges aRangeArr( *pCursor );
562 SwPaM aPam( *pCursor->GetPoint() );
563 for( size_t n = 0; n < aRangeArr.Count(); ++n )
564 GetDoc()->MoveLeftMargin( aRangeArr.SetPam( n, aPam ),
565 bRight, bModulus, GetLayout() );
567 else
568 GetDoc()->MoveLeftMargin( *pCursor, bRight, bModulus, GetLayout() );
570 EndUndo( SwUndoId::END );
571 EndAllAction();
574 static SvtScriptType lcl_SetScriptFlags( sal_uInt16 nType )
576 switch( nType )
578 case css::i18n::ScriptType::LATIN:
579 return SvtScriptType::LATIN;
580 case css::i18n::ScriptType::ASIAN:
581 return SvtScriptType::ASIAN;
582 case css::i18n::ScriptType::COMPLEX:
583 return SvtScriptType::COMPLEX;
584 default:
585 return SvtScriptType::NONE;
589 static bool lcl_IsNoEndTextAttrAtPos(SwRootFrame const& rLayout,
590 const SwTextNode& rTNd, sal_Int32 const nPos,
591 SvtScriptType &rScrpt, bool bInSelection, bool bNum )
593 bool bRet = false;
594 OUString sExp;
596 // consider numbering
597 if ( bNum )
599 bRet = false;
600 SwTextNode const*const pPropsNode(sw::GetParaPropsNode(rLayout, rTNd));
601 if (pPropsNode->IsInList())
603 OSL_ENSURE( pPropsNode->GetNumRule(),
604 "<lcl_IsNoEndTextAttrAtPos(..)> - no list style found at text node. Serious defect." );
605 const SwNumRule* pNumRule = pPropsNode->GetNumRule();
606 if(pNumRule)
608 int nListLevel = pPropsNode->GetActualListLevel();
610 if (nListLevel < 0)
611 nListLevel = 0;
613 if (nListLevel >= MAXLEVEL)
614 nListLevel = MAXLEVEL - 1;
616 const SwNumFormat &rNumFormat = pNumRule->Get( static_cast<sal_uInt16>(nListLevel) );
617 if( SVX_NUM_BITMAP != rNumFormat.GetNumberingType() )
619 if ( SVX_NUM_CHAR_SPECIAL == rNumFormat.GetNumberingType() )
621 sal_UCS4 cBullet = rNumFormat.GetBulletChar();
622 sExp = OUString(&cBullet, 1);
624 else
625 sExp = pPropsNode->GetNumString(true, MAXLEVEL, &rLayout);
631 // and fields
632 if (nPos < rTNd.GetText().getLength() && CH_TXTATR_BREAKWORD == rTNd.GetText()[nPos])
634 const SwTextAttr* const pAttr = rTNd.GetTextAttrForCharAt( nPos );
635 if (pAttr)
637 bRet = true; // all other than fields can be
638 // defined as weak-script ?
639 if ( RES_TXTATR_FIELD == pAttr->Which() )
641 const SwField* const pField = pAttr->GetFormatField().GetField();
642 if (pField)
644 sExp += pField->ExpandField(true, &rLayout);
650 const sal_Int32 nEnd = sExp.getLength();
651 if ( nEnd )
653 if( bInSelection )
655 sal_uInt16 nScript;
656 for( sal_Int32 n = 0; n < nEnd;
657 n = g_pBreakIt->GetBreakIter()->endOfScript( sExp, n, nScript ))
659 nScript = g_pBreakIt->GetBreakIter()->getScriptType( sExp, n );
660 rScrpt |= lcl_SetScriptFlags( nScript );
663 else
664 rScrpt |= lcl_SetScriptFlags( g_pBreakIt->GetBreakIter()->
665 getScriptType( sExp, nEnd-1 ));
668 return bRet;
671 /// returns the script type of the selection
672 SvtScriptType SwEditShell::GetScriptType() const
674 SvtScriptType nRet = SvtScriptType::NONE;
677 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
679 const SwPosition *pStt = rPaM.Start(),
680 *pEnd = pStt == rPaM.GetMark()
681 ? rPaM.GetPoint()
682 : rPaM.GetMark();
683 if( pStt == pEnd || *pStt == *pEnd )
685 const SwTextNode* pTNd = pStt->nNode.GetNode().GetTextNode();
686 if( pTNd )
688 // try to get SwScriptInfo
689 SwTextFrame const* pFrame;
690 const SwScriptInfo *const pScriptInfo =
691 SwScriptInfo::GetScriptInfo(*pTNd, &pFrame);
693 sal_Int32 nPos = pStt->nContent.GetIndex();
694 //Task 90448: we need the scripttype of the previous
695 // position, if no selection exist!
696 if( nPos )
698 SwIndex aIdx( pStt->nContent );
699 if( pTNd->GoPrevious( &aIdx, CRSR_SKIP_CHARS ) )
700 nPos = aIdx.GetIndex();
703 sal_uInt16 nScript;
705 if (!pTNd->GetText().isEmpty())
707 nScript = pScriptInfo
708 ? pScriptInfo->ScriptType(pFrame->MapModelToView(pTNd, nPos))
709 : g_pBreakIt->GetBreakIter()->getScriptType( pTNd->GetText(), nPos );
711 else
712 nScript = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() );
714 if (!lcl_IsNoEndTextAttrAtPos(*GetLayout(), *pTNd, nPos, nRet, false, false))
715 nRet |= lcl_SetScriptFlags( nScript );
718 else
720 sal_uLong nEndIdx = pEnd->nNode.GetIndex();
721 SwNodeIndex aIdx( pStt->nNode );
722 for( ; aIdx.GetIndex() <= nEndIdx; ++aIdx )
723 if( aIdx.GetNode().IsTextNode() )
725 const SwTextNode* pTNd = aIdx.GetNode().GetTextNode();
726 const OUString& rText = pTNd->GetText();
728 // try to get SwScriptInfo
729 SwTextFrame const* pFrame;
730 const SwScriptInfo *const pScriptInfo =
731 SwScriptInfo::GetScriptInfo(*pTNd, &pFrame);
733 sal_Int32 nChg = aIdx == pStt->nNode
734 ? pStt->nContent.GetIndex()
735 : 0;
736 sal_Int32 nEndPos = aIdx == nEndIdx
737 ? pEnd->nContent.GetIndex()
738 : rText.getLength();
740 OSL_ENSURE( nEndPos <= rText.getLength(),
741 "Index outside the range - endless loop!" );
742 if (nEndPos > rText.getLength())
743 nEndPos = rText.getLength();
745 bool const isUntilEnd(pScriptInfo
746 ? pFrame->MapViewToModelPos(TextFrameIndex(pFrame->GetText().getLength())) <= *pEnd
747 : rText.getLength() == nEndPos);
748 sal_uInt16 nScript;
749 while( nChg < nEndPos )
751 TextFrameIndex iChg(pScriptInfo
752 ? pFrame->MapModelToView(pTNd, nChg)
753 : TextFrameIndex(-1/*invalid, do not use*/));
754 nScript = pScriptInfo ?
755 pScriptInfo->ScriptType( iChg ) :
756 g_pBreakIt->GetBreakIter()->getScriptType(
757 rText, nChg );
759 if (!lcl_IsNoEndTextAttrAtPos(*GetLayout(), *pTNd, nChg, nRet, true,
760 TextFrameIndex(0) == iChg && isUntilEnd))
762 nRet |= lcl_SetScriptFlags( nScript );
765 if( (SvtScriptType::LATIN | SvtScriptType::ASIAN |
766 SvtScriptType::COMPLEX) == nRet )
767 break;
769 sal_Int32 nFieldPos = nChg+1;
771 if (pScriptInfo)
773 iChg = pScriptInfo->NextScriptChg(iChg);
774 if (iChg == TextFrameIndex(COMPLETE_STRING))
776 nChg = pTNd->Len();
778 else
780 std::pair<SwTextNode*, sal_Int32> const tmp(
781 pFrame->MapViewToModel(iChg));
782 nChg = (tmp.first == pTNd)
783 ? tmp.second
784 : pTNd->Len();
787 else
789 nChg = g_pBreakIt->GetBreakIter()->endOfScript(
790 rText, nChg, nScript );
793 nFieldPos = rText.indexOf(
794 CH_TXTATR_BREAKWORD, nFieldPos);
795 if ((-1 != nFieldPos) && (nFieldPos < nChg))
796 nChg = nFieldPos;
798 if( (SvtScriptType::LATIN | SvtScriptType::ASIAN |
799 SvtScriptType::COMPLEX) == nRet )
800 break;
803 if( (SvtScriptType::LATIN | SvtScriptType::ASIAN |
804 SvtScriptType::COMPLEX) == nRet )
805 break;
809 if( nRet == SvtScriptType::NONE )
810 nRet = SvtLanguageOptions::GetScriptTypeOfLanguage( LANGUAGE_SYSTEM );
811 return nRet;
814 LanguageType SwEditShell::GetCurLang() const
816 const SwPaM* pCursor = GetCursor();
817 const SwPosition& rPos = *pCursor->GetPoint();
818 const SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode();
819 LanguageType nLang;
820 if( pTNd )
822 //JP 24.9.2001: if exist no selection, then get the language before
823 // the current character!
824 sal_Int32 nPos = rPos.nContent.GetIndex();
825 if( nPos && !pCursor->HasMark() )
826 --nPos;
827 nLang = pTNd->GetLang( nPos );
829 else
830 nLang = LANGUAGE_DONTKNOW;
831 return nLang;
834 sal_uInt16 SwEditShell::GetScalingOfSelectedText() const
836 const SwPaM* pCursor = GetCursor();
837 const SwPosition* pStt = pCursor->Start();
838 const SwTextNode* pTNd = pStt->nNode.GetNode().GetTextNode();
839 OSL_ENSURE( pTNd, "no textnode available" );
841 sal_uInt16 nScaleWidth;
842 if( pTNd )
844 SwTextFrame *const pFrame(static_cast<SwTextFrame *>(
845 pTNd->getLayoutFrame(GetLayout(), pStt)));
846 assert(pFrame); // shell cursor must be positioned in node with frame
847 TextFrameIndex const nStart(pFrame->MapModelToViewPos(*pStt));
848 TextFrameIndex const nEnd(
849 sw::FrameContainsNode(*pFrame, pCursor->End()->nNode.GetIndex())
850 ? pFrame->MapModelToViewPos(*pCursor->End())
851 : TextFrameIndex(pFrame->GetText().getLength()));
852 nScaleWidth = pFrame->GetScalingOfSelectedText(nStart, nEnd);
854 else
855 nScaleWidth = 100; // default are no scaling -> 100%
856 return nScaleWidth;
859 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */