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/linguistic2/XHyphenator.hpp>
35 #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
36 #include <osl/diagnose.h>
37 #include <svl/numformat.hxx>
39 #include <editeng/acorrcfg.hxx>
40 #include <IDocumentRedlineAccess.hxx>
41 #include <rootfrm.hxx>
43 using namespace ::com::sun::star
;
47 class PaMIntoCursorShellRing
49 SwPaM
&m_rDelPam
, &m_rCursor
;
53 static void RemoveFromRing( SwPaM
& rPam
, SwPaM
const * pPrev
);
55 PaMIntoCursorShellRing( SwCursorShell
& rSh
, SwPaM
& rCursor
, SwPaM
& rPam
);
56 ~PaMIntoCursorShellRing();
61 PaMIntoCursorShellRing::PaMIntoCursorShellRing(SwCursorShell
& rCSh
, SwPaM
& rShCursor
, SwPaM
& rPam
)
63 , m_rCursor(rShCursor
)
65 SwPaM
* pShCursor
= rCSh
.GetCursor_();
67 m_pPrevDelPam
= m_rDelPam
.GetPrev();
68 m_pPrevCursor
= m_rCursor
.GetPrev();
70 m_rDelPam
.GetRingContainer().merge(pShCursor
->GetRingContainer());
71 m_rCursor
.GetRingContainer().merge(pShCursor
->GetRingContainer());
74 PaMIntoCursorShellRing::~PaMIntoCursorShellRing()
76 // and take out the Pam again:
77 RemoveFromRing(m_rDelPam
, m_pPrevDelPam
);
78 RemoveFromRing(m_rCursor
, m_pPrevCursor
);
81 void PaMIntoCursorShellRing::RemoveFromRing( SwPaM
& rPam
, SwPaM
const * pPrev
)
89 } while( p
!= pPrev
);
92 SwAutoCorrDoc::SwAutoCorrDoc( SwEditShell
& rEditShell
, SwPaM
& rPam
,
94 : m_rEditSh( rEditShell
), m_rCursor( rPam
)
95 , m_nEndUndoCounter(0)
96 , m_bUndoIdInitialized( cIns
== 0 )
100 SwAutoCorrDoc::~SwAutoCorrDoc()
102 for (int i
= 0; i
< m_nEndUndoCounter
; ++i
)
108 void SwAutoCorrDoc::DeleteSel( SwPaM
& rDelPam
)
110 // this should work with plain SwPaM as well because start and end
111 // are always in same node, but since there is GetRanges already...
112 std::vector
<std::shared_ptr
<SwUnoCursor
>> ranges
;
113 if (sw::GetRanges(ranges
, *m_rEditSh
.GetDoc(), rDelPam
))
115 DeleteSelImpl(rDelPam
);
119 for (auto const& pCursor
: ranges
)
121 DeleteSelImpl(*pCursor
);
126 void SwAutoCorrDoc::DeleteSelImpl(SwPaM
& rDelPam
)
128 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
129 if( pDoc
->IsAutoFormatRedline() )
131 // so that also the DelPam be moved, include it in the
132 // Shell-Cursr-Ring !!
133 // ??? is that really necessary - this should never join nodes, so Update should be enough?
134 // PaMIntoCursorShellRing aTmp( rEditSh, rCursor, rDelPam );
135 assert(rDelPam
.GetPoint()->GetNode() == rDelPam
.GetMark()->GetNode());
136 pDoc
->getIDocumentContentOperations().DeleteAndJoin( rDelPam
);
140 pDoc
->getIDocumentContentOperations().DeleteRange( rDelPam
);
144 bool SwAutoCorrDoc::Delete( sal_Int32 nStt
, sal_Int32 nEnd
)
146 SwTextNode
const*const pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
147 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
148 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
150 SwPaM
aSel(pFrame
->MapViewToModelPos(TextFrameIndex(nStt
)),
151 pFrame
->MapViewToModelPos(TextFrameIndex(nEnd
)));
154 if( m_bUndoIdInitialized
)
155 m_bUndoIdInitialized
= true;
159 bool SwAutoCorrDoc::Insert( sal_Int32 nPos
, const OUString
& rText
)
161 SwTextNode
const*const pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
162 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
163 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
165 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(nPos
)));
166 m_rEditSh
.GetDoc()->getIDocumentContentOperations().InsertString( aPam
, rText
);
167 if( !m_bUndoIdInitialized
)
169 m_bUndoIdInitialized
= true;
170 if( 1 == rText
.getLength() )
172 m_rEditSh
.StartUndo( SwUndoId::AUTOCORRECT
);
179 bool SwAutoCorrDoc::Replace( sal_Int32 nPos
, const OUString
& rText
)
181 return ReplaceRange( nPos
, rText
.getLength(), rText
);
184 bool SwAutoCorrDoc::ReplaceRange( sal_Int32 nPos
, sal_Int32 nSourceLength
, const OUString
& rText
)
186 assert(nSourceLength
== 1); // sw_redlinehide: this is currently the case,
187 // and ensures that the replace range cannot *contain* delete redlines,
188 // so we don't need something along the lines of:
189 // if (sw::GetRanges(ranges, *rEditSh.GetDoc(), aPam))
192 // ReplaceImpl(ranges.begin())
193 // for (ranges.begin() + 1; ranges.end(); )
196 SwTextNode
* const pNd
= m_rCursor
.GetPointNode().GetTextNode();
202 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
203 pNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
205 std::pair
<SwTextNode
*, sal_Int32
> const pos(pFrame
->MapViewToModel(TextFrameIndex(nPos
)));
207 SwPaM
* pPam
= &m_rCursor
;
208 if (pPam
->GetPoint()->GetNode() != *pos
.first
209 || pPam
->GetPoint()->GetContentIndex() != pos
.second
)
211 pPam
= new SwPaM(*pos
.first
, pos
.second
);
214 // text attributes with dummy characters must not be replaced!
215 bool bDoReplace
= true;
216 sal_Int32
const nLen
= rText
.getLength();
217 for (sal_Int32 n
= 0; n
< nLen
&& n
+ nPos
< pFrame
->GetText().getLength(); ++n
)
219 sal_Unicode
const Char
= pFrame
->GetText()[n
+ nPos
];
220 if (CH_TXTATR_BREAKWORD
== Char
|| CH_TXTATR_INWORD
== Char
)
222 assert(pFrame
->MapViewToModel(TextFrameIndex(n
+nPos
)).first
->GetTextAttrForCharAt(pFrame
->MapViewToModel(TextFrameIndex(n
+nPos
)).second
));
228 // tdf#83419 avoid bad autocorrect with visible redlines
229 // e.g. replacing the first letter of the tracked deletion
230 // with its capitalized (and not deleted) version.
231 if ( bDoReplace
&& !pFrame
->getRootFrame()->IsHideRedlines() &&
232 m_rEditSh
.GetDoc()->getIDocumentRedlineAccess().HasRedline( *pPam
, RedlineType::Delete
, /*bStartOrEndInRange=*/false ) )
239 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
241 if( pDoc
->IsAutoFormatRedline() )
243 if (nPos
== pFrame
->GetText().getLength()) // at the End do an Insert
245 pDoc
->getIDocumentContentOperations().InsertString( *pPam
, rText
);
249 assert(pos
.second
!= pos
.first
->Len()); // must be _before_ char
250 PaMIntoCursorShellRing
aTmp( m_rEditSh
, m_rCursor
, *pPam
);
253 pPam
->GetPoint()->SetContent( std::min
<sal_Int32
>(
254 pos
.first
->GetText().getLength(), pos
.second
+ nSourceLength
) );
255 pDoc
->getIDocumentContentOperations().ReplaceRange( *pPam
, rText
, false );
263 pPam
->GetPoint()->SetContent( std::min
<sal_Int32
>(
264 pos
.first
->GetText().getLength(), pos
.second
+ nSourceLength
) );
265 pDoc
->getIDocumentContentOperations().ReplaceRange( *pPam
, rText
, false );
270 if( m_bUndoIdInitialized
)
272 m_bUndoIdInitialized
= true;
273 if( 1 == rText
.getLength() )
275 m_rEditSh
.StartUndo( SwUndoId::AUTOCORRECT
);
281 if( pPam
!= &m_rCursor
)
287 void SwAutoCorrDoc::SetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, sal_uInt16 nSlotId
,
290 SwTextNode
const*const pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
291 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
292 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
294 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(nStt
)),
295 pFrame
->MapViewToModelPos(TextFrameIndex(nEnd
)));
297 SfxItemPool
& rPool
= m_rEditSh
.GetDoc()->GetAttrPool();
298 sal_uInt16 nWhich
= rPool
.GetWhich( nSlotId
, false );
301 rItem
.SetWhich( nWhich
);
303 SfxItemSet
aSet( rPool
, aCharFormatSetRange
);
304 SetAllScriptItem( aSet
, rItem
);
306 m_rEditSh
.GetDoc()->SetFormatItemByAutoFormat( aPam
, aSet
);
308 if( m_bUndoIdInitialized
)
309 m_bUndoIdInitialized
= true;
313 bool SwAutoCorrDoc::SetINetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, const OUString
& rURL
)
315 SwTextNode
const*const pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
316 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
317 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
319 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(nStt
)),
320 pFrame
->MapViewToModelPos(TextFrameIndex(nEnd
)));
322 SfxItemSetFixed
<RES_TXTATR_INETFMT
, RES_TXTATR_INETFMT
>
323 aSet( m_rEditSh
.GetDoc()->GetAttrPool() );
324 aSet
.Put( SwFormatINetFormat( rURL
, OUString() ));
325 m_rEditSh
.GetDoc()->SetFormatItemByAutoFormat( aPam
, aSet
);
326 if( m_bUndoIdInitialized
)
327 m_bUndoIdInitialized
= true;
331 /** Return the text of a previous paragraph
333 * @param bAtNormalPos If <true> before the normal insert position; if <false> in which the
334 * corrected word was inserted. (Doesn't need to be the same paragraph!)
335 * @return text or 0, if previous paragraph does not exists or there are only blankness
337 OUString
const* SwAutoCorrDoc::GetPrevPara(bool const bAtNormalPos
)
339 OUString
const* pStr(nullptr);
341 if( bAtNormalPos
|| !m_oIndex
)
343 m_oIndex
.emplace(m_rCursor
.GetPoint()->GetNode());
345 sw::GotoPrevLayoutTextFrame(*m_oIndex
, m_rEditSh
.GetLayout());
347 SwTextFrame
const* pFrame(nullptr);
348 for (SwTextNode
* pTextNd
= m_oIndex
->GetNode().GetTextNode();
349 pTextNd
; pTextNd
= m_oIndex
->GetNode().GetTextNode())
351 pFrame
= static_cast<SwTextFrame
const*>(
352 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout()));
353 if (pFrame
&& !pFrame
->GetText().isEmpty())
357 sw::GotoPrevLayoutTextFrame(*m_oIndex
, m_rEditSh
.GetLayout());
359 if (pFrame
&& !pFrame
->GetText().isEmpty() &&
360 0 == pFrame
->GetTextNodeForParaProps()->GetAttrOutlineLevel())
362 pStr
= & pFrame
->GetText();
365 if( m_bUndoIdInitialized
)
366 m_bUndoIdInitialized
= true;
371 bool SwAutoCorrDoc::ChgAutoCorrWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
,
372 SvxAutoCorrect
& rACorrect
,
375 if( m_bUndoIdInitialized
)
376 m_bUndoIdInitialized
= true;
378 // Found a beginning of a paragraph or a Blank,
379 // search for the word Kuerzel (Shortcut) in the Auto
380 SwTextNode
* pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
381 OSL_ENSURE( pTextNd
, "where is the TextNode?" );
384 if( nEndPos
== rSttPos
)
387 LanguageType eLang
= GetLanguage(nEndPos
);
388 if(LANGUAGE_SYSTEM
== eLang
)
389 eLang
= GetAppLanguage();
390 LanguageTag
aLanguageTag( eLang
);
392 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
393 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
396 const OUString sFrameText
= pFrame
->GetText();
397 const SvxAutocorrWord
* pFnd
= rACorrect
.SearchWordsInList(
398 sFrameText
, rSttPos
, nEndPos
, *this, aLanguageTag
);
399 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
402 // replace also last colon of keywords surrounded by colons (for example, ":name:")
403 const bool replaceLastChar
= sFrameText
.getLength() > nEndPos
&& pFnd
->GetShort()[0] == ':'
404 && pFnd
->GetShort().endsWith(":");
406 SwPosition
aStartPos( pFrame
->MapViewToModelPos(TextFrameIndex(rSttPos
) ));
407 SwPosition
aEndPos( pFrame
->MapViewToModelPos(TextFrameIndex(nEndPos
+ (replaceLastChar
? 1 : 0))) );
408 SwPaM
aPam(aStartPos
, aEndPos
);
410 // don't replace, if a redline starts or ends within the original text
411 if ( pDoc
->getIDocumentRedlineAccess().HasRedline( aPam
, RedlineType::Any
, /*bStartOrEndInRange=*/true ) )
416 if( pFnd
->IsTextOnly() )
418 //JP 22.04.99: Bug 63883 - Special treatment for dots.
419 const bool bLastCharIsPoint
420 = nEndPos
< sFrameText
.getLength() && ('.' == sFrameText
[nEndPos
]);
421 if( !bLastCharIsPoint
|| pFnd
->GetLong().isEmpty() ||
422 '.' != pFnd
->GetLong()[ pFnd
->GetLong().getLength() - 1 ] )
424 // replace the selection
425 std::vector
<std::shared_ptr
<SwUnoCursor
>> ranges
;
426 if (sw::GetRanges(ranges
, *m_rEditSh
.GetDoc(), aPam
))
428 pDoc
->getIDocumentContentOperations().ReplaceRange(aPam
, pFnd
->GetLong(), false);
431 else if (!ranges
.empty())
433 assert(ranges
.front()->GetPoint()->GetNode() == ranges
.front()->GetMark()->GetNode());
434 pDoc
->getIDocumentContentOperations().ReplaceRange(
435 *ranges
.front(), pFnd
->GetLong(), false);
436 for (auto it
= ranges
.begin() + 1; it
!= ranges
.end(); ++it
)
443 // tdf#83260 After calling sw::DocumentContentOperationsManager::ReplaceRange
444 // pTextNd may become invalid when change tracking is on and Edit -> Track Changes -> Show == OFF.
445 // ReplaceRange shows changes, this moves deleted nodes from special section to document.
446 // Then Show mode is disabled again. As a result pTextNd may be invalidated.
447 pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
452 SwTextBlocks
aTBlks( rACorrect
.GetAutoCorrFileName( aLanguageTag
, false, true ));
453 sal_uInt16 nPos
= aTBlks
.GetIndex( pFnd
->GetShort() );
454 if( USHRT_MAX
!= nPos
&& aTBlks
.BeginGetDoc( nPos
) )
457 pDoc
->DontExpandFormat( *aPam
.GetPoint() );
461 OSL_ENSURE( !m_oIndex
, "who has not deleted his Index?" );
462 m_oIndex
.emplace(m_rCursor
.GetPoint()->GetNode());
463 sw::GotoPrevLayoutTextFrame(*m_oIndex
, m_rEditSh
.GetLayout());
466 SwDoc
* pAutoDoc
= aTBlks
.GetDoc();
467 SwNodeIndex
aSttIdx( pAutoDoc
->GetNodes().GetEndOfExtras(), 1 );
468 SwContentNode
* pContentNd
= pAutoDoc
->GetNodes().GoNext( &aSttIdx
);
469 SwPaM
aCpyPam( aSttIdx
);
471 const SwTableNode
* pTableNd
= pContentNd
->FindTableNode();
474 aCpyPam
.GetPoint()->Assign( *pTableNd
);
478 // then until the end of the Nodes Array
479 aCpyPam
.GetPoint()->Assign( pAutoDoc
->GetNodes().GetEndOfContent(), SwNodeOffset(-1) );
480 pContentNd
= aCpyPam
.GetPointContentNode();
482 aCpyPam
.GetPoint()->SetContent( pContentNd
->Len() );
484 SwDontExpandItem aExpItem
;
485 aExpItem
.SaveDontExpandItems( *aPam
.GetPoint() );
487 pAutoDoc
->getIDocumentContentOperations().CopyRange(aCpyPam
, *aPam
.GetPoint(), SwCopyFlags::CheckPosInFly
);
489 aExpItem
.RestoreDontExpandItems( *aPam
.GetPoint() );
493 sw::GotoNextLayoutTextFrame(*m_oIndex
, m_rEditSh
.GetLayout());
494 pTextNd
= m_oIndex
->GetNode().GetTextNode();
502 if( bRet
&& pPara
&& pTextNd
)
504 SwTextFrame
const*const pNewFrame(static_cast<SwTextFrame
const*>(
505 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
506 *pPara
= pNewFrame
->GetText();
512 bool SwAutoCorrDoc::TransliterateRTLWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
, bool bApply
)
514 if( m_bUndoIdInitialized
)
515 m_bUndoIdInitialized
= true;
517 SwTextNode
* pTextNd
= m_rCursor
.GetPointNode().GetTextNode();
518 OSL_ENSURE( pTextNd
, "where is the TextNode?" );
521 if( nEndPos
== rSttPos
)
524 LanguageType eLang
= GetLanguage(nEndPos
);
525 if(LANGUAGE_SYSTEM
== eLang
)
526 eLang
= GetAppLanguage();
527 LanguageTag
aLanguageTag(eLang
);
529 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
530 pTextNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
533 const OUString sFrameText
= pFrame
->GetText();
534 SwDoc
* pDoc
= m_rEditSh
.GetDoc();
535 if ( pFrame
->IsRightToLeft() || bApply
)
537 // transliterate to Old Hungarian using Numbertext via NatNum12 number format modifier
538 OUString
sWord(sFrameText
.copy(rSttPos
, nEndPos
- rSttPos
));
539 // Consonant disambiguation using hyphenation
540 uno::Reference
< linguistic2::XHyphenator
> xHyph
;
541 xHyph
= ::GetHyphenator();
542 OUStringBuffer sDisambiguatedWord
;
544 const ::css::uno::Sequence
< ::css::beans::PropertyValue
> aProperties
;
545 css::uno::Reference
< css::linguistic2::XHyphenatedWord
> xHyphWord
;
546 for (int i
= 0; i
+1 < sWord
.getLength(); i
++ )
548 xHyphWord
= xHyph
->hyphenate( sWord
,
549 aLanguageTag
.getLocale(),
552 // insert ZWSP at a hyphenation point, if it's not an alternative one (i.e. ssz->sz-sz)
553 if (xHyphWord
.is() && xHyphWord
->getHyphenationPos()+1 == i
&& !xHyphWord
->isAlternativeSpelling())
555 sDisambiguatedWord
.append(CHAR_ZWSP
);
557 sDisambiguatedWord
.append(sWord
[i
]);
559 sDisambiguatedWord
.append(sWord
[sWord
.getLength()-1]);
561 SvNumberFormatter
* pFormatter
= pDoc
->GetNumberFormatter();
563 if (pFormatter
&& !sWord
.isEmpty())
565 const Color
* pColor
= nullptr;
567 // Send text as NatNum12 prefix: "word" -> "[NatNum12 word]0"
569 // Closing bracket doesn't allowed in NatNum parameters, remove it from transliteration:
570 // "[word]" -> "[NatNum12 [word]0"
571 bool bHasBracket
= sWord
.endsWith("]");
573 sDisambiguatedWord
.append("]");
574 OUString
sPrefix("[NatNum12 " + sDisambiguatedWord
+ "0");
575 if (pFormatter
->GetPreviewString(sPrefix
, 0, sConverted
, &pColor
, LANGUAGE_USER_HUNGARIAN_ROVAS
))
578 sConverted
= sConverted
+ "]";
583 SwPaM
aPam(pFrame
->MapViewToModelPos(TextFrameIndex(rSttPos
)),
584 pFrame
->MapViewToModelPos(TextFrameIndex(nEndPos
)));
585 if (bRet
&& nEndPos
<= sFrameText
.getLength())
586 pDoc
->getIDocumentContentOperations().ReplaceRange(aPam
, sConverted
, false);
592 // Called by the functions:
593 // - FnCapitalStartWord
594 // - FnCapitalStartSentence
595 // after the exchange of characters. Then the words, if necessary, can be inserted
596 // into the exception list.
597 void SwAutoCorrDoc::SaveCpltSttWord( ACFlags nFlag
, sal_Int32 nPos
,
598 const OUString
& rExceptWord
,
601 SwNodeOffset nNode
= m_oIndex
? m_oIndex
->GetIndex() : m_rCursor
.GetPoint()->GetNodeIndex();
602 LanguageType eLang
= GetLanguage(nPos
);
603 m_rEditSh
.GetDoc()->SetAutoCorrExceptWord( std::make_unique
<SwAutoCorrExceptWord
>( nFlag
,
604 nNode
, nPos
, rExceptWord
, cChar
, eLang
));
607 LanguageType
SwAutoCorrDoc::GetLanguage( sal_Int32 nPos
) const
609 LanguageType eRet
= LANGUAGE_SYSTEM
;
611 SwTextNode
* pNd
= m_rCursor
.GetPoint()->GetNode().GetTextNode();
615 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(
616 pNd
->getLayoutFrame(m_rEditSh
.GetLayout())));
618 eRet
= pFrame
->GetLangOfChar(TextFrameIndex(nPos
), 0, true);
620 if(LANGUAGE_SYSTEM
== eRet
)
621 eRet
= GetAppLanguage();
625 void SwAutoCorrExceptWord::CheckChar( const SwPosition
& rPos
, sal_Unicode cChr
)
627 // test only if this is an improvement.
628 // If yes, then add the word to the list.
629 if (m_cChar
== cChr
&& rPos
.GetNodeIndex() == m_nNode
&& rPos
.GetContentIndex() == m_nContent
)
631 // get the current autocorrection:
632 SvxAutoCorrect
* pACorr
= SvxAutoCorrCfg::Get().GetAutoCorrect();
634 // then add to the list:
635 if (ACFlags::CapitalStartWord
& m_nFlags
)
636 pACorr
->AddWordStartException(m_sWord
, m_eLanguage
);
637 else if (ACFlags::CapitalStartSentence
& m_nFlags
)
638 pACorr
->AddCplSttException(m_sWord
, m_eLanguage
);
642 bool SwAutoCorrExceptWord::CheckDelChar( const SwPosition
& rPos
)
645 if (!m_bDeleted
&& rPos
.GetNodeIndex() == m_nNode
&& rPos
.GetContentIndex() == m_nContent
)
646 m_bDeleted
= bRet
= true;
650 SwDontExpandItem::~SwDontExpandItem()
654 void SwDontExpandItem::SaveDontExpandItems( const SwPosition
& rPos
)
656 const SwTextNode
* pTextNd
= rPos
.GetNode().GetTextNode();
659 m_pDontExpandItems
.reset( new SfxItemSet( const_cast<SwDoc
&>(pTextNd
->GetDoc()).GetAttrPool(),
660 aCharFormatSetRange
) );
661 const sal_Int32 n
= rPos
.GetContentIndex();
662 if (!pTextNd
->GetParaAttr( *m_pDontExpandItems
, n
, n
,
663 n
!= pTextNd
->GetText().getLength() ))
665 m_pDontExpandItems
.reset();
670 void SwDontExpandItem::RestoreDontExpandItems( const SwPosition
& rPos
)
672 SwTextNode
* pTextNd
= rPos
.GetNode().GetTextNode();
676 const sal_Int32 nStart
= rPos
.GetContentIndex();
677 if( nStart
== pTextNd
->GetText().getLength() )
678 pTextNd
->FormatToTextAttr( pTextNd
);
680 if( !(pTextNd
->GetpSwpHints() && pTextNd
->GetpSwpHints()->Count()) )
683 const size_t nSize
= pTextNd
->GetpSwpHints()->Count();
684 sal_Int32 nAttrStart
;
686 for( size_t n
= 0; n
< nSize
; ++n
)
688 SwTextAttr
* pHt
= pTextNd
->GetpSwpHints()->Get( n
);
689 nAttrStart
= pHt
->GetStart();
690 if( nAttrStart
> nStart
) // beyond the area
693 const sal_Int32
* pAttrEnd
;
694 if( nullptr != ( pAttrEnd
= pHt
->End() ) &&
695 ( ( nAttrStart
< nStart
&&
696 ( pHt
->DontExpand() ? nStart
< *pAttrEnd
697 : nStart
<= *pAttrEnd
)) ||
698 ( nStart
== nAttrStart
&&
699 ( nAttrStart
== *pAttrEnd
|| !nStart
))) )
701 const SfxPoolItem
* pItem
;
702 if( !m_pDontExpandItems
|| SfxItemState::SET
!= m_pDontExpandItems
->
703 GetItemState( pHt
->Which(), false, &pItem
) ||
704 *pItem
!= pHt
->GetAttr() )
706 // The attribute was not previously set in this form in the
707 // paragraph, so it can only be created through insert/copy
708 // Because of that it is a candidate for DontExpand
709 pHt
->SetDontExpand( true );
715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */