1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <hintids.hxx>
22 #include <fmtinfmt.hxx>
26 #include <unocrsr.hxx>
27 #include <txatbase.hxx>
30 #include <acorrect.hxx>
31 #include <shellio.hxx>
34 #include <com/sun/star/i18n/BreakType.hpp>
35 #include <com/sun/star/i18n/WordType.hpp>
36 #include <com/sun/star/i18n/XBreakIterator.hpp>
37 #include <com/sun/star/linguistic2/XHyphenator.hpp>
38 #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
39 #include <svl/zforlist.hxx>
40 #include <svl/zformat.hxx>
42 #include <editeng/acorrcfg.hxx>
43 #include <redline.hxx>
44 #include <IDocumentRedlineAccess.hxx>
45 #include <rootfrm.hxx>
47 using namespace ::com::sun::star
;
51 class PaMIntoCursorShellRing
53 SwPaM
&m_rDelPam
, &m_rCursor
;
57 static void RemoveFromRing( SwPaM
& rPam
, SwPaM
const * pPrev
);
59 PaMIntoCursorShellRing( SwCursorShell
& rSh
, SwPaM
& rCursor
, SwPaM
& rPam
);
60 ~PaMIntoCursorShellRing();
65 PaMIntoCursorShellRing::PaMIntoCursorShellRing(SwCursorShell
& rCSh
, SwPaM
& rShCursor
, SwPaM
& rPam
)
67 , m_rCursor(rShCursor
)
69 SwPaM
* pShCursor
= rCSh
.GetCursor_();
71 m_pPrevDelPam
= m_rDelPam
.GetPrev();
72 m_pPrevCursor
= m_rCursor
.GetPrev();
74 m_rDelPam
.GetRingContainer().merge(pShCursor
->GetRingContainer());
75 m_rCursor
.GetRingContainer().merge(pShCursor
->GetRingContainer());
78 PaMIntoCursorShellRing::~PaMIntoCursorShellRing()
80 // and take out the Pam again:
81 RemoveFromRing(m_rDelPam
, m_pPrevDelPam
);
82 RemoveFromRing(m_rCursor
, m_pPrevCursor
);
85 void PaMIntoCursorShellRing::RemoveFromRing( SwPaM
& rPam
, SwPaM
const * pPrev
)
93 } while( p
!= pPrev
);
96 SwAutoCorrDoc::SwAutoCorrDoc( SwEditShell
& rEditShell
, SwPaM
& rPam
,
98 : m_rEditSh( rEditShell
), m_rCursor( rPam
)
99 , m_nEndUndoCounter(0)
100 , m_bUndoIdInitialized( cIns
== 0 )
104 SwAutoCorrDoc::~SwAutoCorrDoc()
106 for (int i
= 0; i
< m_nEndUndoCounter
; ++i
)
112 void SwAutoCorrDoc::DeleteSel( SwPaM
& rDelPam
)
114 // this should work with plain SwPaM as well because start and end
115 // are always in same node, but since there is GetRanges already...
116 std::vector
<std::shared_ptr
<SwUnoCursor
>> ranges
;
117 if (sw::GetRanges(ranges
, *m_rEditSh
.GetDoc(), rDelPam
))
119 DeleteSelImpl(rDelPam
);
123 for (auto const& pCursor
: ranges
)
125 DeleteSelImpl(*pCursor
);
130 void SwAutoCorrDoc::DeleteSelImpl(SwPaM
& rDelPam
)
132 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
133 if( pDoc
->IsAutoFormatRedline() )
135 // so that also the DelPam be moved, include it in the
136 // Shell-Cursr-Ring !!
137 // ??? is that really necessary - this should never join nodes, so Update should be enough?
138 // PaMIntoCursorShellRing aTmp( rEditSh, rCursor, rDelPam );
139 assert(rDelPam
.GetPoint()->nNode
== rDelPam
.GetMark()->nNode
);
140 pDoc
->getIDocumentContentOperations().DeleteAndJoin( rDelPam
);
144 pDoc
->getIDocumentContentOperations().DeleteRange( rDelPam
);
148 bool SwAutoCorrDoc::Delete( sal_Int32 nStt
, sal_Int32 nEnd
)
150 SwTextNode
const*const pTextNd
= m_rCursor
.GetNode().GetTextNode();
151 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
152 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
154 SwPaM
aSel(pFrame
->MapViewToModelPos(TextFrameIndex(nStt
)),
155 pFrame
->MapViewToModelPos(TextFrameIndex(nEnd
)));
158 if( m_bUndoIdInitialized
)
159 m_bUndoIdInitialized
= true;
163 bool SwAutoCorrDoc::Insert( sal_Int32 nPos
, const OUString
& rText
)
165 SwTextNode
const*const pTextNd
= m_rCursor
.GetNode().GetTextNode();
166 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
167 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
169 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(nPos
)));
170 m_rEditSh
.GetDoc()->getIDocumentContentOperations().InsertString( aPam
, rText
);
171 if( !m_bUndoIdInitialized
)
173 m_bUndoIdInitialized
= true;
174 if( 1 == rText
.getLength() )
176 m_rEditSh
.StartUndo( SwUndoId::AUTOCORRECT
);
183 bool SwAutoCorrDoc::Replace( sal_Int32 nPos
, const OUString
& rText
)
185 return ReplaceRange( nPos
, rText
.getLength(), rText
);
188 bool SwAutoCorrDoc::ReplaceRange( sal_Int32 nPos
, sal_Int32 nSourceLength
, const OUString
& rText
)
190 assert(nSourceLength
== 1); // sw_redlinehide: this is currently the case,
191 // and ensures that the replace range cannot *contain* delete redlines,
192 // so we don't need something along the lines of:
193 // if (sw::GetRanges(ranges, *rEditSh.GetDoc(), aPam))
196 // ReplaceImpl(ranges.begin())
197 // for (ranges.begin() + 1; ranges.end(); )
200 SwTextNode
* const pNd
= m_rCursor
.GetNode().GetTextNode();
206 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
207 pNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
209 std::pair
<SwTextNode
*, sal_Int32
> const pos(pFrame
->MapViewToModel(TextFrameIndex(nPos
)));
211 SwPaM
* pPam
= &m_rCursor
;
212 if (pPam
->GetPoint()->nNode
!= *pos
.first
213 || pPam
->GetPoint()->nContent
!= pos
.second
)
215 pPam
= new SwPaM(*pos
.first
, pos
.second
);
218 // text attributes with dummy characters must not be replaced!
219 bool bDoReplace
= true;
220 sal_Int32
const nLen
= rText
.getLength();
221 for (sal_Int32 n
= 0; n
< nLen
&& n
+ nPos
< pFrame
->GetText().getLength(); ++n
)
223 sal_Unicode
const Char
= pFrame
->GetText()[n
+ nPos
];
224 if (CH_TXTATR_BREAKWORD
== Char
|| CH_TXTATR_INWORD
== Char
)
226 assert(pFrame
->MapViewToModel(TextFrameIndex(n
+nPos
)).first
->GetTextAttrForCharAt(pFrame
->MapViewToModel(TextFrameIndex(n
+nPos
)).second
));
232 // tdf#83419 avoid bad autocorrect with visible redlines
233 // e.g. replacing the first letter of the tracked deletion
234 // with its capitalized (and not deleted) version.
235 if ( bDoReplace
&& !pFrame
->getRootFrame()->IsHideRedlines() &&
236 m_rEditSh
.GetDoc()->getIDocumentRedlineAccess().HasRedline( *pPam
, RedlineType::Delete
, /*bStartOrEndInRange=*/false ) )
243 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
245 if( pDoc
->IsAutoFormatRedline() )
247 if (nPos
== pFrame
->GetText().getLength()) // at the End do an Insert
249 pDoc
->getIDocumentContentOperations().InsertString( *pPam
, rText
);
253 assert(pos
.second
!= pos
.first
->Len()); // must be _before_ char
254 PaMIntoCursorShellRing
aTmp( m_rEditSh
, m_rCursor
, *pPam
);
257 pPam
->GetPoint()->nContent
= std::min
<sal_Int32
>(
258 pos
.first
->GetText().getLength(), pos
.second
+ nSourceLength
);
259 pDoc
->getIDocumentContentOperations().ReplaceRange( *pPam
, rText
, false );
267 pPam
->GetPoint()->nContent
= std::min
<sal_Int32
>(
268 pos
.first
->GetText().getLength(), pos
.second
+ nSourceLength
);
269 pDoc
->getIDocumentContentOperations().ReplaceRange( *pPam
, rText
, false );
274 if( m_bUndoIdInitialized
)
276 m_bUndoIdInitialized
= true;
277 if( 1 == rText
.getLength() )
279 m_rEditSh
.StartUndo( SwUndoId::AUTOCORRECT
);
285 if( pPam
!= &m_rCursor
)
291 void SwAutoCorrDoc::SetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, sal_uInt16 nSlotId
,
294 SwTextNode
const*const pTextNd
= m_rCursor
.GetNode().GetTextNode();
295 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
296 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
298 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(nStt
)),
299 pFrame
->MapViewToModelPos(TextFrameIndex(nEnd
)));
301 SfxItemPool
& rPool
= m_rEditSh
.GetDoc()->GetAttrPool();
302 sal_uInt16 nWhich
= rPool
.GetWhich( nSlotId
, false );
305 rItem
.SetWhich( nWhich
);
307 SfxItemSet
aSet( rPool
, aCharFormatSetRange
);
308 SetAllScriptItem( aSet
, rItem
);
310 m_rEditSh
.GetDoc()->SetFormatItemByAutoFormat( aPam
, aSet
);
312 if( m_bUndoIdInitialized
)
313 m_bUndoIdInitialized
= true;
317 bool SwAutoCorrDoc::SetINetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, const OUString
& rURL
)
319 SwTextNode
const*const pTextNd
= m_rCursor
.GetNode().GetTextNode();
320 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
321 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
323 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(nStt
)),
324 pFrame
->MapViewToModelPos(TextFrameIndex(nEnd
)));
326 SfxItemSet
aSet( m_rEditSh
.GetDoc()->GetAttrPool(),
327 svl::Items
<RES_TXTATR_INETFMT
, RES_TXTATR_INETFMT
>{} );
328 aSet
.Put( SwFormatINetFormat( rURL
, OUString() ));
329 m_rEditSh
.GetDoc()->SetFormatItemByAutoFormat( aPam
, aSet
);
330 if( m_bUndoIdInitialized
)
331 m_bUndoIdInitialized
= true;
335 /** Return the text of a previous paragraph
337 * @param bAtNormalPos If <true> before the normal insert position; if <false> in which the
338 * corrected word was inserted. (Doesn't need to be the same paragraph!)
339 * @return text or 0, if previous paragraph does not exists or there are only blankness
341 OUString
const* SwAutoCorrDoc::GetPrevPara(bool const bAtNormalPos
)
343 OUString
const* pStr(nullptr);
345 if( bAtNormalPos
|| !m_pIndex
)
347 m_pIndex
.reset(new SwNodeIndex(m_rCursor
.GetPoint()->nNode
));
349 sw::GotoPrevLayoutTextFrame(*m_pIndex
, m_rEditSh
.GetLayout());
351 SwTextFrame
const* pFrame(nullptr);
352 for (SwTextNode
* pTextNd
= m_pIndex
->GetNode().GetTextNode();
353 pTextNd
; pTextNd
= m_pIndex
->GetNode().GetTextNode())
355 pFrame
= static_cast<SwTextFrame
const*>(
356 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout()));
357 if (pFrame
&& !pFrame
->GetText().isEmpty())
361 sw::GotoPrevLayoutTextFrame(*m_pIndex
, m_rEditSh
.GetLayout());
363 if (pFrame
&& 0 == pFrame
->GetTextNodeForParaProps()->GetAttrOutlineLevel())
364 pStr
= & pFrame
->GetText();
366 if( m_bUndoIdInitialized
)
367 m_bUndoIdInitialized
= true;
372 bool SwAutoCorrDoc::ChgAutoCorrWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
,
373 SvxAutoCorrect
& rACorrect
,
376 if( m_bUndoIdInitialized
)
377 m_bUndoIdInitialized
= true;
379 // Found a beginning of a paragraph or a Blank,
380 // search for the word Kuerzel (Shortcut) in the Auto
381 SwTextNode
* pTextNd
= m_rCursor
.GetNode().GetTextNode();
382 OSL_ENSURE( pTextNd
, "where is the TextNode?" );
385 if( nEndPos
== rSttPos
)
388 LanguageType eLang
= GetLanguage(nEndPos
);
389 if(LANGUAGE_SYSTEM
== eLang
)
390 eLang
= GetAppLanguage();
391 LanguageTag
aLanguageTag( eLang
);
393 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
394 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
397 const OUString sFrameText
= pFrame
->GetText();
398 const SvxAutocorrWord
* pFnd
= rACorrect
.SearchWordsInList(
399 sFrameText
, rSttPos
, nEndPos
, *this, aLanguageTag
);
400 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
403 // replace also last colon of keywords surrounded by colons (for example, ":name:")
404 const bool replaceLastChar
= sFrameText
.getLength() > nEndPos
&& pFnd
->GetShort()[0] == ':'
405 && pFnd
->GetShort().endsWith(":");
407 SwPosition
aStartPos( pFrame
->MapViewToModelPos(TextFrameIndex(rSttPos
) ));
408 SwPosition
aEndPos( pFrame
->MapViewToModelPos(TextFrameIndex(nEndPos
+ (replaceLastChar
? 1 : 0))) );
409 SwPaM
aPam(aStartPos
, aEndPos
);
411 // don't replace, if a redline starts or ends within the original text
412 if ( pDoc
->getIDocumentRedlineAccess().HasRedline( aPam
, RedlineType::Any
, /*bStartOrEndInRange=*/true ) )
417 if( pFnd
->IsTextOnly() )
419 //JP 22.04.99: Bug 63883 - Special treatment for dots.
420 const bool bLastCharIsPoint
421 = nEndPos
< sFrameText
.getLength() && ('.' == sFrameText
[nEndPos
]);
422 if( !bLastCharIsPoint
|| pFnd
->GetLong().isEmpty() ||
423 '.' != pFnd
->GetLong()[ pFnd
->GetLong().getLength() - 1 ] )
425 // replace the selection
426 std::vector
<std::shared_ptr
<SwUnoCursor
>> ranges
;
427 if (sw::GetRanges(ranges
, *m_rEditSh
.GetDoc(), aPam
))
429 pDoc
->getIDocumentContentOperations().ReplaceRange(aPam
, pFnd
->GetLong(), false);
432 else if (!ranges
.empty())
434 assert(ranges
.front()->GetPoint()->nNode
== ranges
.front()->GetMark()->nNode
);
435 pDoc
->getIDocumentContentOperations().ReplaceRange(
436 *ranges
.front(), pFnd
->GetLong(), false);
437 for (auto it
= ranges
.begin() + 1; it
!= ranges
.end(); ++it
)
444 // tdf#83260 After calling sw::DocumentContentOperationsManager::ReplaceRange
445 // pTextNd may become invalid when change tracking is on and Edit -> Track Changes -> Show == OFF.
446 // ReplaceRange shows changes, this moves deleted nodes from special section to document.
447 // Then Show mode is disabled again. As a result pTextNd may be invalidated.
448 pTextNd
= m_rCursor
.GetNode().GetTextNode();
453 SwTextBlocks
aTBlks( rACorrect
.GetAutoCorrFileName( aLanguageTag
, false, true ));
454 sal_uInt16 nPos
= aTBlks
.GetIndex( pFnd
->GetShort() );
455 if( USHRT_MAX
!= nPos
&& aTBlks
.BeginGetDoc( nPos
) )
458 pDoc
->DontExpandFormat( *aPam
.GetPoint() );
462 OSL_ENSURE( !m_pIndex
, "who has not deleted his Index?" );
463 m_pIndex
.reset(new SwNodeIndex( m_rCursor
.GetPoint()->nNode
));
464 sw::GotoPrevLayoutTextFrame(*m_pIndex
, m_rEditSh
.GetLayout());
467 SwDoc
* pAutoDoc
= aTBlks
.GetDoc();
468 SwNodeIndex
aSttIdx( pAutoDoc
->GetNodes().GetEndOfExtras(), 1 );
469 SwContentNode
* pContentNd
= pAutoDoc
->GetNodes().GoNext( &aSttIdx
);
470 SwPaM
aCpyPam( aSttIdx
);
472 const SwTableNode
* pTableNd
= pContentNd
->FindTableNode();
475 aCpyPam
.GetPoint()->nContent
.Assign( nullptr, 0 );
476 aCpyPam
.GetPoint()->nNode
= *pTableNd
;
480 // then until the end of the Nodes Array
481 aCpyPam
.GetPoint()->nNode
.Assign( pAutoDoc
->GetNodes().GetEndOfContent(), -1 );
482 pContentNd
= aCpyPam
.GetContentNode();
483 aCpyPam
.GetPoint()->nContent
.Assign(
484 pContentNd
, pContentNd
? pContentNd
->Len() : 0);
486 SwDontExpandItem aExpItem
;
487 aExpItem
.SaveDontExpandItems( *aPam
.GetPoint() );
489 pAutoDoc
->getIDocumentContentOperations().CopyRange(aCpyPam
, *aPam
.GetPoint(), SwCopyFlags::CheckPosInFly
);
491 aExpItem
.RestoreDontExpandItems( *aPam
.GetPoint() );
495 sw::GotoNextLayoutTextFrame(*m_pIndex
, m_rEditSh
.GetLayout());
496 pTextNd
= m_pIndex
->GetNode().GetTextNode();
504 if( bRet
&& pPara
&& pTextNd
)
506 SwTextFrame
const*const pNewFrame(static_cast<SwTextFrame
const*>(
507 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
508 *pPara
= pNewFrame
->GetText();
514 bool SwAutoCorrDoc::TransliterateRTLWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
)
516 if( m_bUndoIdInitialized
)
517 m_bUndoIdInitialized
= true;
519 SwTextNode
* pTextNd
= m_rCursor
.GetNode().GetTextNode();
520 OSL_ENSURE( pTextNd
, "where is the TextNode?" );
523 if( nEndPos
== rSttPos
)
526 LanguageType eLang
= GetLanguage(nEndPos
);
527 if(LANGUAGE_SYSTEM
== eLang
)
528 eLang
= GetAppLanguage();
529 LanguageTag
aLanguageTag(eLang
);
531 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
532 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
535 const OUString sFrameText
= pFrame
->GetText();
536 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
537 if ( pFrame
->IsRightToLeft() )
539 // transliterate to Old Hungarian using Numbertext via NatNum12 number format modifier
540 OUString
sWord(sFrameText
.copy(rSttPos
, nEndPos
- rSttPos
));
541 // Consonant disambiguation using hyphenation
542 uno::Reference
< linguistic2::XHyphenator
> xHyph
;
543 xHyph
= ::GetHyphenator();
544 OUStringBuffer sDisambiguatedWord
;
546 const ::css::uno::Sequence
< ::css::beans::PropertyValue
> aProperties
;
547 css::uno::Reference
< css::linguistic2::XHyphenatedWord
> xHyphWord
;
548 for (int i
= 0; i
+1 < sWord
.getLength(); i
++ )
550 xHyphWord
= xHyph
->hyphenate( sWord
,
551 aLanguageTag
.getLocale(),
554 // insert ZWSP at a hyphenation point, if it's not an alternative one (i.e. ssz->sz-sz)
555 if (xHyphWord
.is() && xHyphWord
->getHyphenationPos()+1 == i
&& !xHyphWord
->isAlternativeSpelling())
557 sDisambiguatedWord
.append(CHAR_ZWSP
);
559 sDisambiguatedWord
.append(sWord
[i
]);
561 sDisambiguatedWord
.append(sWord
[sWord
.getLength()-1]);
563 SvNumberFormatter
* pFormatter
= pDoc
->GetNumberFormatter();
565 if (pFormatter
&& !sWord
.isEmpty())
567 const Color
* pColor
= nullptr;
568 // Send text as NatNum12 prefix
569 OUString
sPrefix("[NatNum12 " + sDisambiguatedWord
.makeStringAndClear() + "]0");
570 if (pFormatter
->GetPreviewString(sPrefix
, 0, sConverted
, &pColor
, LANGUAGE_USER_HUNGARIAN_ROVAS
))
574 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(rSttPos
)),
575 pFrame
->MapViewToModelPos(TextFrameIndex(nEndPos
)));
576 if (bRet
&& nEndPos
<= sFrameText
.getLength())
577 pDoc
->getIDocumentContentOperations().ReplaceRange(aPam
, sConverted
, false);
583 // Called by the functions:
584 // - FnCapitalStartWord
585 // - FnCapitalStartSentence
586 // after the exchange of characters. Then the words, if necessary, can be inserted
587 // into the exception list.
588 void SwAutoCorrDoc::SaveCpltSttWord( ACFlags nFlag
, sal_Int32 nPos
,
589 const OUString
& rExceptWord
,
592 sal_uLong nNode
= m_pIndex
? m_pIndex
->GetIndex() : m_rCursor
.GetPoint()->nNode
.GetIndex();
593 LanguageType eLang
= GetLanguage(nPos
);
594 m_rEditSh
.GetDoc()->SetAutoCorrExceptWord( std::make_unique
<SwAutoCorrExceptWord
>( nFlag
,
595 nNode
, nPos
, rExceptWord
, cChar
, eLang
));
598 LanguageType
SwAutoCorrDoc::GetLanguage( sal_Int32 nPos
) const
600 LanguageType eRet
= LANGUAGE_SYSTEM
;
602 SwTextNode
* pNd
= m_rCursor
.GetPoint()->nNode
.GetNode().GetTextNode();
606 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
607 pNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
609 eRet
= pFrame
->GetLangOfChar(TextFrameIndex(nPos
), 0, true);
611 if(LANGUAGE_SYSTEM
== eRet
)
612 eRet
= GetAppLanguage();
616 void SwAutoCorrExceptWord::CheckChar( const SwPosition
& rPos
, sal_Unicode cChr
)
618 // test only if this is an improvement.
619 // If yes, then add the word to the list.
620 if (m_cChar
== cChr
&& rPos
.nNode
.GetIndex() == m_nNode
&& rPos
.nContent
.GetIndex() == m_nContent
)
622 // get the current autocorrection:
623 SvxAutoCorrect
* pACorr
= SvxAutoCorrCfg::Get().GetAutoCorrect();
625 // then add to the list:
626 if (ACFlags::CapitalStartWord
& m_nFlags
)
627 pACorr
->AddWrtSttException(m_sWord
, m_eLanguage
);
628 else if (ACFlags::CapitalStartSentence
& m_nFlags
)
629 pACorr
->AddCplSttException(m_sWord
, m_eLanguage
);
633 bool SwAutoCorrExceptWord::CheckDelChar( const SwPosition
& rPos
)
636 if (!m_bDeleted
&& rPos
.nNode
.GetIndex() == m_nNode
&& rPos
.nContent
.GetIndex() == m_nContent
)
637 m_bDeleted
= bRet
= true;
641 SwDontExpandItem::~SwDontExpandItem()
645 void SwDontExpandItem::SaveDontExpandItems( const SwPosition
& rPos
)
647 const SwTextNode
* pTextNd
= rPos
.nNode
.GetNode().GetTextNode();
650 m_pDontExpandItems
.reset( new SfxItemSet( const_cast<SwDoc
&>(pTextNd
->GetDoc()).GetAttrPool(),
651 aCharFormatSetRange
) );
652 const sal_Int32 n
= rPos
.nContent
.GetIndex();
653 if (!pTextNd
->GetParaAttr( *m_pDontExpandItems
, n
, n
,
654 n
!= pTextNd
->GetText().getLength() ))
656 m_pDontExpandItems
.reset();
661 void SwDontExpandItem::RestoreDontExpandItems( const SwPosition
& rPos
)
663 SwTextNode
* pTextNd
= rPos
.nNode
.GetNode().GetTextNode();
667 const sal_Int32 nStart
= rPos
.nContent
.GetIndex();
668 if( nStart
== pTextNd
->GetText().getLength() )
669 pTextNd
->FormatToTextAttr( pTextNd
);
671 if( !(pTextNd
->GetpSwpHints() && pTextNd
->GetpSwpHints()->Count()) )
674 const size_t nSize
= pTextNd
->GetpSwpHints()->Count();
675 sal_Int32 nAttrStart
;
677 for( size_t n
= 0; n
< nSize
; ++n
)
679 SwTextAttr
* pHt
= pTextNd
->GetpSwpHints()->Get( n
);
680 nAttrStart
= pHt
->GetStart();
681 if( nAttrStart
> nStart
) // beyond the area
684 const sal_Int32
* pAttrEnd
;
685 if( nullptr != ( pAttrEnd
= pHt
->End() ) &&
686 ( ( nAttrStart
< nStart
&&
687 ( pHt
->DontExpand() ? nStart
< *pAttrEnd
688 : nStart
<= *pAttrEnd
)) ||
689 ( nStart
== nAttrStart
&&
690 ( nAttrStart
== *pAttrEnd
|| !nStart
))) )
692 const SfxPoolItem
* pItem
;
693 if( !m_pDontExpandItems
|| SfxItemState::SET
!= m_pDontExpandItems
->
694 GetItemState( pHt
->Which(), false, &pItem
) ||
695 *pItem
!= pHt
->GetAttr() )
697 // The attribute was not previously set in this form in the
698 // paragraph, so it can only be created through insert/copy
699 // Because of that it is a candidate for DontExpand
700 pHt
->SetDontExpand( true );
706 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */