/* -*- 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { struct TextPortion { sal_uInt16 nStart, nEnd; svtools::ColorConfigEntry eType; }; } #define MAX_SYNTAX_HIGHLIGHT 20 #define MAX_HIGHLIGHTTIME 200 typedef std::vector TextPortions; static void lcl_Highlight(std::u16string_view aSource, TextPortions& aPortionList) { const sal_Unicode cOpenBracket = '<'; const sal_Unicode cCloseBracket= '>'; const sal_Unicode cSlash = '/'; const sal_Unicode cExclamation = '!'; const sal_Unicode cMinus = '-'; const sal_Unicode cSpace = ' '; const sal_Unicode cTab = 0x09; const sal_Unicode cLF = 0x0a; const sal_Unicode cCR = 0x0d; const sal_Int32 nStrLen = aSource.size(); sal_Int32 nInsert = 0; // number of inserted portions sal_Int32 nActPos = 0; // position, where '<' was found sal_Int32 nPortStart = SAL_MAX_INT32; // for the TextPortion sal_Int32 nPortEnd = 0; TextPortion aText; while(nActPos < nStrLen) { if((nActPos < nStrLen - 2) && (aSource[nActPos] == cOpenBracket)) { svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN; // insert 'empty' portion if(nPortEnd < nActPos - 1 ) { // don't move at the beginning aText.nStart = nPortEnd; if(nInsert) aText.nStart += 1; aText.nEnd = nActPos - 1; aText.eType = svtools::HTMLUNKNOWN; aPortionList.push_back( aText ); nInsert++; } sal_Unicode cFollowFirst = aSource[nActPos + 1]; sal_Unicode cFollowNext = aSource[nActPos + 2]; if(cExclamation == cFollowFirst) { // " nActPos + 1) { // some string was found OUString sToken( aSource.substr(nActPos + 1, nSrchPos - nActPos - 1 ) ); sToken = sToken.toAsciiUpperCase(); HtmlTokenId nToken = ::GetHTMLToken(sToken); if(nToken != HtmlTokenId::NONE) { eFoundType = svtools::HTMLKEYWORD; nPortEnd = nSrchPos; nPortStart = nActPos; } else SAL_WARN("sw", "HTML token " << sToken << " not recognised!"); } } // now we still have to look for '>' if(svtools::HTMLUNKNOWN != eFoundType) { bool bFound = false; for(sal_Int32 i = nPortEnd; i < nStrLen; i++) if(cCloseBracket == aSource[i]) { bFound = true; nPortEnd = i; break; } if(!bFound && (eFoundType == svtools::HTMLCOMMENT)) { // comment without ending in this line bFound = true; nPortEnd = nStrLen - 1; } if(bFound ||(eFoundType == svtools::HTMLCOMMENT)) { TextPortion aTextPortion; aTextPortion.nStart = nPortStart + 1; aTextPortion.nEnd = nPortEnd; aTextPortion.eType = eFoundType; aPortionList.push_back( aTextPortion ); nInsert++; } } } nActPos++; } if(nInsert && nPortEnd < nActPos - 1) { aText.nStart = nPortEnd + 1; aText.nEnd = nActPos - 1; aText.eType = svtools::HTMLUNKNOWN; aPortionList.push_back( aText ); nInsert++; } } class SwSrcEditWindow::ChangesListener: public cppu::WeakImplHelper< css::beans::XPropertiesChangeListener > { public: explicit ChangesListener(SwSrcEditWindow & editor): m_Editor(editor) {} private: virtual ~ChangesListener() override {} virtual void SAL_CALL disposing(css::lang::EventObject const &) override { std::unique_lock g(m_Editor.mutex_); m_Editor.m_xNotifier.clear(); } virtual void SAL_CALL propertiesChange( css::uno::Sequence< css::beans::PropertyChangeEvent > const &) override { SolarMutexGuard g; m_Editor.SetFont(); } SwSrcEditWindow & m_Editor; }; SwSrcEditWindow::SwSrcEditWindow( vcl::Window* pParent, SwSrcView* pParentView ) : Window( pParent, WB_BORDER|WB_CLIPCHILDREN ), m_pOutWin(nullptr), m_pHScrollbar(nullptr), m_pVScrollbar(nullptr), m_pSrcView(pParentView), m_nCurTextWidth(0), m_nStartLine(USHRT_MAX), m_eSourceEncoding(osl_getThreadTextEncoding()), m_bReadonly(false), m_bHighlighting(false), m_aSyntaxIdle("sw uibase SwSrcEditWindow Syntax") { SetHelpId(HID_SOURCE_EDITWIN); CreateTextEngine(); // Using "this" in ctor is a little fishy, but should work here at least as // long as there are no derivations: m_xListener = new ChangesListener(*this); css::uno::Reference< css::beans::XMultiPropertySet > n( officecfg::Office::Common::Font::SourceViewFont::get(), css::uno::UNO_QUERY_THROW); { std::unique_lock g(mutex_); m_xNotifier = n; } n->addPropertiesChangeListener({ "FontHeight", "FontName" }, m_xListener); } SwSrcEditWindow::~SwSrcEditWindow() { disposeOnce(); } void SwSrcEditWindow::dispose() { css::uno::Reference< css::beans::XMultiPropertySet > n; { std::unique_lock g(mutex_); n = m_xNotifier; } if (n.is()) { n->removePropertiesChangeListener(m_xListener); } m_aSyntaxIdle.Stop(); if ( m_pOutWin ) m_pOutWin->SetTextView( nullptr ); if ( m_pTextEngine ) { EndListening( *m_pTextEngine ); m_pTextEngine->RemoveView( m_pTextView.get() ); m_pTextView.reset(); m_pTextEngine.reset(); } m_pHScrollbar.disposeAndClear(); m_pVScrollbar.disposeAndClear(); m_pOutWin.disposeAndClear(); vcl::Window::dispose(); } void SwSrcEditWindow::DataChanged( const DataChangedEvent& rDCEvt ) { Window::DataChanged( rDCEvt ); switch ( rDCEvt.GetType() ) { case DataChangedEventType::SETTINGS: // newly rearrange ScrollBars or trigger Resize, because // ScrollBar size could have changed. For this, in the // Resize handler the size of ScrollBars has to be queried // from the settings as well. if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) Resize(); break; default: break; } } void SwSrcEditWindow::Resize() { // ScrollBars, etc. happens in Adjust... if ( !m_pTextView ) return; tools::Long nVisY = m_pTextView->GetStartDocPos().Y(); m_pTextView->ShowCursor(); Size aOutSz( GetOutputSizePixel() ); tools::Long nMaxVisAreaStart = m_pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height(); if ( nMaxVisAreaStart < 0 ) nMaxVisAreaStart = 0; if ( m_pTextView->GetStartDocPos().Y() > nMaxVisAreaStart ) { Point aStartDocPos( m_pTextView->GetStartDocPos() ); aStartDocPos.setY( nMaxVisAreaStart ); m_pTextView->SetStartDocPos( aStartDocPos ); m_pTextView->ShowCursor(); } tools::Long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize(); Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd ); Point aScrollPos(0, aOutSz.Height() - nScrollStd); m_pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); aScrollSz.setWidth( aScrollSz.Height() ); aScrollSz.setHeight( aOutSz.Height() ); aScrollPos = Point(aOutSz.Width() - nScrollStd, 0); m_pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); aOutSz.AdjustWidth( -nScrollStd ); aOutSz.AdjustHeight( -nScrollStd ); m_pOutWin->SetOutputSizePixel(aOutSz); InitScrollBars(); // set line in first Resize if(USHRT_MAX != m_nStartLine) { if(m_nStartLine < m_pTextEngine->GetParagraphCount()) { TextSelection aSel(TextPaM( m_nStartLine, 0 ), TextPaM( m_nStartLine, 0x0 )); m_pTextView->SetSelection(aSel); m_pTextView->ShowCursor(); } m_nStartLine = USHRT_MAX; } if ( nVisY != m_pTextView->GetStartDocPos().Y() ) Invalidate(); } void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt ) { Window::DataChanged( rDCEvt ); switch( rDCEvt.GetType() ) { case DataChangedEventType::SETTINGS: // query settings if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) { const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); SetBackground( rCol ); vcl::Font aFont( m_pTextView->GetTextEngine()->GetFont() ); aFont.SetFillColor( rCol ); m_pTextView->GetTextEngine()->SetFont( aFont ); } break; default: break; } } void TextViewOutWin::MouseMove( const MouseEvent &rEvt ) { if ( m_pTextView ) m_pTextView->MouseMove( rEvt ); } void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt ) { if ( m_pTextView ) { m_pTextView->MouseButtonUp( rEvt ); SfxViewFrame& rFrame = static_cast(GetParent())->GetSrcView()->GetViewFrame(); SfxBindings& rBindings = rFrame.GetBindings(); rBindings.Invalidate( SID_TABLE_CELL ); rBindings.Invalidate( SID_CUT ); rBindings.Invalidate( SID_COPY ); } } void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt ) { GrabFocus(); if ( m_pTextView ) m_pTextView->MouseButtonDown( rEvt ); } void TextViewOutWin::Command( const CommandEvent& rCEvt ) { switch(rCEvt.GetCommand()) { case CommandEventId::ContextMenu: SfxDispatcher::ExecutePopup(); break; case CommandEventId::Wheel: case CommandEventId::StartAutoScroll: case CommandEventId::AutoScroll: { const CommandWheelData* pWData = rCEvt.GetWheelData(); if( !pWData || CommandWheelMode::ZOOM != pWData->GetMode() ) { static_cast(GetParent())->HandleWheelCommand( rCEvt ); } } break; default: if ( m_pTextView ) m_pTextView->Command( rCEvt ); else Window::Command(rCEvt); } } void TextViewOutWin::KeyInput( const KeyEvent& rKEvt ) { bool bDone = false; SwSrcEditWindow* pSrcEditWin = static_cast(GetParent()); bool bChange = !pSrcEditWin->IsReadonly() || !TextEngine::DoesKeyChangeText( rKEvt ); if(bChange) bDone = m_pTextView->KeyInput( rKEvt ); SfxBindings& rBindings = static_cast(GetParent())->GetSrcView()->GetViewFrame().GetBindings(); if ( !bDone ) { if ( !SfxViewShell::Current()->KeyInput( rKEvt ) ) Window::KeyInput( rKEvt ); } else { rBindings.Invalidate( SID_TABLE_CELL ); if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) rBindings.Update( SID_BASICIDE_STAT_POS ); if (pSrcEditWin->GetTextEngine()->IsModified() ) { rBindings.Invalidate( SID_SAVEDOC ); rBindings.Invalidate( SID_DOC_MODIFIED ); } if( rKEvt.GetKeyCode().GetCode() == KEY_INSERT ) rBindings.Invalidate( SID_ATTR_INSERT ); } rBindings.Invalidate( SID_CUT ); rBindings.Invalidate( SID_COPY ); SwDocShell* pDocShell = pSrcEditWin->GetSrcView()->GetDocShell(); if(pSrcEditWin->GetTextEngine()->IsModified()) { pDocShell->SetModified(); } } void TextViewOutWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) { m_pTextView->Paint(rRenderContext, rRect); } void SwSrcEditWindow::CreateTextEngine() { // FIXME RenderContext const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); m_pOutWin = VclPtr::Create(this, 0); m_pOutWin->SetBackground(Wallpaper(rCol)); m_pOutWin->SetPointer(PointerStyle::Text); m_pOutWin->Show(); // create Scrollbars m_pHScrollbar = VclPtr::Create(this, true); m_pHScrollbar->EnableRTL( false ); m_pHScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, HorzScrollHdl)); m_pHScrollbar->Show(); m_pVScrollbar = VclPtr::Create(this, false); m_pVScrollbar->EnableRTL( false ); m_pVScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, VertScrollHdl)); m_pVScrollbar->Show(); m_pTextEngine.reset(new ExtTextEngine); m_pTextView.reset(new TextView( m_pTextEngine.get(), m_pOutWin )); m_pTextView->SetAutoIndentMode(true); m_pOutWin->SetTextView(m_pTextView.get()); m_pTextEngine->SetUpdateMode( false ); m_pTextEngine->InsertView( m_pTextView.get() ); vcl::Font aFont; aFont.SetTransparent( false ); aFont.SetFillColor( rCol ); SetPointFont(*GetOutDev(), aFont); aFont = GetFont(); aFont.SetFillColor( rCol ); m_pOutWin->SetFont( aFont ); m_pTextEngine->SetFont( aFont ); m_aSyntaxIdle.SetInvokeHandler( LINK( this, SwSrcEditWindow, SyntaxTimerHdl ) ); m_pTextEngine->EnableUndo( true ); m_pTextEngine->SetUpdateMode( true ); m_pTextView->ShowCursor(); InitScrollBars(); StartListening( *m_pTextEngine ); SfxBindings& rBind = GetSrcView()->GetViewFrame().GetBindings(); rBind.Invalidate( SID_TABLE_CELL ); } void SwSrcEditWindow::SetScrollBarRanges() { // Extra method, not InitScrollBars, because also for TextEngine events. m_pHScrollbar->SetRange( Range( 0, m_nCurTextWidth-1 ) ); m_pVScrollbar->SetRange( Range(0, m_pTextEngine->GetTextHeight()-1) ); } void SwSrcEditWindow::InitScrollBars() { SetScrollBarRanges(); Size aOutSz( m_pOutWin->GetOutputSizePixel() ); m_pVScrollbar->SetVisibleSize( aOutSz.Height() ); m_pVScrollbar->SetPageSize( aOutSz.Height() * 8 / 10 ); m_pVScrollbar->SetLineSize( m_pOutWin->GetTextHeight() ); m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() ); m_pHScrollbar->SetVisibleSize( aOutSz.Width() ); m_pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 ); m_pHScrollbar->SetLineSize( m_pOutWin->GetTextWidth(OUString('x')) ); m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() ); } IMPL_LINK_NOARG(SwSrcEditWindow, HorzScrollHdl, weld::Scrollbar&, void) { tools::Long nDiff = m_pTextView->GetStartDocPos().X() - m_pHScrollbar->GetThumbPos(); GetTextView()->Scroll( nDiff, 0 ); m_pTextView->ShowCursor( false ); m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() ); GetSrcView()->GetViewFrame().GetBindings().Invalidate( SID_TABLE_CELL ); } IMPL_LINK_NOARG(SwSrcEditWindow, VertScrollHdl, weld::Scrollbar&, void) { tools::Long nDiff = m_pTextView->GetStartDocPos().Y() - m_pVScrollbar->GetThumbPos(); GetTextView()->Scroll( 0, nDiff ); m_pTextView->ShowCursor( false ); m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() ); GetSrcView()->GetViewFrame().GetBindings().Invalidate( SID_TABLE_CELL ); } IMPL_LINK( SwSrcEditWindow, SyntaxTimerHdl, Timer*, pIdle, void ) { tools::Time aSyntaxCheckStart( tools::Time::SYSTEM ); SAL_WARN_IF(m_pTextView == nullptr, "sw", "No View yet, but syntax highlighting?!"); m_bHighlighting = true; sal_uInt16 nCount = 0; // at first the region around the cursor is processed TextSelection aSel = m_pTextView->GetSelection(); sal_uInt16 nCur = o3tl::narrowing(aSel.GetStart().GetPara()); if(nCur > 40) nCur -= 40; else nCur = 0; if(!m_aSyntaxLineTable.empty()) for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++) { if(m_aSyntaxLineTable.find(nCur) != m_aSyntaxLineTable.end()) { DoSyntaxHighlight( nCur ); m_aSyntaxLineTable.erase( nCur ); nCount++; if(m_aSyntaxLineTable.empty()) break; if((tools::Time( tools::Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME ) { break; } } } // when there is still anything left by then, go on from the beginning while ( !m_aSyntaxLineTable.empty() && nCount < MAX_SYNTAX_HIGHLIGHT) { sal_uInt16 nLine = *m_aSyntaxLineTable.begin(); DoSyntaxHighlight( nLine ); m_aSyntaxLineTable.erase(nLine); nCount ++; if(tools::Time( tools::Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME) { break; } } if(!m_aSyntaxLineTable.empty() && !pIdle->IsActive()) pIdle->Start(); // SyntaxTimerHdl is called when text changed // => good opportunity to determine text width! tools::Long nPrevTextWidth = m_nCurTextWidth; m_nCurTextWidth = m_pTextEngine->CalcTextWidth() + 25; // small tolerance if ( m_nCurTextWidth != nPrevTextWidth ) SetScrollBarRanges(); m_bHighlighting = false; } void SwSrcEditWindow::DoSyntaxHighlight( sal_uInt16 nPara ) { // Because of DelayedSyntaxHighlight it could happen, // that the line doesn't exist anymore! if ( nPara >= m_pTextEngine->GetParagraphCount() ) return; bool bTempModified = IsModified(); m_pTextEngine->RemoveAttribs( nPara ); OUString aSource( m_pTextEngine->GetText( nPara ) ); m_pTextEngine->SetUpdateMode( false ); ImpDoHighlight( aSource, nPara ); TextView* pTmp = m_pTextEngine->GetActiveView(); pTmp->SetAutoScroll(false); m_pTextEngine->SetActiveView(nullptr); m_pTextEngine->SetUpdateMode( true ); m_pTextEngine->SetActiveView(pTmp); pTmp->SetAutoScroll(true); pTmp->ShowCursor( false/*pTmp->IsAutoScroll()*/ ); if(!bTempModified) ClearModifyFlag(); } void SwSrcEditWindow::ImpDoHighlight( std::u16string_view aSource, sal_uInt16 nLineOff ) { TextPortions aPortionList; lcl_Highlight(aSource, aPortionList); size_t nCount = aPortionList.size(); if ( !nCount ) return; TextPortion& rLast = aPortionList[nCount-1]; if ( rLast.nStart > rLast.nEnd ) // Only until Bug from MD is resolved { nCount--; aPortionList.pop_back(); if ( !nCount ) return; } { // Only blanks and tabs have to be attributed along. // When two identical attributes are placed consecutively, // it optimises the TextEngine. sal_uInt16 nLastEnd = 0; for ( size_t i = 0; i < nCount; i++ ) { TextPortion& r = aPortionList[i]; if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved continue; if ( r.nStart > nLastEnd ) { // Can I rely on the fact that all except blank and tab // are being highlighted?! r.nStart = nLastEnd; } nLastEnd = r.nEnd+1; if ( ( i == (nCount-1) ) && ( r.nEnd < aSource.size() ) ) r.nEnd = aSource.size(); } } for (TextPortion & r : aPortionList) { if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved continue; if(r.eType != svtools::HTMLSGML && r.eType != svtools::HTMLCOMMENT && r.eType != svtools::HTMLKEYWORD && r.eType != svtools::HTMLUNKNOWN) r.eType = svtools::HTMLUNKNOWN; Color aColor(SW_MOD()->GetColorConfig().GetColorValue(r.eType).nColor); m_pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLineOff, r.nStart, r.nEnd+1 ); } } void SwSrcEditWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) { const TextHint* pTextHint = dynamic_cast(&rHint); if (!pTextHint) return; switch (pTextHint->GetId()) { case SfxHintId::TextViewScrolled: m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() ); m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() ); break; case SfxHintId::TextHeightChanged: if ( m_pTextEngine->GetTextHeight() < m_pOutWin->GetOutputSizePixel().Height() ) m_pTextView->Scroll( 0, m_pTextView->GetStartDocPos().Y() ); m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() ); SetScrollBarRanges(); break; case SfxHintId::TextParaInserted: case SfxHintId::TextParaContentChanged: if ( !m_bHighlighting ) { m_aSyntaxLineTable.insert( o3tl::narrowing(pTextHint->GetValue()) ); m_aSyntaxIdle.Start(); } break; default: break; } } void SwSrcEditWindow::ImplInvalidate(const vcl::Region* pRegion, InvalidateFlags nFlags) { m_pOutWin->Invalidate(); Window::ImplInvalidate(pRegion, nFlags); } void SwSrcEditWindow::Command( const CommandEvent& rCEvt ) { switch(rCEvt.GetCommand()) { case CommandEventId::Wheel: case CommandEventId::StartAutoScroll: case CommandEventId::AutoScroll: { const CommandWheelData* pWData = rCEvt.GetWheelData(); if( !pWData || CommandWheelMode::ZOOM != pWData->GetMode() ) HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar ); } break; default: Window::Command(rCEvt); } } void SwSrcEditWindow::HandleWheelCommand( const CommandEvent& rCEvt ) { m_pTextView->Command(rCEvt); HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar ); } void SwSrcEditWindow::GetFocus() { if (m_pOutWin) m_pOutWin->GrabFocus(); } static bool lcl_GetLanguagesForEncoding(rtl_TextEncoding eEnc, LanguageType aLanguages[]) { switch(eEnc) { case RTL_TEXTENCODING_UTF7 : case RTL_TEXTENCODING_UTF8 : // don#t fill - all LANGUAGE_SYSTEM means unicode font has to be used break; case RTL_TEXTENCODING_ISO_8859_3: case RTL_TEXTENCODING_ISO_8859_1 : case RTL_TEXTENCODING_MS_1252 : case RTL_TEXTENCODING_APPLE_ROMAN : case RTL_TEXTENCODING_IBM_850 : case RTL_TEXTENCODING_ISO_8859_14 : case RTL_TEXTENCODING_ISO_8859_15 : //fill with western languages aLanguages[0] = LANGUAGE_GERMAN; aLanguages[1] = LANGUAGE_FRENCH; aLanguages[2] = LANGUAGE_ITALIAN; aLanguages[3] = LANGUAGE_SPANISH; break; case RTL_TEXTENCODING_IBM_865 : //scandinavian aLanguages[0] = LANGUAGE_FINNISH; aLanguages[1] = LANGUAGE_NORWEGIAN; aLanguages[2] = LANGUAGE_SWEDISH; aLanguages[3] = LANGUAGE_DANISH; break; case RTL_TEXTENCODING_ISO_8859_10 : case RTL_TEXTENCODING_ISO_8859_13 : case RTL_TEXTENCODING_ISO_8859_2 : case RTL_TEXTENCODING_IBM_852 : case RTL_TEXTENCODING_MS_1250 : case RTL_TEXTENCODING_APPLE_CENTEURO : aLanguages[0] = LANGUAGE_POLISH; aLanguages[1] = LANGUAGE_CZECH; aLanguages[2] = LANGUAGE_HUNGARIAN; aLanguages[3] = LANGUAGE_SLOVAK; break; case RTL_TEXTENCODING_ISO_8859_4 : case RTL_TEXTENCODING_IBM_775 : case RTL_TEXTENCODING_MS_1257 : aLanguages[0] = LANGUAGE_LATVIAN ; aLanguages[1] = LANGUAGE_LITHUANIAN; aLanguages[2] = LANGUAGE_ESTONIAN ; break; case RTL_TEXTENCODING_IBM_863 : aLanguages[0] = LANGUAGE_FRENCH_CANADIAN; break; case RTL_TEXTENCODING_APPLE_FARSI : aLanguages[0] = LANGUAGE_FARSI; break; case RTL_TEXTENCODING_APPLE_ROMANIAN:aLanguages[0] = LANGUAGE_ROMANIAN; break; case RTL_TEXTENCODING_IBM_861 : case RTL_TEXTENCODING_APPLE_ICELAND : aLanguages[0] = LANGUAGE_ICELANDIC; break; case RTL_TEXTENCODING_APPLE_CROATIAN:aLanguages[0] = LANGUAGE_CROATIAN; break; case RTL_TEXTENCODING_IBM_437 : case RTL_TEXTENCODING_ASCII_US : aLanguages[0] = LANGUAGE_ENGLISH; break; case RTL_TEXTENCODING_IBM_862 : case RTL_TEXTENCODING_MS_1255 : case RTL_TEXTENCODING_APPLE_HEBREW : case RTL_TEXTENCODING_ISO_8859_8 : aLanguages[0] = LANGUAGE_HEBREW; break; case RTL_TEXTENCODING_IBM_857 : case RTL_TEXTENCODING_MS_1254 : case RTL_TEXTENCODING_APPLE_TURKISH: case RTL_TEXTENCODING_ISO_8859_9 : aLanguages[0] = LANGUAGE_TURKISH; break; case RTL_TEXTENCODING_IBM_860 : aLanguages[0] = LANGUAGE_PORTUGUESE; break; case RTL_TEXTENCODING_IBM_869 : case RTL_TEXTENCODING_MS_1253 : case RTL_TEXTENCODING_APPLE_GREEK : case RTL_TEXTENCODING_ISO_8859_7 : case RTL_TEXTENCODING_IBM_737 : aLanguages[0] = LANGUAGE_GREEK; break; case RTL_TEXTENCODING_KOI8_R : case RTL_TEXTENCODING_ISO_8859_5 : case RTL_TEXTENCODING_IBM_855 : case RTL_TEXTENCODING_MS_1251 : case RTL_TEXTENCODING_IBM_866 : case RTL_TEXTENCODING_APPLE_CYRILLIC : aLanguages[0] = LANGUAGE_RUSSIAN; break; case RTL_TEXTENCODING_APPLE_UKRAINIAN: case RTL_TEXTENCODING_KOI8_U: aLanguages[0] = LANGUAGE_UKRAINIAN; break; case RTL_TEXTENCODING_IBM_864 : case RTL_TEXTENCODING_MS_1256 : case RTL_TEXTENCODING_ISO_8859_6 : case RTL_TEXTENCODING_APPLE_ARABIC : aLanguages[0] = LANGUAGE_ARABIC_SAUDI_ARABIA; break; case RTL_TEXTENCODING_APPLE_CHINTRAD : case RTL_TEXTENCODING_MS_950 : case RTL_TEXTENCODING_GBT_12345 : case RTL_TEXTENCODING_BIG5 : case RTL_TEXTENCODING_EUC_TW : case RTL_TEXTENCODING_BIG5_HKSCS : aLanguages[0] = LANGUAGE_CHINESE_TRADITIONAL; break; case RTL_TEXTENCODING_EUC_JP : case RTL_TEXTENCODING_ISO_2022_JP : case RTL_TEXTENCODING_JIS_X_0201 : case RTL_TEXTENCODING_JIS_X_0208 : case RTL_TEXTENCODING_JIS_X_0212 : case RTL_TEXTENCODING_APPLE_JAPANESE : case RTL_TEXTENCODING_MS_932 : case RTL_TEXTENCODING_SHIFT_JIS : aLanguages[0] = LANGUAGE_JAPANESE; break; case RTL_TEXTENCODING_GB_2312 : case RTL_TEXTENCODING_MS_936 : case RTL_TEXTENCODING_GBK : case RTL_TEXTENCODING_GB_18030 : case RTL_TEXTENCODING_APPLE_CHINSIMP : case RTL_TEXTENCODING_EUC_CN : case RTL_TEXTENCODING_ISO_2022_CN : aLanguages[0] = LANGUAGE_CHINESE_SIMPLIFIED; break; case RTL_TEXTENCODING_APPLE_KOREAN : case RTL_TEXTENCODING_MS_949 : case RTL_TEXTENCODING_EUC_KR : case RTL_TEXTENCODING_ISO_2022_KR : case RTL_TEXTENCODING_MS_1361 : aLanguages[0] = LANGUAGE_KOREAN; break; case RTL_TEXTENCODING_APPLE_THAI : case RTL_TEXTENCODING_MS_874 : case RTL_TEXTENCODING_TIS_620 : aLanguages[0] = LANGUAGE_THAI; break; default: aLanguages[0] = Application::GetSettings().GetUILanguageTag().getLanguageType(); } return aLanguages[0] != LANGUAGE_SYSTEM; } void SwSrcEditWindow::SetFont() { OUString sFontName( officecfg::Office::Common::Font::SourceViewFont::FontName::get(). value_or(OUString())); if(sFontName.isEmpty()) { LanguageType aLanguages[5] = { LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM }; vcl::Font aFont; if(lcl_GetLanguagesForEncoding(m_eSourceEncoding, aLanguages)) { //TODO: check for multiple languages aFont = OutputDevice::GetDefaultFont(DefaultFontType::FIXED, aLanguages[0], GetDefaultFontFlags::NONE, GetOutDev()); } else aFont = OutputDevice::GetDefaultFont(DefaultFontType::SANS_UNICODE, Application::GetSettings().GetLanguageTag().getLanguageType(), GetDefaultFontFlags::NONE, GetOutDev()); sFontName = aFont.GetFamilyName(); } const SvxFontListItem* pFontListItem = static_cast(m_pSrcView->GetDocShell()->GetItem( SID_ATTR_CHAR_FONTLIST )); const FontList* pList = pFontListItem->GetFontList(); FontMetric aFontMetric = pList->Get(sFontName,WEIGHT_NORMAL, ITALIC_NONE); const vcl::Font& rFont = GetTextEngine()->GetFont(); vcl::Font aFont(aFontMetric); Size aSize(rFont.GetFontSize()); //font height is stored in point and set in twip aSize.setHeight( officecfg::Office::Common::Font::SourceViewFont::FontHeight::get() * 20 ); aFont.SetFontSize(m_pOutWin->LogicToPixel(aSize, MapMode(MapUnit::MapTwip))); GetTextEngine()->SetFont( aFont ); m_pOutWin->SetFont(aFont); } void SwSrcEditWindow::SetTextEncoding(rtl_TextEncoding eEncoding) { m_eSourceEncoding = eEncoding; SetFont(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */