Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / docvw / srcedtw.cxx
blob732553e2bbf4aa2fa8ce669ac662e23bc0511fe5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <hintids.hxx>
23 #include <cmdid.h>
25 #include <com/sun/star/beans/XMultiPropertySet.hpp>
26 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
27 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
28 #include <cppuhelper/implbase.hxx>
29 #include <officecfg/Office/Common.hxx>
30 #include <rtl/ustring.hxx>
31 #include <sal/log.hxx>
32 #include <vcl/commandevent.hxx>
33 #include <vcl/event.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/textview.hxx>
36 #include <vcl/ptrstyle.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <svtools/htmltokn.h>
40 #include <vcl/txtattr.hxx>
41 #include <vcl/settings.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <editeng/flstitem.hxx>
44 #include <vcl/metric.hxx>
45 #include <svtools/ctrltool.hxx>
46 #include <svtools/scrolladaptor.hxx>
47 #include <tools/time.hxx>
48 #include <swmodule.hxx>
49 #include <docsh.hxx>
50 #include <srcview.hxx>
51 #include <helpids.h>
52 #include <vector>
54 namespace
57 struct TextPortion
59 sal_uInt16 nStart, nEnd;
60 svtools::ColorConfigEntry eType;
65 #define MAX_SYNTAX_HIGHLIGHT 20
66 #define MAX_HIGHLIGHTTIME 200
68 typedef std::vector<TextPortion> TextPortions;
70 static void lcl_Highlight(std::u16string_view aSource, TextPortions& aPortionList)
72 const sal_Unicode cOpenBracket = '<';
73 const sal_Unicode cCloseBracket= '>';
74 const sal_Unicode cSlash = '/';
75 const sal_Unicode cExclamation = '!';
76 const sal_Unicode cMinus = '-';
77 const sal_Unicode cSpace = ' ';
78 const sal_Unicode cTab = 0x09;
79 const sal_Unicode cLF = 0x0a;
80 const sal_Unicode cCR = 0x0d;
82 const sal_Int32 nStrLen = aSource.size();
83 sal_Int32 nInsert = 0; // number of inserted portions
84 sal_Int32 nActPos = 0; // position, where '<' was found
85 sal_Int32 nPortStart = SAL_MAX_INT32; // for the TextPortion
86 sal_Int32 nPortEnd = 0;
87 TextPortion aText;
88 while(nActPos < nStrLen)
90 if((nActPos < nStrLen - 2) && (aSource[nActPos] == cOpenBracket))
92 svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN;
93 // insert 'empty' portion
94 if(nPortEnd < nActPos - 1 )
96 // don't move at the beginning
97 aText.nStart = nPortEnd;
98 if(nInsert)
99 aText.nStart += 1;
100 aText.nEnd = nActPos - 1;
101 aText.eType = svtools::HTMLUNKNOWN;
102 aPortionList.push_back( aText );
103 nInsert++;
105 sal_Unicode cFollowFirst = aSource[nActPos + 1];
106 sal_Unicode cFollowNext = aSource[nActPos + 2];
107 if(cExclamation == cFollowFirst)
109 // "<!" SGML or comment
110 if(cMinus == cFollowNext &&
111 nActPos < nStrLen - 3 && cMinus == aSource[nActPos + 3])
113 eFoundType = svtools::HTMLCOMMENT;
115 else
116 eFoundType = svtools::HTMLSGML;
117 nPortStart = nActPos;
118 nPortEnd = nActPos + 1;
120 else if(cSlash == cFollowFirst)
122 // "</" ignore slash
123 nPortStart = nActPos;
124 nActPos++;
126 if(svtools::HTMLUNKNOWN == eFoundType)
128 // now here a keyword could follow
129 sal_uInt16 nSrchPos = nActPos;
130 while(++nSrchPos < nStrLen - 1)
132 sal_Unicode cNext = aSource[nSrchPos];
133 if( cNext == cSpace ||
134 cNext == cTab ||
135 cNext == cLF ||
136 cNext == cCR)
137 break;
138 else if(cNext == cCloseBracket)
140 break;
143 if(nSrchPos > nActPos + 1)
145 // some string was found
146 OUString sToken( aSource.substr(nActPos + 1, nSrchPos - nActPos - 1 ) );
147 sToken = sToken.toAsciiUpperCase();
148 HtmlTokenId nToken = ::GetHTMLToken(sToken);
149 if(nToken != HtmlTokenId::NONE)
151 eFoundType = svtools::HTMLKEYWORD;
152 nPortEnd = nSrchPos;
153 nPortStart = nActPos;
155 else
156 SAL_WARN("sw", "HTML token " << sToken << " not recognised!");
159 // now we still have to look for '>'
160 if(svtools::HTMLUNKNOWN != eFoundType)
162 bool bFound = false;
163 for(sal_Int32 i = nPortEnd; i < nStrLen; i++)
164 if(cCloseBracket == aSource[i])
166 bFound = true;
167 nPortEnd = i;
168 break;
170 if(!bFound && (eFoundType == svtools::HTMLCOMMENT))
172 // comment without ending in this line
173 bFound = true;
174 nPortEnd = nStrLen - 1;
177 if(bFound ||(eFoundType == svtools::HTMLCOMMENT))
179 TextPortion aTextPortion;
180 aTextPortion.nStart = nPortStart + 1;
181 aTextPortion.nEnd = nPortEnd;
182 aTextPortion.eType = eFoundType;
183 aPortionList.push_back( aTextPortion );
184 nInsert++;
189 nActPos++;
191 if(nInsert && nPortEnd < nActPos - 1)
193 aText.nStart = nPortEnd + 1;
194 aText.nEnd = nActPos - 1;
195 aText.eType = svtools::HTMLUNKNOWN;
196 aPortionList.push_back( aText );
197 nInsert++;
201 class SwSrcEditWindow::ChangesListener:
202 public cppu::WeakImplHelper< css::beans::XPropertiesChangeListener >
204 public:
205 explicit ChangesListener(SwSrcEditWindow & editor): m_Editor(editor) {}
207 private:
208 virtual ~ChangesListener() override {}
210 virtual void SAL_CALL disposing(css::lang::EventObject const &) override
212 std::unique_lock g(m_Editor.mutex_);
213 m_Editor.m_xNotifier.clear();
216 virtual void SAL_CALL propertiesChange(
217 css::uno::Sequence< css::beans::PropertyChangeEvent > const &) override
219 SolarMutexGuard g;
220 m_Editor.SetFont();
223 SwSrcEditWindow & m_Editor;
226 SwSrcEditWindow::SwSrcEditWindow( vcl::Window* pParent, SwSrcView* pParentView ) :
227 Window( pParent, WB_BORDER|WB_CLIPCHILDREN ),
229 m_pOutWin(nullptr),
230 m_pHScrollbar(nullptr),
231 m_pVScrollbar(nullptr),
233 m_pSrcView(pParentView),
235 m_nCurTextWidth(0),
236 m_nStartLine(USHRT_MAX),
237 m_eSourceEncoding(osl_getThreadTextEncoding()),
238 m_bReadonly(false),
239 m_bHighlighting(false),
240 m_aSyntaxIdle("sw uibase SwSrcEditWindow Syntax")
242 SetHelpId(HID_SOURCE_EDITWIN);
243 CreateTextEngine();
245 // Using "this" in ctor is a little fishy, but should work here at least as
246 // long as there are no derivations:
247 m_xListener = new ChangesListener(*this);
248 css::uno::Reference< css::beans::XMultiPropertySet > n(
249 officecfg::Office::Common::Font::SourceViewFont::get(),
250 css::uno::UNO_QUERY_THROW);
252 std::unique_lock g(mutex_);
253 m_xNotifier = n;
255 n->addPropertiesChangeListener({ "FontHeight", "FontName" }, m_xListener);
258 SwSrcEditWindow::~SwSrcEditWindow()
260 disposeOnce();
263 void SwSrcEditWindow::dispose()
265 css::uno::Reference< css::beans::XMultiPropertySet > n;
267 std::unique_lock g(mutex_);
268 n = m_xNotifier;
270 if (n.is()) {
271 n->removePropertiesChangeListener(m_xListener);
273 m_aSyntaxIdle.Stop();
274 if ( m_pOutWin )
275 m_pOutWin->SetTextView( nullptr );
277 if ( m_pTextEngine )
279 EndListening( *m_pTextEngine );
280 m_pTextEngine->RemoveView( m_pTextView.get() );
282 m_pTextView.reset();
283 m_pTextEngine.reset();
285 m_pHScrollbar.disposeAndClear();
286 m_pVScrollbar.disposeAndClear();
287 m_pOutWin.disposeAndClear();
288 vcl::Window::dispose();
291 void SwSrcEditWindow::DataChanged( const DataChangedEvent& rDCEvt )
293 Window::DataChanged( rDCEvt );
295 switch ( rDCEvt.GetType() )
297 case DataChangedEventType::SETTINGS:
298 // newly rearrange ScrollBars or trigger Resize, because
299 // ScrollBar size could have changed. For this, in the
300 // Resize handler the size of ScrollBars has to be queried
301 // from the settings as well.
302 if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
303 Resize();
304 break;
305 default: break;
309 void SwSrcEditWindow::Resize()
311 // ScrollBars, etc. happens in Adjust...
312 if ( !m_pTextView )
313 return;
315 tools::Long nVisY = m_pTextView->GetStartDocPos().Y();
316 m_pTextView->ShowCursor();
317 Size aOutSz( GetOutputSizePixel() );
318 tools::Long nMaxVisAreaStart = m_pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height();
319 if ( nMaxVisAreaStart < 0 )
320 nMaxVisAreaStart = 0;
321 if ( m_pTextView->GetStartDocPos().Y() > nMaxVisAreaStart )
323 Point aStartDocPos( m_pTextView->GetStartDocPos() );
324 aStartDocPos.setY( nMaxVisAreaStart );
325 m_pTextView->SetStartDocPos( aStartDocPos );
326 m_pTextView->ShowCursor();
328 tools::Long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize();
329 Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd );
330 Point aScrollPos(0, aOutSz.Height() - nScrollStd);
332 m_pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz);
334 aScrollSz.setWidth( aScrollSz.Height() );
335 aScrollSz.setHeight( aOutSz.Height() );
336 aScrollPos = Point(aOutSz.Width() - nScrollStd, 0);
338 m_pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz);
339 aOutSz.AdjustWidth( -nScrollStd );
340 aOutSz.AdjustHeight( -nScrollStd );
341 m_pOutWin->SetOutputSizePixel(aOutSz);
342 InitScrollBars();
344 // set line in first Resize
345 if(USHRT_MAX != m_nStartLine)
347 if(m_nStartLine < m_pTextEngine->GetParagraphCount())
349 TextSelection aSel(TextPaM( m_nStartLine, 0 ), TextPaM( m_nStartLine, 0x0 ));
350 m_pTextView->SetSelection(aSel);
351 m_pTextView->ShowCursor();
353 m_nStartLine = USHRT_MAX;
356 if ( nVisY != m_pTextView->GetStartDocPos().Y() )
357 Invalidate();
362 void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt )
364 Window::DataChanged( rDCEvt );
366 switch( rDCEvt.GetType() )
368 case DataChangedEventType::SETTINGS:
369 // query settings
370 if( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
372 const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor();
373 SetBackground( rCol );
374 vcl::Font aFont( m_pTextView->GetTextEngine()->GetFont() );
375 aFont.SetFillColor( rCol );
376 m_pTextView->GetTextEngine()->SetFont( aFont );
378 break;
379 default: break;
383 void TextViewOutWin::MouseMove( const MouseEvent &rEvt )
385 if ( m_pTextView )
386 m_pTextView->MouseMove( rEvt );
389 void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt )
391 if ( m_pTextView )
393 m_pTextView->MouseButtonUp( rEvt );
394 SfxViewFrame& rFrame = static_cast<SwSrcEditWindow*>(GetParent())->GetSrcView()->GetViewFrame();
395 SfxBindings& rBindings = rFrame.GetBindings();
396 rBindings.Invalidate( SID_TABLE_CELL );
397 rBindings.Invalidate( SID_CUT );
398 rBindings.Invalidate( SID_COPY );
402 void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt )
404 GrabFocus();
405 if ( m_pTextView )
406 m_pTextView->MouseButtonDown( rEvt );
409 void TextViewOutWin::Command( const CommandEvent& rCEvt )
411 switch(rCEvt.GetCommand())
413 case CommandEventId::ContextMenu:
414 SfxDispatcher::ExecutePopup();
415 break;
416 case CommandEventId::Wheel:
417 case CommandEventId::StartAutoScroll:
418 case CommandEventId::AutoScroll:
420 const CommandWheelData* pWData = rCEvt.GetWheelData();
421 if( !pWData || CommandWheelMode::ZOOM != pWData->GetMode() )
423 static_cast<SwSrcEditWindow*>(GetParent())->HandleWheelCommand( rCEvt );
426 break;
428 default:
429 if ( m_pTextView )
430 m_pTextView->Command( rCEvt );
431 else
432 Window::Command(rCEvt);
436 void TextViewOutWin::KeyInput( const KeyEvent& rKEvt )
438 bool bDone = false;
439 SwSrcEditWindow* pSrcEditWin = static_cast<SwSrcEditWindow*>(GetParent());
440 bool bChange = !pSrcEditWin->IsReadonly() || !TextEngine::DoesKeyChangeText( rKEvt );
441 if(bChange)
442 bDone = m_pTextView->KeyInput( rKEvt );
444 SfxBindings& rBindings = static_cast<SwSrcEditWindow*>(GetParent())->GetSrcView()->GetViewFrame().GetBindings();
445 if ( !bDone )
447 if ( !SfxViewShell::Current()->KeyInput( rKEvt ) )
448 Window::KeyInput( rKEvt );
450 else
452 rBindings.Invalidate( SID_TABLE_CELL );
453 if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR )
454 rBindings.Update( SID_BASICIDE_STAT_POS );
455 if (pSrcEditWin->GetTextEngine()->IsModified() )
457 rBindings.Invalidate( SID_SAVEDOC );
458 rBindings.Invalidate( SID_DOC_MODIFIED );
460 if( rKEvt.GetKeyCode().GetCode() == KEY_INSERT )
461 rBindings.Invalidate( SID_ATTR_INSERT );
464 rBindings.Invalidate( SID_CUT );
465 rBindings.Invalidate( SID_COPY );
467 SwDocShell* pDocShell = pSrcEditWin->GetSrcView()->GetDocShell();
468 if(pSrcEditWin->GetTextEngine()->IsModified())
470 pDocShell->SetModified();
474 void TextViewOutWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
476 m_pTextView->Paint(rRenderContext, rRect);
479 void SwSrcEditWindow::CreateTextEngine()
481 // FIXME RenderContext
483 const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor();
484 m_pOutWin = VclPtr<TextViewOutWin>::Create(this, 0);
485 m_pOutWin->SetBackground(Wallpaper(rCol));
486 m_pOutWin->SetPointer(PointerStyle::Text);
487 m_pOutWin->Show();
489 // create Scrollbars
490 m_pHScrollbar = VclPtr<ScrollAdaptor>::Create(this, true);
491 m_pHScrollbar->EnableRTL( false );
492 m_pHScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, HorzScrollHdl));
493 m_pHScrollbar->Show();
495 m_pVScrollbar = VclPtr<ScrollAdaptor>::Create(this, false);
496 m_pVScrollbar->EnableRTL( false );
497 m_pVScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, VertScrollHdl));
498 m_pVScrollbar->Show();
500 m_pTextEngine.reset(new ExtTextEngine);
501 m_pTextView.reset(new TextView( m_pTextEngine.get(), m_pOutWin ));
502 m_pTextView->SetAutoIndentMode(true);
503 m_pOutWin->SetTextView(m_pTextView.get());
505 m_pTextEngine->SetUpdateMode( false );
506 m_pTextEngine->InsertView( m_pTextView.get() );
508 vcl::Font aFont;
509 aFont.SetTransparent( false );
510 aFont.SetFillColor( rCol );
511 SetPointFont(*GetOutDev(), aFont);
512 aFont = GetFont();
513 aFont.SetFillColor( rCol );
514 m_pOutWin->SetFont( aFont );
515 m_pTextEngine->SetFont( aFont );
517 m_aSyntaxIdle.SetInvokeHandler( LINK( this, SwSrcEditWindow, SyntaxTimerHdl ) );
519 m_pTextEngine->EnableUndo( true );
520 m_pTextEngine->SetUpdateMode( true );
522 m_pTextView->ShowCursor();
523 InitScrollBars();
524 StartListening( *m_pTextEngine );
526 SfxBindings& rBind = GetSrcView()->GetViewFrame().GetBindings();
527 rBind.Invalidate( SID_TABLE_CELL );
530 void SwSrcEditWindow::SetScrollBarRanges()
532 // Extra method, not InitScrollBars, because also for TextEngine events.
534 m_pHScrollbar->SetRange( Range( 0, m_nCurTextWidth-1 ) );
535 m_pVScrollbar->SetRange( Range(0, m_pTextEngine->GetTextHeight()-1) );
538 void SwSrcEditWindow::InitScrollBars()
540 SetScrollBarRanges();
542 Size aOutSz( m_pOutWin->GetOutputSizePixel() );
543 m_pVScrollbar->SetVisibleSize( aOutSz.Height() );
544 m_pVScrollbar->SetPageSize( aOutSz.Height() * 8 / 10 );
545 m_pVScrollbar->SetLineSize( m_pOutWin->GetTextHeight() );
546 m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
547 m_pHScrollbar->SetVisibleSize( aOutSz.Width() );
548 m_pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 );
549 m_pHScrollbar->SetLineSize( m_pOutWin->GetTextWidth(OUString('x')) );
550 m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() );
554 IMPL_LINK_NOARG(SwSrcEditWindow, HorzScrollHdl, weld::Scrollbar&, void)
556 tools::Long nDiff = m_pTextView->GetStartDocPos().X() - m_pHScrollbar->GetThumbPos();
557 GetTextView()->Scroll( nDiff, 0 );
558 m_pTextView->ShowCursor( false );
559 m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() );
560 GetSrcView()->GetViewFrame().GetBindings().Invalidate( SID_TABLE_CELL );
563 IMPL_LINK_NOARG(SwSrcEditWindow, VertScrollHdl, weld::Scrollbar&, void)
565 tools::Long nDiff = m_pTextView->GetStartDocPos().Y() - m_pVScrollbar->GetThumbPos();
566 GetTextView()->Scroll( 0, nDiff );
567 m_pTextView->ShowCursor( false );
568 m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
569 GetSrcView()->GetViewFrame().GetBindings().Invalidate( SID_TABLE_CELL );
572 IMPL_LINK( SwSrcEditWindow, SyntaxTimerHdl, Timer*, pIdle, void )
574 tools::Time aSyntaxCheckStart( tools::Time::SYSTEM );
575 SAL_WARN_IF(m_pTextView == nullptr, "sw", "No View yet, but syntax highlighting?!");
577 m_bHighlighting = true;
578 sal_uInt16 nCount = 0;
579 // at first the region around the cursor is processed
580 TextSelection aSel = m_pTextView->GetSelection();
581 sal_uInt16 nCur = o3tl::narrowing<sal_uInt16>(aSel.GetStart().GetPara());
582 if(nCur > 40)
583 nCur -= 40;
584 else
585 nCur = 0;
586 if(!m_aSyntaxLineTable.empty())
587 for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++)
589 if(m_aSyntaxLineTable.find(nCur) != m_aSyntaxLineTable.end())
591 DoSyntaxHighlight( nCur );
592 m_aSyntaxLineTable.erase( nCur );
593 nCount++;
594 if(m_aSyntaxLineTable.empty())
595 break;
596 if((tools::Time( tools::Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME )
598 break;
603 // when there is still anything left by then, go on from the beginning
604 while ( !m_aSyntaxLineTable.empty() && nCount < MAX_SYNTAX_HIGHLIGHT)
606 sal_uInt16 nLine = *m_aSyntaxLineTable.begin();
607 DoSyntaxHighlight( nLine );
608 m_aSyntaxLineTable.erase(nLine);
609 nCount ++;
610 if(tools::Time( tools::Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME)
612 break;
616 if(!m_aSyntaxLineTable.empty() && !pIdle->IsActive())
617 pIdle->Start();
618 // SyntaxTimerHdl is called when text changed
619 // => good opportunity to determine text width!
620 tools::Long nPrevTextWidth = m_nCurTextWidth;
621 m_nCurTextWidth = m_pTextEngine->CalcTextWidth() + 25; // small tolerance
622 if ( m_nCurTextWidth != nPrevTextWidth )
623 SetScrollBarRanges();
624 m_bHighlighting = false;
627 void SwSrcEditWindow::DoSyntaxHighlight( sal_uInt16 nPara )
629 // Because of DelayedSyntaxHighlight it could happen,
630 // that the line doesn't exist anymore!
631 if ( nPara >= m_pTextEngine->GetParagraphCount() )
632 return;
634 bool bTempModified = IsModified();
635 m_pTextEngine->RemoveAttribs( nPara );
636 OUString aSource( m_pTextEngine->GetText( nPara ) );
637 m_pTextEngine->SetUpdateMode( false );
638 ImpDoHighlight( aSource, nPara );
639 TextView* pTmp = m_pTextEngine->GetActiveView();
640 pTmp->SetAutoScroll(false);
641 m_pTextEngine->SetActiveView(nullptr);
642 m_pTextEngine->SetUpdateMode( true );
643 m_pTextEngine->SetActiveView(pTmp);
644 pTmp->SetAutoScroll(true);
645 pTmp->ShowCursor( false/*pTmp->IsAutoScroll()*/ );
647 if(!bTempModified)
648 ClearModifyFlag();
652 void SwSrcEditWindow::ImpDoHighlight( std::u16string_view aSource, sal_uInt16 nLineOff )
654 TextPortions aPortionList;
655 lcl_Highlight(aSource, aPortionList);
657 size_t nCount = aPortionList.size();
658 if ( !nCount )
659 return;
661 TextPortion& rLast = aPortionList[nCount-1];
662 if ( rLast.nStart > rLast.nEnd ) // Only until Bug from MD is resolved
664 nCount--;
665 aPortionList.pop_back();
666 if ( !nCount )
667 return;
671 // Only blanks and tabs have to be attributed along.
672 // When two identical attributes are placed consecutively,
673 // it optimises the TextEngine.
674 sal_uInt16 nLastEnd = 0;
676 for ( size_t i = 0; i < nCount; i++ )
678 TextPortion& r = aPortionList[i];
679 if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved
680 continue;
682 if ( r.nStart > nLastEnd )
684 // Can I rely on the fact that all except blank and tab
685 // are being highlighted?!
686 r.nStart = nLastEnd;
688 nLastEnd = r.nEnd+1;
689 if ( ( i == (nCount-1) ) && ( r.nEnd < aSource.size() ) )
690 r.nEnd = aSource.size();
694 for (TextPortion & r : aPortionList)
696 if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved
697 continue;
698 if(r.eType != svtools::HTMLSGML &&
699 r.eType != svtools::HTMLCOMMENT &&
700 r.eType != svtools::HTMLKEYWORD &&
701 r.eType != svtools::HTMLUNKNOWN)
702 r.eType = svtools::HTMLUNKNOWN;
703 Color aColor(SW_MOD()->GetColorConfig().GetColorValue(r.eType).nColor);
704 m_pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLineOff, r.nStart, r.nEnd+1 );
708 void SwSrcEditWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
710 const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
711 if (!pTextHint)
712 return;
714 switch (pTextHint->GetId())
716 case SfxHintId::TextViewScrolled:
717 m_pHScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().X() );
718 m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
719 break;
721 case SfxHintId::TextHeightChanged:
722 if ( m_pTextEngine->GetTextHeight() < m_pOutWin->GetOutputSizePixel().Height() )
723 m_pTextView->Scroll( 0, m_pTextView->GetStartDocPos().Y() );
724 m_pVScrollbar->SetThumbPos( m_pTextView->GetStartDocPos().Y() );
725 SetScrollBarRanges();
726 break;
728 case SfxHintId::TextParaInserted:
729 case SfxHintId::TextParaContentChanged:
730 if ( !m_bHighlighting )
732 m_aSyntaxLineTable.insert( o3tl::narrowing<sal_uInt16>(pTextHint->GetValue()) );
733 m_aSyntaxIdle.Start();
735 break;
736 default: break;
740 void SwSrcEditWindow::Invalidate(InvalidateFlags )
742 m_pOutWin->Invalidate();
743 Window::Invalidate();
746 void SwSrcEditWindow::Command( const CommandEvent& rCEvt )
748 switch(rCEvt.GetCommand())
750 case CommandEventId::Wheel:
751 case CommandEventId::StartAutoScroll:
752 case CommandEventId::AutoScroll:
754 const CommandWheelData* pWData = rCEvt.GetWheelData();
755 if( !pWData || CommandWheelMode::ZOOM != pWData->GetMode() )
756 HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
758 break;
759 default:
760 Window::Command(rCEvt);
764 void SwSrcEditWindow::HandleWheelCommand( const CommandEvent& rCEvt )
766 m_pTextView->Command(rCEvt);
767 HandleScrollCommand( rCEvt, m_pHScrollbar, m_pVScrollbar );
770 void SwSrcEditWindow::GetFocus()
772 if (m_pOutWin)
773 m_pOutWin->GrabFocus();
776 static bool lcl_GetLanguagesForEncoding(rtl_TextEncoding eEnc, LanguageType aLanguages[])
778 switch(eEnc)
780 case RTL_TEXTENCODING_UTF7 :
781 case RTL_TEXTENCODING_UTF8 :
782 // don#t fill - all LANGUAGE_SYSTEM means unicode font has to be used
783 break;
785 case RTL_TEXTENCODING_ISO_8859_3:
786 case RTL_TEXTENCODING_ISO_8859_1 :
787 case RTL_TEXTENCODING_MS_1252 :
788 case RTL_TEXTENCODING_APPLE_ROMAN :
789 case RTL_TEXTENCODING_IBM_850 :
790 case RTL_TEXTENCODING_ISO_8859_14 :
791 case RTL_TEXTENCODING_ISO_8859_15 :
792 //fill with western languages
793 aLanguages[0] = LANGUAGE_GERMAN;
794 aLanguages[1] = LANGUAGE_FRENCH;
795 aLanguages[2] = LANGUAGE_ITALIAN;
796 aLanguages[3] = LANGUAGE_SPANISH;
797 break;
799 case RTL_TEXTENCODING_IBM_865 :
800 //scandinavian
801 aLanguages[0] = LANGUAGE_FINNISH;
802 aLanguages[1] = LANGUAGE_NORWEGIAN;
803 aLanguages[2] = LANGUAGE_SWEDISH;
804 aLanguages[3] = LANGUAGE_DANISH;
805 break;
807 case RTL_TEXTENCODING_ISO_8859_10 :
808 case RTL_TEXTENCODING_ISO_8859_13 :
809 case RTL_TEXTENCODING_ISO_8859_2 :
810 case RTL_TEXTENCODING_IBM_852 :
811 case RTL_TEXTENCODING_MS_1250 :
812 case RTL_TEXTENCODING_APPLE_CENTEURO :
813 aLanguages[0] = LANGUAGE_POLISH;
814 aLanguages[1] = LANGUAGE_CZECH;
815 aLanguages[2] = LANGUAGE_HUNGARIAN;
816 aLanguages[3] = LANGUAGE_SLOVAK;
817 break;
819 case RTL_TEXTENCODING_ISO_8859_4 :
820 case RTL_TEXTENCODING_IBM_775 :
821 case RTL_TEXTENCODING_MS_1257 :
822 aLanguages[0] = LANGUAGE_LATVIAN ;
823 aLanguages[1] = LANGUAGE_LITHUANIAN;
824 aLanguages[2] = LANGUAGE_ESTONIAN ;
825 break;
827 case RTL_TEXTENCODING_IBM_863 : aLanguages[0] = LANGUAGE_FRENCH_CANADIAN; break;
828 case RTL_TEXTENCODING_APPLE_FARSI : aLanguages[0] = LANGUAGE_FARSI; break;
829 case RTL_TEXTENCODING_APPLE_ROMANIAN:aLanguages[0] = LANGUAGE_ROMANIAN; break;
831 case RTL_TEXTENCODING_IBM_861 :
832 case RTL_TEXTENCODING_APPLE_ICELAND :
833 aLanguages[0] = LANGUAGE_ICELANDIC;
834 break;
836 case RTL_TEXTENCODING_APPLE_CROATIAN:aLanguages[0] = LANGUAGE_CROATIAN; break;
838 case RTL_TEXTENCODING_IBM_437 :
839 case RTL_TEXTENCODING_ASCII_US : aLanguages[0] = LANGUAGE_ENGLISH; break;
841 case RTL_TEXTENCODING_IBM_862 :
842 case RTL_TEXTENCODING_MS_1255 :
843 case RTL_TEXTENCODING_APPLE_HEBREW :
844 case RTL_TEXTENCODING_ISO_8859_8 :
845 aLanguages[0] = LANGUAGE_HEBREW;
846 break;
848 case RTL_TEXTENCODING_IBM_857 :
849 case RTL_TEXTENCODING_MS_1254 :
850 case RTL_TEXTENCODING_APPLE_TURKISH:
851 case RTL_TEXTENCODING_ISO_8859_9 :
852 aLanguages[0] = LANGUAGE_TURKISH;
853 break;
855 case RTL_TEXTENCODING_IBM_860 :
856 aLanguages[0] = LANGUAGE_PORTUGUESE;
857 break;
859 case RTL_TEXTENCODING_IBM_869 :
860 case RTL_TEXTENCODING_MS_1253 :
861 case RTL_TEXTENCODING_APPLE_GREEK :
862 case RTL_TEXTENCODING_ISO_8859_7 :
863 case RTL_TEXTENCODING_IBM_737 :
864 aLanguages[0] = LANGUAGE_GREEK;
865 break;
867 case RTL_TEXTENCODING_KOI8_R :
868 case RTL_TEXTENCODING_ISO_8859_5 :
869 case RTL_TEXTENCODING_IBM_855 :
870 case RTL_TEXTENCODING_MS_1251 :
871 case RTL_TEXTENCODING_IBM_866 :
872 case RTL_TEXTENCODING_APPLE_CYRILLIC :
873 aLanguages[0] = LANGUAGE_RUSSIAN;
874 break;
876 case RTL_TEXTENCODING_APPLE_UKRAINIAN:
877 case RTL_TEXTENCODING_KOI8_U:
878 aLanguages[0] = LANGUAGE_UKRAINIAN;
879 break;
881 case RTL_TEXTENCODING_IBM_864 :
882 case RTL_TEXTENCODING_MS_1256 :
883 case RTL_TEXTENCODING_ISO_8859_6 :
884 case RTL_TEXTENCODING_APPLE_ARABIC :
885 aLanguages[0] = LANGUAGE_ARABIC_SAUDI_ARABIA;
886 break;
888 case RTL_TEXTENCODING_APPLE_CHINTRAD :
889 case RTL_TEXTENCODING_MS_950 :
890 case RTL_TEXTENCODING_GBT_12345 :
891 case RTL_TEXTENCODING_BIG5 :
892 case RTL_TEXTENCODING_EUC_TW :
893 case RTL_TEXTENCODING_BIG5_HKSCS :
894 aLanguages[0] = LANGUAGE_CHINESE_TRADITIONAL;
895 break;
897 case RTL_TEXTENCODING_EUC_JP :
898 case RTL_TEXTENCODING_ISO_2022_JP :
899 case RTL_TEXTENCODING_JIS_X_0201 :
900 case RTL_TEXTENCODING_JIS_X_0208 :
901 case RTL_TEXTENCODING_JIS_X_0212 :
902 case RTL_TEXTENCODING_APPLE_JAPANESE :
903 case RTL_TEXTENCODING_MS_932 :
904 case RTL_TEXTENCODING_SHIFT_JIS :
905 aLanguages[0] = LANGUAGE_JAPANESE;
906 break;
908 case RTL_TEXTENCODING_GB_2312 :
909 case RTL_TEXTENCODING_MS_936 :
910 case RTL_TEXTENCODING_GBK :
911 case RTL_TEXTENCODING_GB_18030 :
912 case RTL_TEXTENCODING_APPLE_CHINSIMP :
913 case RTL_TEXTENCODING_EUC_CN :
914 case RTL_TEXTENCODING_ISO_2022_CN :
915 aLanguages[0] = LANGUAGE_CHINESE_SIMPLIFIED;
916 break;
918 case RTL_TEXTENCODING_APPLE_KOREAN :
919 case RTL_TEXTENCODING_MS_949 :
920 case RTL_TEXTENCODING_EUC_KR :
921 case RTL_TEXTENCODING_ISO_2022_KR :
922 case RTL_TEXTENCODING_MS_1361 :
923 aLanguages[0] = LANGUAGE_KOREAN;
924 break;
926 case RTL_TEXTENCODING_APPLE_THAI :
927 case RTL_TEXTENCODING_MS_874 :
928 case RTL_TEXTENCODING_TIS_620 :
929 aLanguages[0] = LANGUAGE_THAI;
930 break;
931 default: aLanguages[0] = Application::GetSettings().GetUILanguageTag().getLanguageType();
933 return aLanguages[0] != LANGUAGE_SYSTEM;
935 void SwSrcEditWindow::SetFont()
937 OUString sFontName(
938 officecfg::Office::Common::Font::SourceViewFont::FontName::get().
939 value_or(OUString()));
940 if(sFontName.isEmpty())
942 LanguageType aLanguages[5] =
944 LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM
946 vcl::Font aFont;
947 if(lcl_GetLanguagesForEncoding(m_eSourceEncoding, aLanguages))
949 //TODO: check for multiple languages
950 aFont = OutputDevice::GetDefaultFont(DefaultFontType::FIXED, aLanguages[0], GetDefaultFontFlags::NONE, GetOutDev());
952 else
953 aFont = OutputDevice::GetDefaultFont(DefaultFontType::SANS_UNICODE,
954 Application::GetSettings().GetLanguageTag().getLanguageType(), GetDefaultFontFlags::NONE, GetOutDev());
955 sFontName = aFont.GetFamilyName();
957 const SvxFontListItem* pFontListItem =
958 static_cast<const SvxFontListItem* >(m_pSrcView->GetDocShell()->GetItem( SID_ATTR_CHAR_FONTLIST ));
959 const FontList* pList = pFontListItem->GetFontList();
960 FontMetric aFontMetric = pList->Get(sFontName,WEIGHT_NORMAL, ITALIC_NONE);
962 const vcl::Font& rFont = GetTextEngine()->GetFont();
963 vcl::Font aFont(aFontMetric);
964 Size aSize(rFont.GetFontSize());
965 //font height is stored in point and set in twip
966 aSize.setHeight(
967 officecfg::Office::Common::Font::SourceViewFont::FontHeight::get() * 20 );
968 aFont.SetFontSize(m_pOutWin->LogicToPixel(aSize, MapMode(MapUnit::MapTwip)));
969 GetTextEngine()->SetFont( aFont );
970 m_pOutWin->SetFont(aFont);
973 void SwSrcEditWindow::SetTextEncoding(rtl_TextEncoding eEncoding)
975 m_eSourceEncoding = eEncoding;
976 SetFont();
979 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */