/* -*- 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 .
*/
PaMIntoCursorShellRing::~PaMIntoCursorShellRing()
{ // and take out the Pam again:
RemoveFromRing(m_rDelPam, m_pPrevDelPam);
RemoveFromRing(m_rCursor, m_pPrevCursor);
}
SwAutoCorrDoc::~SwAutoCorrDoc()
{ for (int i = 0; i < m_nEndUndoCounter; ++i)
{
m_rEditSh.EndUndo();
}
}
void SwAutoCorrDoc::DeleteSel( SwPaM& rDelPam )
{ // this should work with plain SwPaM as well because start and end // are always in same node, but since there is GetRanges already...
std::vector<std::shared_ptr<SwUnoCursor>> ranges; if (sw::GetRanges(ranges, *m_rEditSh.GetDoc(), rDelPam))
{
DeleteSelImpl(rDelPam);
} else
{ for (autoconst& pCursor : ranges)
{
DeleteSelImpl(*pCursor);
}
}
}
void SwAutoCorrDoc::DeleteSelImpl(SwPaM & rDelPam)
{
SwDoc* pDoc = m_rEditSh.GetDoc(); if( pDoc->IsAutoFormatRedline() )
{ // so that also the DelPam be moved, include it in the // Shell-Cursr-Ring !! // ??? is that really necessary - this should never join nodes, so Update should be enough? // PaMIntoCursorShellRing aTmp( rEditSh, rCursor, rDelPam );
assert(rDelPam.GetPoint()->GetNode() == rDelPam.GetMark()->GetNode());
pDoc->getIDocumentContentOperations().DeleteAndJoin( rDelPam );
} else
{
pDoc->getIDocumentContentOperations().DeleteRange( rDelPam );
}
}
bool SwAutoCorrDoc::ReplaceRange( sal_Int32 nPos, sal_Int32 nSourceLength, const OUString& rText )
{
assert(nSourceLength == 1); // sw_redlinehide: this is currently the case, // and ensures that the replace range cannot *contain* delete redlines, // so we don't need something along the lines of: // if (sw::GetRanges(ranges, *rEditSh.GetDoc(), aPam)) // ReplaceImpl(...) // else // ReplaceImpl(ranges.begin()) // for (ranges.begin() + 1; ranges.end(); ) // DeleteImpl(*it)
SwPaM* pPam = &m_rCursor; if (pPam->GetPoint()->GetNode() != *pos.first
|| pPam->GetPoint()->GetContentIndex() != pos.second)
{
pPam = new SwPaM(*pos.first, pos.second);
}
// text attributes with dummy characters must not be replaced! bool bDoReplace = true;
sal_Int32 const nLen = rText.getLength(); for (sal_Int32 n = 0; n < nLen && n + nPos < pFrame->GetText().getLength(); ++n)
{
sal_Unicode constChar = pFrame->GetText()[n + nPos]; if (CH_TXTATR_BREAKWORD == Char || CH_TXTATR_INWORD == Char)
{
assert(pFrame->MapViewToModel(TextFrameIndex(n+nPos)).first->GetTextAttrForCharAt(pFrame->MapViewToModel(TextFrameIndex(n+nPos)).second));
bDoReplace = false; break;
}
}
// tdf#83419 avoid bad autocorrect with visible redlines // e.g. replacing the first letter of the tracked deletion // with its capitalized (and not deleted) version. if ( bDoReplace && !pFrame->getRootFrame()->IsHideRedlines() &&
m_rEditSh.GetDoc()->getIDocumentRedlineAccess().HasRedline( *pPam, RedlineType::Delete, /*bStartOrEndInRange=*/false ) )
{
bDoReplace = false;
}
if ( bDoReplace )
{
SwDoc* pDoc = m_rEditSh.GetDoc();
if( pDoc->IsAutoFormatRedline() )
{ if (nPos == pFrame->GetText().getLength()) // at the End do an Insert
{
pDoc->getIDocumentContentOperations().InsertString( *pPam, rText );
} else
{
assert(pos.second != pos.first->Len()); // must be _before_ char
PaMIntoCursorShellRing aTmp( m_rEditSh, m_rCursor, *pPam );
/** Return the text of a previous paragraph * * @param bAtNormalPos If <true> before the normal insert position; if <false> in which the * corrected word was inserted. (Doesn't need to be the same paragraph!) * @return text or 0, if previous paragraph does not exists or there are only blankness
*/
OUString const* SwAutoCorrDoc::GetPrevPara(boolconst bAtNormalPos)
{
OUString const* pStr(nullptr);
// Found a beginning of a paragraph or a Blank, // search for the word Kuerzel (Shortcut) in the Auto
SwTextNode* pTextNd = m_rCursor.GetPointNode().GetTextNode();
OSL_ENSURE( pTextNd, "where is the TextNode?" );
// don't replace, if a redline starts or ends within the original text if ( pDoc->getIDocumentRedlineAccess().HasRedline( aPam, RedlineType::Any, /*bStartOrEndInRange=*/true ) )
{ return bRet;
}
if( pFnd->IsTextOnly() )
{ //JP 22.04.99: Bug 63883 - Special treatment for dots. constbool bLastCharIsPoint
= nEndPos < sFrameText.getLength() && ('.' == sFrameText[nEndPos]); if( !bLastCharIsPoint || pFnd->GetLong().isEmpty() || '.' != pFnd->GetLong()[ pFnd->GetLong().getLength() - 1 ] )
{ // replace the selection
std::vector<std::shared_ptr<SwUnoCursor>> ranges; bool noRedlines = sw::GetRanges(ranges,
*m_rEditSh.GetDoc(), aPam);
OSL_ENSURE(noRedlines, "redlines should have been blocked.");
OSL_ENSURE(ranges.empty(), "no redlines expected here.");
// tdf#83260 After calling sw::DocumentContentOperationsManager::ReplaceRange // pTextNd may become invalid when change tracking is on and Edit -> Track Changes -> Show == OFF. // ReplaceRange shows changes, this moves deleted nodes from special section to document. // Then Show mode is disabled again. As a result pTextNd may be invalidated.
pTextNd = m_rCursor.GetPointNode().GetTextNode();
}
} else
{
SwTextBlocks aTBlks( rACorrect.GetAutoCorrFileName( aLanguageTag, false, true ));
sal_uInt16 nPos = aTBlks.GetIndex( pFnd->GetShort() ); if( USHRT_MAX != nPos && aTBlks.BeginGetDoc( nPos ) )
{
DeleteSel( aPam );
pDoc->DontExpandFormat( *aPam.GetPoint() );
if( pPara )
{
OSL_ENSURE( !m_oIndex, "who has not deleted his Index?" );
m_oIndex.emplace(m_rCursor.GetPoint()->GetNode());
sw::GotoPrevLayoutTextFrame(*m_oIndex, m_rEditSh.GetLayout());
}
// then until the end of the Nodes Array
aCpyPam.GetPoint()->Assign( pAutoDoc->GetNodes().GetEndOfContent(), SwNodeOffset(-1) );
pContentNd = aCpyPam.GetPointContentNode(); if (pContentNd)
aCpyPam.GetPoint()->SetContent( pContentNd->Len() );
if( pPara )
{
sw::GotoNextLayoutTextFrame(*m_oIndex, m_rEditSh.GetLayout());
pTextNd = m_oIndex->GetNode().GetTextNode();
} // hmm... the inserted text can have multiple text nodes // - not sure what the "pos" should point to, but pFrame // is not changed so try the first node?
nEndPos = sttPos + aCpyPam.GetMark()->GetContentIndex();
bRet = true;
}
aTBlks.EndGetDoc();
} if( sttPos < minSttPos) {
minSttPos = sttPos;
}
sttPos = rSttPos;
sFrameText = pFrame->GetText();
} while( SvxAutoCorrect::SearchWordsNext(sFrameText, sttPos, nEndPos,
*pStatus) );
rSttPos = minSttPos;
}
const OUString sFrameText = pFrame->GetText();
SwDoc* pDoc = m_rEditSh.GetDoc(); if ( pFrame->IsRightToLeft() || bApply )
{ // transliterate to Old Hungarian using Numbertext via NatNum12 number format modifier
OUString sWord(sFrameText.copy(rSttPos, nEndPos - rSttPos)); // Consonant disambiguation using hyphenation
uno::Reference< linguistic2::XHyphenator > xHyph;
xHyph = ::GetHyphenator();
OUStringBuffer sDisambiguatedWord;
const ::css::uno::Sequence< ::css::beans::PropertyValue > aProperties;
css::uno::Reference< css::linguistic2::XHyphenatedWord > xHyphWord; for (int i = 0; i+1 < sWord.getLength(); i++ )
{
xHyphWord = xHyph->hyphenate( sWord,
aLanguageTag.getLocale(),
i,
aProperties ); // insert ZWSP at a hyphenation point, if it's not an alternative one (i.e. ssz->sz-sz) if (xHyphWord.is() && xHyphWord->getHyphenationPos()+1 == i && !xHyphWord->isAlternativeSpelling())
{
sDisambiguatedWord.append(CHAR_ZWSP);
}
sDisambiguatedWord.append(sWord[i]);
}
sDisambiguatedWord.append(sWord[sWord.getLength()-1]);
// Called by the functions: // - FnCapitalStartWord // - FnCapitalStartSentence // after the exchange of characters. Then the words, if necessary, can be inserted // into the exception list. void SwAutoCorrDoc::SaveCpltSttWord( ACFlags nFlag, sal_Int32 nPos, const OUString& rExceptWord,
sal_Unicode cChar )
{
SwNodeOffset nNode = m_oIndex ? m_oIndex->GetIndex() : m_rCursor.GetPoint()->GetNodeIndex();
LanguageType eLang = GetLanguage(nPos);
m_rEditSh.GetDoc()->SetAutoCorrExceptWord( std::make_unique<SwAutoCorrExceptWord>( nFlag,
nNode, nPos, rExceptWord, cChar, eLang ));
}
void SwAutoCorrExceptWord::CheckChar( const SwPosition& rPos, sal_Unicode cChr )
{ // test only if this is an improvement. // If yes, then add the word to the list. if (m_cChar == cChr && rPos.GetNodeIndex() == m_nNode && rPos.GetContentIndex() == m_nContent)
{ // get the current autocorrection:
SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
// then add to the list: if (ACFlags::CapitalStartWord & m_nFlags)
pACorr->AddWordStartException(m_sWord, m_eLanguage); elseif (ACFlags::CapitalStartSentence & m_nFlags)
pACorr->AddCplSttException(m_sWord, m_eLanguage);
}
}
for( size_t n = 0; n < nSize; ++n )
{
SwTextAttr* pHt = pTextNd->GetpSwpHints()->Get( n );
nAttrStart = pHt->GetStart(); if( nAttrStart > nStart ) // beyond the area break;
const sal_Int32* pAttrEnd; if( nullptr != ( pAttrEnd = pHt->End() ) &&
( ( nAttrStart < nStart &&
( pHt->DontExpand() ? nStart < *pAttrEnd
: nStart <= *pAttrEnd )) ||
( nStart == nAttrStart &&
( nAttrStart == *pAttrEnd || !nStart ))) )
{ const SfxPoolItem* pItem; if( !m_pDontExpandItems || SfxItemState::SET != m_pDontExpandItems->
GetItemState( pHt->Which(), false, &pItem ) ||
*pItem != pHt->GetAttr() )
{ // The attribute was not previously set in this form in the // paragraph, so it can only be created through insert/copy // Because of that it is a candidate for DontExpand
pHt->SetDontExpand( true );
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.