class SwKeepConversionDirectionStateContext
{ public:
SwKeepConversionDirectionStateContext()
{ //!! hack to transport the current conversion direction state settings //!! into the next incarnation that iterates over the drawing objects //!! ( see SwHHCWrapper::~SwHHCWrapper() )
editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( true );
}
// check for existence of a draw view which means that there are // (or previously were) draw objects present in the document. // I.e. we like to check those too. if ( m_bIsDrawObj /*&& bLastRet*/ && m_rView.GetWrtShell().HasDrawView() )
{
vcl::Cursor *pSave = m_rView.GetWindow()->GetCursor();
{
SwKeepConversionDirectionStateContext aContext;
// finally for chinese translation we need to change the documents // default language and font to the new ones to be used.
LanguageType nTargetLang = GetTargetLanguage(); if (!IsChinese( nTargetLang )) return;
SwDoc *pDoc = m_rView.GetDocShell()->GetDoc();
//!! Note: This also effects the default language of text boxes (EditEngine/EditView) !!
pDoc->SetDefault( SvxLanguageItem( nTargetLang, RES_CHRATR_CJK_LANGUAGE ) );
m_rWrtShell.Right( SwCursorSkipMode::Chars, /*bExpand*/ false,
o3tl::narrowing<sal_uInt16>(m_nUnitOffset + nUnitStart), true );
pCursor->SetMark();
m_rWrtShell.Right( SwCursorSkipMode::Chars, /*bExpand*/ true,
o3tl::narrowing<sal_uInt16>(nUnitEnd - nUnitStart), true ); // end selection now. Otherwise SHIFT+HOME (extending the selection) // won't work when the dialog is closed without any replacement. // (see #116346#)
m_rWrtShell.EndSelect();
}
// select current unit
SelectNewUnit_impl( nUnitStart, nUnitEnd );
m_rWrtShell.EndAllAction();
}
void SwHHCWrapper::ChangeText( const OUString &rNewText,
std::u16string_view aOrigText, const uno::Sequence< sal_Int32 > *pOffsets,
SwPaM *pCursor )
{ //!! please see also TextConvWrapper::ChangeText with is a modified //!! copy of this code
OSL_ENSURE( !rNewText.isEmpty(), "unexpected empty string" ); if (rNewText.isEmpty()) return;
if (pOffsets && pCursor) // try to keep as much attributation as possible ?
{ // remember cursor start position for later setting of the cursor const SwPosition *pStart = pCursor->Start(); const sal_Int32 nStartIndex = pStart->GetContentIndex();
SwTextNode *pStartTextNode = pStart->GetNode().GetTextNode();
// offset to calculate the position in the text taking into // account that text may have been replaced with new text of // different length. Negative values allowed!
tools::Long nCorrectionOffset = 0;
OSL_ENSURE(nIndices == 0 || nIndices == nConvTextLen, "mismatch between string length and sequence length!" );
// find all substrings that need to be replaced (and only those) while (true)
{ // get index in original text that matches nPos in new text
sal_Int32 nIndex; if (nPos < nConvTextLen)
nIndex = nPos < nIndices ? pIndices[nPos] : nPos; else
{
nPos = nConvTextLen;
nIndex = aOrigText.size();
}
if (nPos == nConvTextLen || /* end of string also terminates non-matching char sequence */
aOrigText[nIndex] == rNewText[nPos])
{ // substring that needs to be replaced found? if (nChgPos != -1 && nConvChgPos != -1)
{
nChgLen = nIndex - nChgPos;
nConvChgLen = nPos - nConvChgPos;
OUString aInNew( rNewText.copy( nConvChgPos, nConvChgLen ) );
// set selection to sub string to be replaced in original text
sal_Int32 nChgInNodeStartIndex = nStartIndex + nCorrectionOffset + nChgPos;
OSL_ENSURE( m_rWrtShell.GetCursor()->HasMark(), "cursor misplaced (nothing selected)" );
m_rWrtShell.GetCursor()->GetMark()->Assign( *pStartTextNode, nChgInNodeStartIndex );
m_rWrtShell.GetCursor()->GetPoint()->Assign( *pStartTextNode, nChgInNodeStartIndex + nChgLen );
// replace selected sub string with the corresponding // sub string from the new text while keeping as // much from the attributes as possible
ChangeText_impl( aInNew, true );
nCorrectionOffset += nConvChgLen - nChgLen;
nChgPos = -1;
nConvChgPos = -1;
}
} else
{ // begin of non-matching char sequence found ? if (nChgPos == -1 && nConvChgPos == -1)
{
nChgPos = nIndex;
nConvChgPos = nPos;
}
} if (nPos >= nConvTextLen) break;
++nPos;
}
// set cursor to the end of all the new text // (as it would happen after ChangeText_impl (Delete and Insert) // of the whole text in the 'else' branch below)
m_rWrtShell.ClearMark();
m_rWrtShell.GetCursor()->Start()->Assign( *pStartTextNode, nStartIndex + nConvTextLen );
} else
{
ChangeText_impl( rNewText, false );
}
}
void SwHHCWrapper::ChangeText_impl( const OUString &rNewText, bool bKeepAttributes )
{ if (bKeepAttributes)
{ // get item set with all relevant attributes
SfxItemSet aItemSet(SfxItemSet::makeFixedSfxItemSet<RES_CHRATR_BEGIN, RES_FRMATR_END>(m_rWrtShell.GetAttrPool())); // get all attributes spanning the whole selection in order to // restore those for the new text
m_rWrtShell.GetCurAttr( aItemSet );
// select new inserted text (currently the Point is right after the new text) if (!m_rWrtShell.GetCursor()->HasMark())
m_rWrtShell.GetCursor()->SetMark();
SwPosition *pMark = m_rWrtShell.GetCursor()->GetMark();
pMark->SetContent( pMark->GetContentIndex() - rNewText.getLength() );
// since 'SetAttr' below functions like merging with the attributes // from the itemset with any existing ones we have to get rid of all // all attributes now. (Those attributes that may take effect left // to the position where the new text gets inserted after the old text // was deleted)
m_rWrtShell.ResetAttr(); // apply previously saved attributes to new text
m_rWrtShell.SetAttrSet( aItemSet );
} else
{
m_rWrtShell.Delete(true);
m_rWrtShell.Insert( rNewText );
}
}
if (pRuby)
{
m_rWrtShell.StartUndo( SwUndoId::SETRUBYATTR ); if (!aNewOrigText.isEmpty())
{ // according to FT we currently should not bother about keeping // attributes in Hangul/Hanja conversion
ChangeText( aNewOrigText, rOrigText, nullptr, nullptr );
//!! since Delete, Insert in 'ChangeText' do not set the WrtShells //!! bInSelect flag //!! back to false we do it now manually in order for the selection //!! to be done properly in the following call to Left. // We didn't fix it in Delete and Insert since it is currently // unclear if someone depends on this incorrect behaviour // of the flag.
m_rWrtShell.EndSelect();
// according to FT we should currently not bother about keeping // attributes in Hangul/Hanja conversion and leave that untouched. // Thus we do this only for Chinese translation... constbool bIsChineseConversion = IsChinese( GetSourceLanguage() ); if (bIsChineseConversion)
ChangeText( aNewText, rOrigText, &rOffsets, m_rWrtShell.GetCursor() ); else
ChangeText( aNewText, rOrigText, nullptr, nullptr );
// change language and font if necessary if (bIsChineseConversion)
{
m_rWrtShell.SetMark();
m_rWrtShell.GetCursor()->GetMark()->AdjustContent( -aNewText.getLength() );
if (pSttPos->GetNode().IsTextNode() &&
pEndPos->GetNode().IsTextNode())
{
m_pConvArgs.reset( new SwConversionArgs( GetSourceLanguage(), *pSttPos, *pEndPos ) );
} else// we are not in the text (maybe a graphic or OLE object is selected) let's start from the top
{ // get PaM that points to the start of the document
SwNode& rNode = m_rView.GetDocShell()->GetDoc()->GetNodes().GetEndOfContent();
SwPaM aPam(rNode);
aPam.Move( fnMoveBackward, GoInDoc ); // move to start of document
pSttPos = aPam.GetPoint(); //! using a PaM here makes sure we will get only text nodes
SwTextNode *pTextNode = pSttPos->GetNode().GetTextNode(); // just in case we check anyway... if (!pTextNode || !pTextNode->IsTextNode()) return;
m_pConvArgs.reset( new SwConversionArgs( GetSourceLanguage(), *pSttPos, *pSttPos ) );
}
OSL_ENSURE( m_pConvArgs->pStartPos && m_pConvArgs->pStartPos->GetNode().IsTextNode(), "failed to get proper start text node" );
OSL_ENSURE( m_pConvArgs->pEndPos && m_pConvArgs->pEndPos->GetNode().IsTextNode(), "failed to get proper end text node" );
// chinese conversion specific settings
OSL_ENSURE( IsChinese( GetSourceLanguage() ) == IsChinese( GetTargetLanguage() ), "source and target language mismatch?" ); if (IsChinese( GetTargetLanguage() ))
{
m_pConvArgs->nConvTargetLang = GetTargetLanguage();
m_pConvArgs->pTargetFont = GetTargetFont();
m_pConvArgs->bAllowImplicitChangesForNotConvertibleText = true;
}
// if it is not just a selection and we are about to begin // with the current conversion for the very first time // we need to find the start of the current (initial) // convertible unit in order for the text conversion to give // the correct result for that. Since it is easier to obtain // the start of the word we use that though. if (!pCursor->HasMark()) // is not a selection?
{ // since #118246 / #117803 still occurs if the cursor is placed // between the two chinese characters to be converted (because both // of them are words on their own!) using the word boundary here does // not work. Thus since chinese conversion is not interactive we start // at the begin of the paragraph to solve the problem, i.e. have the // TextConversion service get those characters together in the same call.
sal_Int32 nStartIdx = -1; if (editeng::HangulHanjaConversion::IsChinese( GetSourceLanguage() ) )
nStartIdx = 0; else
{
OUString aText( m_pConvArgs->pStartPos->GetNode().GetTextNode()->GetText() ); const sal_Int32 nPos = m_pConvArgs->pStartPos->GetContentIndex();
Boundary aBoundary( g_pBreakIt->GetBreakIter()->
getWordBoundary( aText, nPos, g_pBreakIt->GetLocale( m_pConvArgs->nConvSrcLang ),
WordType::DICTIONARY_WORD, true ) );
// valid result found? if (aBoundary.startPos < aText.getLength() &&
aBoundary.startPos != aBoundary.endPos)
{
nStartIdx = aBoundary.startPos;
}
}
if (nStartIdx != -1)
m_pConvArgs->pStartPos->SetContent( nStartIdx );
}
}
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.