diff options
Diffstat (limited to 'sw/source/uibase/docvw/srcedtw.cxx')
-rw-r--r-- | sw/source/uibase/docvw/srcedtw.cxx | 993 |
1 files changed, 993 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/srcedtw.cxx b/sw/source/uibase/docvw/srcedtw.cxx new file mode 100644 index 000000000000..353780925449 --- /dev/null +++ b/sw/source/uibase/docvw/srcedtw.cxx @@ -0,0 +1,993 @@ +/* -*- 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 <sal/config.h> + +#include <hintids.hxx> +#include <cmdid.h> + +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertiesChangeListener.hpp> +#include <cppuhelper/implbase1.hxx> +#include <officecfg/Office/Common.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <vcl/textview.hxx> +#include <svx/svxids.hrc> +#include <vcl/scrbar.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/app.hxx> +#include <svtools/htmltokn.h> +#include <vcl/txtattr.hxx> +#include <vcl/settings.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/flstitem.hxx> +#include <vcl/metric.hxx> +#include <svtools/ctrltool.hxx> +#include <tools/time.hxx> +#include <swmodule.hxx> +#include <docsh.hxx> +#include <srcview.hxx> +#include <helpid.h> +#include <deque> + +struct SwTextPortion +{ + sal_uInt16 nLine; + sal_uInt16 nStart, nEnd; + svtools::ColorConfigEntry eType; +}; + +#define MAX_SYNTAX_HIGHLIGHT 20 +#define MAX_HIGHLIGHTTIME 200 +#define SYNTAX_HIGHLIGHT_TIMEOUT 200 + +typedef std::deque<SwTextPortion> SwTextPortions; + +static void lcl_Highlight(const OUString& rSource, SwTextPortions& 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_uInt16 nStrLen = rSource.getLength(); + sal_uInt16 nInsert = 0; // number of inserted portions + sal_uInt16 nActPos = 0; // position, where '<' was found + sal_uInt16 nOffset = 0; // Offset of nActPos to '<' + sal_uInt16 nPortStart = USHRT_MAX; // for the TextPortion + sal_uInt16 nPortEnd = 0; + SwTextPortion aText; + while(nActPos < nStrLen) + { + svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN; + if((nActPos < nStrLen - 2) && (rSource[nActPos] == cOpenBracket)) + { + // insert 'empty' portion + if(nPortEnd < nActPos - 1 ) + { + aText.nLine = 0; + // 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 = rSource[nActPos + 1]; + sal_Unicode cFollowNext = rSource[nActPos + 2]; + if(cExclamation == cFollowFirst) + { + // "<!" SGML or comment + if(cMinus == cFollowNext && + nActPos < nStrLen - 3 && cMinus == rSource[nActPos + 3]) + { + eFoundType = svtools::HTMLCOMMENT; + } + else + eFoundType = svtools::HTMLSGML; + nPortStart = nActPos; + nPortEnd = nActPos + 1; + } + else if(cSlash == cFollowFirst) + { + // "</" ignore slash + nPortStart = nActPos; + nActPos++; + nOffset++; + } + if(svtools::HTMLUNKNOWN == eFoundType) + { + // now here a keyword could follow + sal_uInt16 nSrchPos = nActPos; + while(++nSrchPos < nStrLen - 1) + { + sal_Unicode cNext = rSource[nSrchPos]; + if( cNext == cSpace || + cNext == cTab || + cNext == cLF || + cNext == cCR) + break; + else if(cNext == cCloseBracket) + { + break; + } + } + if(nSrchPos > nActPos + 1) + { + // some string was found + OUString sToken = rSource.copy(nActPos + 1, nSrchPos - nActPos - 1 ); + sToken = sToken.toAsciiUpperCase(); + int nToken = ::GetHTMLToken(sToken); + if(nToken) + { + // Token was found + eFoundType = svtools::HTMLKEYWORD; + nPortEnd = nSrchPos; + nPortStart = nActPos; + } + else + { + // what was that? + SAL_WARN( + "sw.level2", + "Token " << sToken + << " not recognised!"); + } + + } + } + // now we still have to look for '>' + if(svtools::HTMLUNKNOWN != eFoundType) + { + bool bFound = false; + for(sal_uInt16 i = nPortEnd; i < nStrLen; i++) + if(cCloseBracket == rSource[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)) + { + SwTextPortion aTextPortion; + aTextPortion.nLine = 0; + aTextPortion.nStart = nPortStart + 1; + aTextPortion.nEnd = nPortEnd; + aTextPortion.eType = eFoundType; + aPortionList.push_back( aTextPortion ); + nInsert++; + eFoundType = svtools::HTMLUNKNOWN; + } + + } + } + nActPos++; + } + if(nInsert && nPortEnd < nActPos - 1) + { + aText.nLine = 0; + aText.nStart = nPortEnd + 1; + aText.nEnd = nActPos - 1; + aText.eType = svtools::HTMLUNKNOWN; + aPortionList.push_back( aText ); + nInsert++; + } +} + +class SwSrcEditWindow::ChangesListener: + public cppu::WeakImplHelper1< css::beans::XPropertiesChangeListener > +{ +public: + ChangesListener(SwSrcEditWindow & editor): editor_(editor) {} + +private: + virtual ~ChangesListener() {} + + virtual void SAL_CALL disposing(css::lang::EventObject const &) + throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + osl::MutexGuard g(editor_.mutex_); + editor_.notifier_.clear(); + } + + virtual void SAL_CALL propertiesChange( + css::uno::Sequence< css::beans::PropertyChangeEvent > const &) + throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + SolarMutexGuard g; + editor_.SetFont(); + } + + SwSrcEditWindow & editor_; +}; + +SwSrcEditWindow::SwSrcEditWindow( Window* pParent, SwSrcView* pParentView ) : + Window( pParent, WB_BORDER|WB_CLIPCHILDREN ), + + pTextEngine(0), + + pOutWin(0), + pHScrollbar(0), + pVScrollbar(0), + + pSrcView(pParentView), + + nCurTextWidth(0), + nStartLine(USHRT_MAX), + eSourceEncoding(osl_getThreadTextEncoding()), + bDoSyntaxHighlight(true), + bHighlighting(false) +{ + 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: + listener_ = new ChangesListener(*this); + css::uno::Reference< css::beans::XMultiPropertySet > n( + officecfg::Office::Common::Font::SourceViewFont::get(), + css::uno::UNO_QUERY_THROW); + { + osl::MutexGuard g(mutex_); + notifier_ = n; + } + css::uno::Sequence< OUString > s(2); + s[0] = "FontHeight"; + s[1] = "FontName"; + n->addPropertiesChangeListener(s, listener_.get()); +} + + SwSrcEditWindow::~SwSrcEditWindow() +{ + css::uno::Reference< css::beans::XMultiPropertySet > n; + { + osl::MutexGuard g(mutex_); + n = notifier_; + } + if (n.is()) { + n->removePropertiesChangeListener(listener_.get()); + } + aSyntaxIdleTimer.Stop(); + if ( pTextEngine ) + { + EndListening( *pTextEngine ); + pTextEngine->RemoveView( pTextView ); + + delete pHScrollbar; + delete pVScrollbar; + + delete pTextView; + delete pTextEngine; + } + delete pOutWin; +} + +void SwSrcEditWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + switch ( rDCEvt.GetType() ) + { + case DATACHANGED_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() & SETTINGS_STYLE ) + Resize(); + break; + } +} + +void SwSrcEditWindow::Resize() +{ + // ScrollBars, etc. happens in Adjust... + if ( pTextView ) + { + long nVisY = pTextView->GetStartDocPos().Y(); + pTextView->ShowCursor(); + Size aOutSz( GetOutputSizePixel() ); + long nMaxVisAreaStart = pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height(); + if ( nMaxVisAreaStart < 0 ) + nMaxVisAreaStart = 0; + if ( pTextView->GetStartDocPos().Y() > nMaxVisAreaStart ) + { + Point aStartDocPos( pTextView->GetStartDocPos() ); + aStartDocPos.Y() = nMaxVisAreaStart; + pTextView->SetStartDocPos( aStartDocPos ); + pTextView->ShowCursor(); + } + long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize(); + Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd ); + Point aScrollPos(0, aOutSz.Height() - nScrollStd); + + pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); + + aScrollSz.Width() = aScrollSz.Height(); + aScrollSz.Height() = aOutSz.Height(); + aScrollPos = Point(aOutSz.Width() - nScrollStd, 0); + + pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); + aOutSz.Width() -= nScrollStd; + aOutSz.Height() -= nScrollStd; + pOutWin->SetOutputSizePixel(aOutSz); + InitScrollBars(); + + // set line in first Resize + if(USHRT_MAX != nStartLine) + { + if(nStartLine < pTextEngine->GetParagraphCount()) + { + TextSelection aSel(TextPaM( nStartLine, 0 ), TextPaM( nStartLine, 0x0 )); + pTextView->SetSelection(aSel); + pTextView->ShowCursor(); + } + nStartLine = USHRT_MAX; + } + + if ( nVisY != pTextView->GetStartDocPos().Y() ) + Invalidate(); + } + +} + +void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + switch( rDCEvt.GetType() ) + { + case DATACHANGED_SETTINGS: + // query settings + if( rDCEvt.GetFlags() & SETTINGS_STYLE ) + { + const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); + SetBackground( rCol ); + Font aFont( pTextView->GetTextEngine()->GetFont() ); + aFont.SetFillColor( rCol ); + pTextView->GetTextEngine()->SetFont( aFont ); + } + break; + } +} + +void TextViewOutWin::MouseMove( const MouseEvent &rEvt ) +{ + if ( pTextView ) + pTextView->MouseMove( rEvt ); +} + +void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt ) +{ + if ( pTextView ) + { + pTextView->MouseButtonUp( rEvt ); + SfxBindings& rBindings = ((SwSrcEditWindow*)GetParent())->GetSrcView()->GetViewFrame()->GetBindings(); + rBindings.Invalidate( SID_TABLE_CELL ); + rBindings.Invalidate( SID_CUT ); + rBindings.Invalidate( SID_COPY ); + } +} + +void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt ) +{ + GrabFocus(); + if ( pTextView ) + pTextView->MouseButtonDown( rEvt ); +} + +void TextViewOutWin::Command( const CommandEvent& rCEvt ) +{ + switch(rCEvt.GetCommand()) + { + case COMMAND_CONTEXTMENU: + ((SwSrcEditWindow*)GetParent())->GetSrcView()->GetViewFrame()-> + GetDispatcher()->ExecutePopup(); + break; + case COMMAND_WHEEL: + case COMMAND_STARTAUTOSCROLL: + case COMMAND_AUTOSCROLL: + { + const CommandWheelData* pWData = rCEvt.GetWheelData(); + if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() ) + { + ((SwSrcEditWindow*)GetParent())->HandleWheelCommand( rCEvt ); + } + } + break; + + default: + if ( pTextView ) + pTextView->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +void TextViewOutWin::KeyInput( const KeyEvent& rKEvt ) +{ + bool bDone = false; + SwSrcEditWindow* pSrcEditWin = (SwSrcEditWindow*)GetParent(); + bool bChange = !pSrcEditWin->IsReadonly() || !TextEngine::DoesKeyChangeText( rKEvt ); + if(bChange) + bDone = pTextView->KeyInput( rKEvt ); + + SfxBindings& rBindings = ((SwSrcEditWindow*)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( const Rectangle& rRect ) +{ + pTextView->Paint( rRect ); +} + +void SwSrcEditWindow::CreateTextEngine() +{ + const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); + pOutWin = new TextViewOutWin(this, 0); + pOutWin->SetBackground(Wallpaper(rCol)); + pOutWin->SetPointer(Pointer(POINTER_TEXT)); + pOutWin->Show(); + + // create Scrollbars + pHScrollbar = new ScrollBar(this, WB_3DLOOK |WB_HSCROLL|WB_DRAG); + pHScrollbar->EnableRTL( false ); // --- RTL --- no mirroring for scrollbars + pHScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, ScrollHdl)); + pHScrollbar->Show(); + + pVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG); + pVScrollbar->EnableRTL( false ); // --- RTL --- no mirroring for scrollbars + pVScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, ScrollHdl)); + pHScrollbar->EnableDrag(); + pVScrollbar->Show(); + + pTextEngine = new ExtTextEngine; + pTextView = new ExtTextView( pTextEngine, pOutWin ); + pTextView->SetAutoIndentMode(true); + pOutWin->SetTextView(pTextView); + + pTextEngine->SetUpdateMode( false ); + pTextEngine->InsertView( pTextView ); + + Font aFont; + aFont.SetTransparent( false ); + aFont.SetFillColor( rCol ); + SetPointFont( aFont ); + aFont = GetFont(); + aFont.SetFillColor( rCol ); + pOutWin->SetFont( aFont ); + pTextEngine->SetFont( aFont ); + + aSyntaxIdleTimer.SetTimeout( SYNTAX_HIGHLIGHT_TIMEOUT ); + aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, SwSrcEditWindow, SyntaxTimerHdl ) ); + + pTextEngine->EnableUndo( true ); + pTextEngine->SetUpdateMode( true ); + + pTextView->ShowCursor( true, true ); + InitScrollBars(); + StartListening( *pTextEngine ); + + SfxBindings& rBind = GetSrcView()->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_TABLE_CELL ); +} + +void SwSrcEditWindow::SetScrollBarRanges() +{ + // Extra method, not InitScrollBars, because also for TextEngine events. + + pHScrollbar->SetRange( Range( 0, nCurTextWidth-1 ) ); + pVScrollbar->SetRange( Range(0, pTextEngine->GetTextHeight()-1) ); +} + +void SwSrcEditWindow::InitScrollBars() +{ + SetScrollBarRanges(); + + Size aOutSz( pOutWin->GetOutputSizePixel() ); + pVScrollbar->SetVisibleSize( aOutSz.Height() ); + pVScrollbar->SetPageSize( aOutSz.Height() * 8 / 10 ); + pVScrollbar->SetLineSize( pOutWin->GetTextHeight() ); + pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); + pHScrollbar->SetVisibleSize( aOutSz.Width() ); + pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 ); + pHScrollbar->SetLineSize( pOutWin->GetTextWidth(OUString('x')) ); + pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() ); + +} + +IMPL_LINK(SwSrcEditWindow, ScrollHdl, ScrollBar*, pScroll) +{ + if(pScroll == pVScrollbar) + { + long nDiff = pTextView->GetStartDocPos().Y() - pScroll->GetThumbPos(); + GetTextView()->Scroll( 0, nDiff ); + pTextView->ShowCursor( false, true ); + pScroll->SetThumbPos( pTextView->GetStartDocPos().Y() ); + } + else + { + long nDiff = pTextView->GetStartDocPos().X() - pScroll->GetThumbPos(); + GetTextView()->Scroll( nDiff, 0 ); + pTextView->ShowCursor( false, true ); + pScroll->SetThumbPos( pTextView->GetStartDocPos().X() ); + } + GetSrcView()->GetViewFrame()->GetBindings().Invalidate( SID_TABLE_CELL ); + return 0; +} + +IMPL_LINK( SwSrcEditWindow, SyntaxTimerHdl, Timer *, pTimer ) +{ + Time aSyntaxCheckStart( Time::SYSTEM ); + SAL_WARN_IF(pTextView == 0, "sw", "No View yet, but syntax highlighting?!"); + + bHighlighting = true; + sal_uInt16 nCount = 0; + // at first the region around the cursor is processed + TextSelection aSel = pTextView->GetSelection(); + sal_uInt16 nCur = (sal_uInt16)aSel.GetStart().GetPara(); + if(nCur > 40) + nCur -= 40; + else + nCur = 0; + if(!aSyntaxLineTable.empty()) + for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++) + { + if(aSyntaxLineTable.find(nCur) != aSyntaxLineTable.end()) + { + DoSyntaxHighlight( nCur ); + aSyntaxLineTable.erase( nCur ); + nCount++; + if(aSyntaxLineTable.empty()) + break; + if((Time( Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME ) + { + pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT ); + break; + } + } + } + + // when there is still anything left by then, go on from the beginning + while ( !aSyntaxLineTable.empty() && nCount < MAX_SYNTAX_HIGHLIGHT) + { + sal_uInt16 nLine = *aSyntaxLineTable.begin(); + DoSyntaxHighlight( nLine ); + aSyntaxLineTable.erase(nLine); + nCount ++; + if(Time( Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME) + { + pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT ); + break; + } + } + + if(!aSyntaxLineTable.empty() && !pTimer->IsActive()) + pTimer->Start(); + // SyntaxTimerHdl is called when text changed + // => good opportunity to determine text width! + long nPrevTextWidth = nCurTextWidth; + nCurTextWidth = pTextEngine->CalcTextWidth() + 25; // kleine Toleranz + if ( nCurTextWidth != nPrevTextWidth ) + SetScrollBarRanges(); + bHighlighting = false; + + return 0; +} + +void SwSrcEditWindow::DoSyntaxHighlight( sal_uInt16 nPara ) +{ + // Because of DelayedSyntaxHighlight it could happen, + // that the line doesn't exist anymore! + if ( nPara < pTextEngine->GetParagraphCount() ) + { + bool bTempModified = IsModified(); + pTextEngine->RemoveAttribs( nPara, true ); + OUString aSource( pTextEngine->GetText( nPara ) ); + pTextEngine->SetUpdateMode( false ); + ImpDoHighlight( aSource, nPara ); + TextView* pTmp = pTextEngine->GetActiveView(); + pTmp->SetAutoScroll(false); + pTextEngine->SetActiveView(0); + pTextEngine->SetUpdateMode( true ); + pTextEngine->SetActiveView(pTmp); + pTmp->SetAutoScroll(true); + pTmp->ShowCursor( false/*pTmp->IsAutoScroll()*/ ); + + if(!bTempModified) + ClearModifyFlag(); + } +} + +void SwSrcEditWindow::DoDelayedSyntaxHighlight( sal_uInt16 nPara ) +{ + if ( !bHighlighting && bDoSyntaxHighlight ) + { + aSyntaxLineTable.insert( nPara ); + aSyntaxIdleTimer.Start(); + } +} + +void SwSrcEditWindow::ImpDoHighlight( const OUString& rSource, sal_uInt16 nLineOff ) +{ + SwTextPortions aPortionList; + lcl_Highlight(rSource, aPortionList); + + size_t nCount = aPortionList.size(); + if ( !nCount ) + return; + + SwTextPortion& 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++ ) + { + SwTextPortion& r = aPortionList[i]; + SAL_WARN_IF( + r.nLine != aPortionList[0].nLine, "sw.level2", + "multiple lines after all?"); + 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 < rSource.getLength() ) ) + r.nEnd = rSource.getLength(); + } + } + + for ( size_t i = 0; i < aPortionList.size(); i++ ) + { + SwTextPortion& r = aPortionList[i]; + 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((ColorData)SW_MOD()->GetColorConfig().GetColorValue((svtools::ColorConfigEntry)r.eType).nColor); + sal_uInt16 nLine = nLineOff+r.nLine; + pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLine, r.nStart, r.nEnd+1, true ); + } +} + +void SwSrcEditWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + if ( rHint.ISA( TextHint ) ) + { + const TextHint& rTextHint = (const TextHint&)rHint; + if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED ) + { + pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() ); + pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); + } + else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED ) + { + if ( (long)pTextEngine->GetTextHeight() < pOutWin->GetOutputSizePixel().Height() ) + pTextView->Scroll( 0, pTextView->GetStartDocPos().Y() ); + pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); + SetScrollBarRanges(); + } + else if( ( rTextHint.GetId() == TEXT_HINT_PARAINSERTED ) || + ( rTextHint.GetId() == TEXT_HINT_PARACONTENTCHANGED ) ) + { + DoDelayedSyntaxHighlight( (sal_uInt16)rTextHint.GetValue() ); + } + } +} + +void SwSrcEditWindow::Invalidate(sal_uInt16 ) +{ + pOutWin->Invalidate(); + Window::Invalidate(); + +} + +void SwSrcEditWindow::Command( const CommandEvent& rCEvt ) +{ + switch(rCEvt.GetCommand()) + { + case COMMAND_WHEEL: + case COMMAND_STARTAUTOSCROLL: + case COMMAND_AUTOSCROLL: + { + const CommandWheelData* pWData = rCEvt.GetWheelData(); + if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() ) + HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar ); + } + break; + default: + Window::Command(rCEvt); + } +} + +void SwSrcEditWindow::HandleWheelCommand( const CommandEvent& rCEvt ) +{ + pTextView->Command(rCEvt); + HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar ); +} + +void SwSrcEditWindow::GetFocus() +{ + 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(). + get_value_or(OUString())); + if(sFontName.isEmpty()) + { + LanguageType aLanguages[5] = + { + LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM + }; + Font aFont; + if(lcl_GetLanguagesForEncoding(eSourceEncoding, aLanguages)) + { + //TODO: check for multiple languages + aFont = OutputDevice::GetDefaultFont(DEFAULTFONT_FIXED, aLanguages[0], 0, this); + } + else + aFont = OutputDevice::GetDefaultFont(DEFAULTFONT_SANS_UNICODE, + Application::GetSettings().GetLanguageTag().getLanguageType(), 0, this); + sFontName = aFont.GetName(); + } + const SvxFontListItem* pFontListItem = + (const SvxFontListItem* )pSrcView->GetDocShell()->GetItem( SID_ATTR_CHAR_FONTLIST ); + const FontList* pList = pFontListItem->GetFontList(); + FontInfo aInfo = pList->Get(sFontName,WEIGHT_NORMAL, ITALIC_NONE); + + const Font& rFont = GetTextEngine()->GetFont(); + Font aFont(aInfo); + Size aSize(rFont.GetSize()); + //font height is stored in point and set in twip + aSize.Height() = + officecfg::Office::Common::Font::SourceViewFont::FontHeight::get() * 20; + aFont.SetSize(pOutWin->LogicToPixel(aSize, MAP_TWIP)); + GetTextEngine()->SetFont( aFont ); + pOutWin->SetFont(aFont); +} + +void SwSrcEditWindow::SetTextEncoding(rtl_TextEncoding eEncoding) +{ + eSourceEncoding = eEncoding; + SetFont(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |