/* -*- 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 .
*/
// the value of used script types const SvtScriptType nScriptType =pOLV->GetSelectedScriptType();
OUString aScriptTypesInUse( OUString::number( static_cast<int>(nScriptType) ) );//rEditEngine.GetScriptType(aSelection)
// get keyboard language
OUString aKeyboardLang;
LanguageType nLang = rEditView.GetInputLanguage(); if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM)
aKeyboardLang = SvtLanguageTable::GetLanguageString( nLang );
// get the language that is in use
OUString aCurrentLang(u"*"_ustr);
SfxItemSet aSet(pOLV->GetAttribs());
nLang = SwLangHelper::GetCurrentLanguage( aSet,nScriptType ); if (nLang != LANGUAGE_DONTKNOW)
aCurrentLang = SvtLanguageTable::GetLanguageString( nLang );
// build sequence for status value
uno::Sequence<OUString> aSeq{ aCurrentLang,
aScriptTypesInUse,
aKeyboardLang,
SwLangHelper::GetTextForLanguageGuessing(&rEditEngine, aSelection)
};
// set sequence as status value
SfxStringListItem aItem( SID_LANGUAGE_STATUS );
aItem.SetStringList( aSeq );
rSet.Put( aItem );
}
const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(SID_LANGUAGE_STATUS); if (pItem)
aNewLangText = pItem->GetValue();
//!! Remember the view frame right now... //!! (call to GetView().GetViewFrame() will break if the //!! SwTextShell got destroyed meanwhile.)
SfxViewFrame& rViewFrame = rView.GetViewFrame();
if (aNewLangText == "*" )
{ // open the dialog "Tools/Options/Languages and Locales - General"
SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog( rView.GetFrameWeld(), SID_LANGUAGE_OPTIONS ));
pDlg->Execute();
} else
{ // setting the new language... if (!aNewLangText.isEmpty())
{ static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr); static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr); static constexpr OUString aDocumentLangPrefix(u"Default_"_ustr);
sal_Int32 nPos = 0; bool bForSelection = true; bool bForParagraph = false; if (-1 != (nPos = aNewLangText.indexOf( aSelectionLangPrefix )))
{ // ... for the current selection
aNewLangText = aNewLangText.replaceAt(nPos, aSelectionLangPrefix.getLength(), u"");
bForSelection = true;
} elseif (-1 != (nPos = aNewLangText.indexOf( aParagraphLangPrefix )))
{ // ... for the current paragraph language
aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), u"");
bForSelection = true;
bForParagraph = true;
} elseif (-1 != (nPos = aNewLangText.indexOf( aDocumentLangPrefix )))
{ // ... as default document language
aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), u"");
bForSelection = false;
}
if (bForParagraph)
{
bRestoreSelection = true;
SwLangHelper::SelectPara( rEditView, aSelection );
aSelection = pOLV->GetSelection();
} if (!bForSelection) // document language to be changed...
{
rSh.StartAction();
rSh.LockView( true );
rSh.Push();
// prepare to apply new language to all text in document
rSh.SelAll();
rSh.ExtendedSelectAll();
}
if (!bForSelection)
{ // need to release view and restore selection...
rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
rSh.LockView( false );
rSh.EndAction();
}
}
}
// invalidate slot to get the new language displayed
rViewFrame.GetBindings().Invalidate( rReq.GetSlot() );
// change language for selection or paragraph // (for paragraph is handled by previously having set the selection to the // whole paragraph) if (bIsForSelection)
{ // apply language to current selection if (pEditEngine)
{
rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
rCoreSet.Put(SvxScriptHintItem(eHintType, nHintWhichId));
pEditEngine->QuickSetAttribs(rCoreSet, rSelection);
} else
{
rWrtSh.GetCurAttr( rCoreSet );
rCoreSet.Put( SvxLanguageItem( nLang, nLangWhichId ));
rCoreSet.Put(SvxScriptHintItem(eHintType, nHintWhichId));
rWrtSh.SetAttrSet( rCoreSet );
}
} else// change language for all text
{ // set document default language switch (nLangWhichId)
{ case EE_CHAR_LANGUAGE : nLangWhichId = RES_CHRATR_LANGUAGE; break; case EE_CHAR_LANGUAGE_CJK : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break; case EE_CHAR_LANGUAGE_CTL : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
} //Set the default document language
rWrtSh.SetDefault( SvxLanguageItem( nLang, nLangWhichId ) );
rWrtSh.GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::LanguageChanged));
// #i102191: hard set respective language attribute in text document // (for all text in the document - which should be selected by now...)
rWrtSh.SetAttrItem( SvxLanguageItem( nLang, nLangWhichId ) );
}
}
if (bIsForSelection)
{ // change language for selection or paragraph // (for paragraph is handled by previously having set the selection to the // whole paragraph)
EditEngine* pEditEngine = pOLV ? &pOLV->GetEditView().getEditEngine() : nullptr;
OSL_ENSURE( !pOLV || pEditEngine, "OutlinerView without EditEngine???" ); if (pEditEngine)
{ for (sal_uInt16 i : aLangWhichId_EE)
rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, i ));
pEditEngine->QuickSetAttribs(rCoreSet, rSelection);
} else
{
rWrtSh.GetCurAttr( rCoreSet ); for (sal_uInt16 i : aLangWhichId_Writer)
rCoreSet.Put( SvxLanguageItem( LANGUAGE_NONE, i ));
rWrtSh.SetAttrSet( rCoreSet );
}
} else// change language for all text
{
o3tl::sorted_vector<sal_uInt16> aAttribs; for (sal_uInt16 i : aLangWhichId_Writer)
{
rWrtSh.SetDefault( SvxLanguageItem( LANGUAGE_NONE, i ) );
aAttribs.insert( i );
}
rWrtSh.GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::LanguageChanged));
// set all language attributes to default // (for all text in the document - which should be selected by now...)
rWrtSh.ResetAttr( aAttribs );
}
}
void ResetLanguages( SwWrtShell &rWrtSh, OutlinerView const * pOLV )
{ // reset language for current selection. // The selection should already have been expanded to the whole paragraph or // to all text in the document if those are the ranges where to reset // the language attributes
// ugly hack, as it seems that EditView/EditEngine does not update their spellchecking marks // when setting a new language attribute
EditEngine& rEditEngine = rEditView.getEditEngine();
EEControlBits nCntrl = rEditEngine.GetControlWord(); // turn off
rEditEngine.SetControlWord(nCntrl & ~EEControlBits::ONLINESPELLING); //turn back on
rEditEngine.SetControlWord(nCntrl);
rEditEngine.CompleteOnlineSpelling();
/// @returns : the language for the selected text that is set for the /// specified attribute (script type). /// If there are more than one languages used LANGUAGE_DONTKNOW will be returned. /// @param nLangWhichId : one of /// RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
LanguageType GetLanguage( SwWrtShell &rSh, TypedWhichId<SvxLanguageItem> nLangWhichId )
{
SfxItemSet aSet( rSh.GetAttrPool(), nLangWhichId, nLangWhichId );
rSh.GetCurAttr( aSet );
const SvxLanguageItem *pItem = nullptr;
SfxItemState nState = aSet.GetItemState( nLangWhichId, true, &pItem ); if (nState > SfxItemState::DEFAULT && pItem)
{ // the item is set and can be used
nLang = pItem->GetLanguage();
} elseif (nState == SfxItemState::DEFAULT)
{ // since the attribute is not set: retrieve the default value
nLang = aSet.GetPool()->GetUserOrPoolDefaultItem( nLangWhichId ).GetLanguage();
} elseif (nState == SfxItemState::INVALID)
{ // there is more than one language...
nLang = LANGUAGE_DONTKNOW;
}
OSL_ENSURE( nLang != LANGUAGE_SYSTEM, "failed to get the language?" );
return nLang;
}
/// @returns: the language in use for the selected text. /// 'In use' means the language(s) matching the script type(s) of the /// selected text. Or in other words, the language a spell checker would use. /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
LanguageType GetCurrentLanguage( SwWrtShell &rSh )
{ //set language attribute to use according to the script type
TypedWhichId<SvxLanguageItem> nLangWhichId(0); bool bIsSingleScriptType = true; switch (rSh.GetScriptType())
{ case SvtScriptType::LATIN : nLangWhichId = RES_CHRATR_LANGUAGE; break; case SvtScriptType::ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break; case SvtScriptType::COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break; default: bIsSingleScriptType = false; break;
}
// get language according to the script type(s) in use
LanguageType nCurrentLang = LANGUAGE_SYSTEM; if (bIsSingleScriptType)
nCurrentLang = GetLanguage( rSh, nLangWhichId ); else
{ // check if all script types are set to LANGUAGE_NONE and return // that if this is the case. Otherwise, having multiple script types // in use always means there are several languages in use... const TypedWhichId<SvxLanguageItem> aScriptTypes[3] =
{
RES_CHRATR_LANGUAGE,
RES_CHRATR_CJK_LANGUAGE,
RES_CHRATR_CTL_LANGUAGE
};
nCurrentLang = LANGUAGE_NONE; for (const TypedWhichId<SvxLanguageItem>& aScriptType : aScriptTypes)
{
LanguageType nTmpLang = GetLanguage( rSh, aScriptType ); if (nTmpLang != LANGUAGE_NONE)
{
nCurrentLang = LANGUAGE_DONTKNOW; break;
}
}
}
OSL_ENSURE( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
return nCurrentLang;
}
/// @returns: the language in use for the selected text. /// 'In use' means the language(s) matching the script type(s) of the /// selected text. Or in other words, the language a spell checker would use. /// If there is more than one language LANGUAGE_DONTKNOW will be returned.
LanguageType GetCurrentLanguage( SfxItemSet const & aSet, SvtScriptType nScriptType )
{ //set language attribute to use according to the script type
TypedWhichId<SvxLanguageItem> nLangWhichId(0); bool bIsSingleScriptType = true; switch (nScriptType)
{ case SvtScriptType::LATIN : nLangWhichId = EE_CHAR_LANGUAGE; break; case SvtScriptType::ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; default: bIsSingleScriptType = false;
}
// get language according to the script type(s) in use
LanguageType nCurrentLang = LANGUAGE_SYSTEM; if (bIsSingleScriptType)
nCurrentLang = GetLanguage( aSet, nLangWhichId ); else
{ // check if all script types are set to LANGUAGE_NONE and return // that if this is the case. Otherwise, having multiple script types // in use always means there are several languages in use... const TypedWhichId<SvxLanguageItem> aScriptTypes[3] =
{
EE_CHAR_LANGUAGE,
EE_CHAR_LANGUAGE_CJK,
EE_CHAR_LANGUAGE_CTL
};
nCurrentLang = LANGUAGE_NONE; for (const TypedWhichId<SvxLanguageItem>& aScriptType : aScriptTypes)
{
LanguageType nTmpLang = GetLanguage( aSet, aScriptType ); if (nTmpLang != LANGUAGE_NONE)
{
nCurrentLang = LANGUAGE_DONTKNOW; break;
}
}
}
OSL_ENSURE( nCurrentLang != LANGUAGE_SYSTEM, "failed to get the language?" );
return nCurrentLang;
}
OUString GetTextForLanguageGuessing( SwWrtShell const &rSh )
{ // string for guessing language
OUString aText;
SwPaM *pCursor = rSh.GetCursor();
SwTextNode *pNode = pCursor->GetPointNode().GetTextNode(); if (pNode)
{
aText = pNode->GetText(); if (!aText.isEmpty())
{
sal_Int32 nEnd = pCursor->GetPoint()->GetContentIndex(); // at most 100 chars to the left... const sal_Int32 nStt = nEnd > 100 ? nEnd - 100 : 0; // ... and 100 to the right of the cursor position
nEnd = aText.getLength() - nEnd > 100 ? nEnd + 100 : aText.getLength();
aText = aText.copy( nStt, nEnd - nStt );
}
} return aText;
}
OUString GetTextForLanguageGuessing(EditEngine const * rEditEngine, const ESelection& rDocSelection)
{ // string for guessing language
// get the full text of the paragraph that the end of selection is in
OUString aText = rEditEngine->GetText(rDocSelection.end.nIndex); if (!aText.isEmpty())
{
sal_Int32 nStt = 0;
sal_Int32 nEnd = rDocSelection.end.nIndex; // at most 100 chars to the left...
nStt = nEnd > 100 ? nEnd - 100 : 0; // ... and 100 to the right of the cursor position
nEnd = aText.getLength() - nEnd > 100 ? nEnd + 100 : aText.getLength();
aText = aText.copy( nStt, nEnd - nStt );
}
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.