1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlfileview.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
33 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
34 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
35 #include <com/sun/star/xml/sax/SAXParseException.hpp>
36 #include <com/sun/star/xml/XImportFilter.hpp>
37 #include <com/sun/star/io/XActiveDataSource.hpp>
38 #include <comphelper/oslfile2streamwrap.hxx>
40 #include <rtl/tencinfo.h>
41 #include <vcl/svapp.hxx>
42 #include <vos/mutex.hxx>
43 #include <svtools/textview.hxx>
44 #ifndef _SCRBAR_HXX //autogen
45 #include <vcl/scrbar.hxx>
47 #include <tools/stream.hxx>
48 #include <tools/time.hxx>
49 #include <osl/file.hxx>
50 #include <vcl/msgbox.hxx>
51 #include <svtools/colorcfg.hxx>
52 #include <svtools/htmltokn.h>
53 #include <svtools/txtattr.hxx>
55 #include "xmlfilterdialogstrings.hrc"
56 #include "xmlfiltersettingsdialog.hxx"
57 #include "xmlfileview.hxx"
58 #include "xmlfileview.hrc"
59 #include "xmlfilterhelpids.hrc"
63 using namespace com::sun::star::lang
;
64 using namespace com::sun::star::beans
;
65 using namespace com::sun::star::uno
;
66 using namespace com::sun::star::io
;
67 using namespace com::sun::star::xml
;
68 using namespace com::sun::star::xml::sax
;
71 #define MAX_SYNTAX_HIGHLIGHT 20
72 #define MAX_HIGHLIGHTTIME 200
73 #define SYNTAX_HIGHLIGHT_TIMEOUT 200
80 svtools::ColorConfigEntry eType
;
83 SV_DECL_VARARR(SwTextPortions
, SwTextPortion
,16,16)
84 SV_IMPL_VARARR(SwTextPortions
, SwTextPortion
);
86 class XMLErrorHandler
: public ::cppu::WeakImplHelper1
< XErrorHandler
>
89 XMLErrorHandler( XMLSourceFileDialog
* pParent
, ListBox
& rListBox
);
92 virtual void SAL_CALL
error( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
);
93 virtual void SAL_CALL
fatalError( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
);
94 virtual void SAL_CALL
warning( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
);
97 XMLSourceFileDialog
* mpParent
;
101 XMLErrorHandler::XMLErrorHandler( XMLSourceFileDialog
* pParent
, ListBox
& rListBox
)
102 : mpParent( pParent
),
103 mrListBox( rListBox
)
108 void SAL_CALL
XMLErrorHandler::error( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
110 vos::OGuard
aGuard( Application::GetSolarMutex() );
113 if( aSAXParseException
>>= e
)
115 String
sErr( String::CreateFromInt32( e
.LineNumber
) );
116 sErr
+= String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
117 sErr
+= String( e
.Message
);
118 USHORT nEntry
= mrListBox
.InsertEntry( sErr
);
119 mrListBox
.SetEntryData( nEntry
, (void*)e
.LineNumber
);
123 void SAL_CALL
XMLErrorHandler::fatalError( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
125 vos::OGuard
aGuard( Application::GetSolarMutex() );
128 if( aSAXParseException
>>= e
)
130 String
sErr( String::CreateFromInt32( e
.LineNumber
) );
131 sErr
+= String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
132 sErr
+= String( e
.Message
);
133 USHORT nEntry
= mrListBox
.InsertEntry( sErr
);
134 mrListBox
.SetEntryData( nEntry
, (void*)e
.LineNumber
);
138 void SAL_CALL
XMLErrorHandler::warning( const Any
& /* aSAXParseException */ ) throw (SAXException
, RuntimeException
)
142 if( aSAXParseException >>= e )
144 String sErr( String::CreateFromInt32( e.LineNumber ) );
145 sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
146 sErr += String( e.Message );
147 USHORT nEntry = mrListBox.InsertEntry( sErr );
148 mrListBox.SetEntryData( nEntry, (void*)e.LineNumber );
154 XMLFileWindow::XMLFileWindow( Window
* pParent
) :
155 Window( pParent
, WB_BORDER
|WB_CLIPCHILDREN
),
161 nStartLine(USHRT_MAX
),
162 eSourceEncoding(gsl_getSystemTextEncoding()),
168 XMLFileWindow::~XMLFileWindow()
172 EndListening( *pTextEngine
);
173 pTextEngine
->RemoveView( pTextView
);
184 void XMLFileWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
186 Window::DataChanged( rDCEvt
);
188 switch ( rDCEvt
.GetType() )
190 case DATACHANGED_SETTINGS
:
191 // ScrollBars neu anordnen bzw. Resize ausloesen, da sich
192 // ScrollBar-Groesse geaendert haben kann. Dazu muss dann im
193 // Resize-Handler aber auch die Groesse der ScrollBars aus
194 // den Settings abgefragt werden.
195 if( rDCEvt
.GetFlags() & SETTINGS_STYLE
)
201 void XMLFileWindow::Resize()
203 // ScrollBars, etc. passiert in Adjust...
206 long nVisY
= pTextView
->GetStartDocPos().Y();
207 pTextView
->ShowCursor();
208 Size
aOutSz( GetOutputSizePixel() );
209 long nMaxVisAreaStart
= pTextView
->GetTextEngine()->GetTextHeight() - aOutSz
.Height();
210 if ( nMaxVisAreaStart
< 0 )
211 nMaxVisAreaStart
= 0;
212 if ( pTextView
->GetStartDocPos().Y() > nMaxVisAreaStart
)
214 Point
aStartDocPos( pTextView
->GetStartDocPos() );
215 aStartDocPos
.Y() = nMaxVisAreaStart
;
216 pTextView
->SetStartDocPos( aStartDocPos
);
217 pTextView
->ShowCursor();
219 long nScrollStd
= GetSettings().GetStyleSettings().GetScrollBarSize();
220 Size
aScrollSz(aOutSz
.Width() - nScrollStd
, nScrollStd
);
221 Point
aScrollPos(0, aOutSz
.Height() - nScrollStd
);
223 pHScrollbar
->SetPosSizePixel( aScrollPos
, aScrollSz
);
225 aScrollSz
.Width() = aScrollSz
.Height();
226 aScrollSz
.Height() = aOutSz
.Height() - aScrollSz
.Height();
227 aScrollPos
= Point(aOutSz
.Width() - nScrollStd
, 0);
229 pVScrollbar
->SetPosSizePixel( aScrollPos
, aScrollSz
);
230 aOutSz
.Width() -= nScrollStd
;
231 aOutSz
.Height() -= nScrollStd
;
232 pOutWin
->SetOutputSizePixel(aOutSz
);
235 // Zeile im ersten Resize setzen
236 if(USHRT_MAX
!= nStartLine
)
238 if(nStartLine
< pTextEngine
->GetParagraphCount())
240 TextSelection
aSel(TextPaM( nStartLine
, 0 ), TextPaM( nStartLine
, 0x0 ));
241 pTextView
->SetSelection(aSel
);
242 pTextView
->ShowCursor();
244 nStartLine
= USHRT_MAX
;
247 if ( nVisY
!= pTextView
->GetStartDocPos().Y() )
253 void TextViewOutWin::DataChanged( const DataChangedEvent
& rDCEvt
)
255 Window::DataChanged( rDCEvt
);
257 switch( rDCEvt
.GetType() )
259 case DATACHANGED_SETTINGS
:
260 // den Settings abgefragt werden.
261 if( rDCEvt
.GetFlags() & SETTINGS_STYLE
)
263 const Color
&rCol
= GetSettings().GetStyleSettings().GetWindowColor();
264 SetBackground( rCol
);
265 Font
aFont( pTextView
->GetTextEngine()->GetFont() );
266 aFont
.SetFillColor( rCol
);
267 pTextView
->GetTextEngine()->SetFont( aFont
);
273 void TextViewOutWin::MouseMove( const MouseEvent
&rEvt
)
276 pTextView
->MouseMove( rEvt
);
279 void TextViewOutWin::MouseButtonUp( const MouseEvent
&rEvt
)
282 pTextView
->MouseButtonUp( rEvt
);
285 void TextViewOutWin::MouseButtonDown( const MouseEvent
&rEvt
)
289 pTextView
->MouseButtonDown( rEvt
);
292 void TextViewOutWin::Command( const CommandEvent
& rCEvt
)
294 switch(rCEvt
.GetCommand())
296 case COMMAND_CONTEXTMENU
:
299 case COMMAND_STARTAUTOSCROLL
:
300 case COMMAND_AUTOSCROLL
:
302 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
303 if( !pWData
|| COMMAND_WHEEL_ZOOM
!= pWData
->GetMode() )
305 ((XMLFileWindow
*)GetParent())->HandleWheelCommand( rCEvt
);
312 pTextView
->Command( rCEvt
);
314 Window::Command(rCEvt
);
318 void TextViewOutWin::KeyInput( const KeyEvent
& rKEvt
)
320 if(!TextEngine::DoesKeyChangeText( rKEvt
))
321 pTextView
->KeyInput( rKEvt
);
324 void TextViewOutWin::Paint( const Rectangle
& rRect
)
326 pTextView
->Paint( rRect
);
329 void XMLFileWindow::CreateTextEngine()
331 const Color
&rCol
= GetSettings().GetStyleSettings().GetWindowColor();
332 pOutWin
= new TextViewOutWin(this, 0);
333 pOutWin
->SetBackground(Wallpaper(rCol
));
334 pOutWin
->SetPointer(Pointer(POINTER_TEXT
));
338 pHScrollbar
= new ScrollBar(this, WB_3DLOOK
|WB_HSCROLL
|WB_DRAG
);
339 pHScrollbar
->SetScrollHdl(LINK(this, XMLFileWindow
, ScrollHdl
));
342 pVScrollbar
= new ScrollBar(this, WB_3DLOOK
|WB_VSCROLL
|WB_DRAG
);
343 pVScrollbar
->SetScrollHdl(LINK(this, XMLFileWindow
, ScrollHdl
));
344 pHScrollbar
->EnableDrag();
347 pTextEngine
= new TextEngine
;
348 pTextView
= new TextView( pTextEngine
, pOutWin
);
349 pTextView
->SetAutoIndentMode(TRUE
);
350 pOutWin
->SetTextView(pTextView
);
352 pTextEngine
->SetUpdateMode( FALSE
);
353 pTextEngine
->InsertView( pTextView
);
356 aFont
.SetTransparent( FALSE
);
357 aFont
.SetFillColor( rCol
);
358 SetPointFont( aFont
);
360 aFont
.SetFillColor( rCol
);
361 pOutWin
->SetFont( aFont
);
362 pTextEngine
->SetFont( aFont
);
364 aSyntaxIdleTimer
.SetTimeout( SYNTAX_HIGHLIGHT_TIMEOUT
);
365 aSyntaxIdleTimer
.SetTimeoutHdl( LINK( this, XMLFileWindow
, SyntaxTimerHdl
) );
367 pTextEngine
->EnableUndo( FALSE
);
368 pTextEngine
->SetUpdateMode( TRUE
);
370 // pTextView->ShowCursor( TRUE, TRUE );
371 pTextView
->HideCursor();
374 StartListening( *pTextEngine
);
377 void XMLFileWindow::SetScrollBarRanges()
379 pHScrollbar
->SetRange( Range( 0, nCurTextWidth
-1 ) );
380 pVScrollbar
->SetRange( Range(0, pTextEngine
->GetTextHeight()-1) );
383 void XMLFileWindow::InitScrollBars()
385 SetScrollBarRanges();
387 Size
aOutSz( pOutWin
->GetOutputSizePixel() );
388 pVScrollbar
->SetVisibleSize( aOutSz
.Height() );
389 pVScrollbar
->SetPageSize( aOutSz
.Height() * 8 / 10 );
390 pVScrollbar
->SetLineSize( pOutWin
->GetTextHeight() );
391 pVScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
392 pHScrollbar
->SetVisibleSize( aOutSz
.Width() );
393 pHScrollbar
->SetPageSize( aOutSz
.Width() * 8 / 10 );
394 pHScrollbar
->SetLineSize( pOutWin
->GetTextWidth( 'x' ) );
395 pHScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().X() );
399 IMPL_LINK(XMLFileWindow
, ScrollHdl
, ScrollBar
*, pScroll
)
401 if(pScroll
== pVScrollbar
)
403 long nDiff
= pTextView
->GetStartDocPos().Y() - pScroll
->GetThumbPos();
404 GetTextView()->Scroll( 0, nDiff
);
405 pTextView
->ShowCursor( FALSE
, TRUE
);
406 pScroll
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
410 long nDiff
= pTextView
->GetStartDocPos().X() - pScroll
->GetThumbPos();
411 GetTextView()->Scroll( nDiff
, 0 );
412 pTextView
->ShowCursor( FALSE
, TRUE
);
413 pScroll
->SetThumbPos( pTextView
->GetStartDocPos().X() );
418 void XMLFileWindow::Notify( SfxBroadcaster
& /* rBC */, const SfxHint
& rHint
)
420 if ( rHint
.ISA( TextHint
) )
422 const TextHint
& rTextHint
= (const TextHint
&)rHint
;
423 if( rTextHint
.GetId() == TEXT_HINT_VIEWSCROLLED
)
425 pHScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().X() );
426 pVScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
428 else if( rTextHint
.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED
)
430 if ( (long)pTextEngine
->GetTextHeight() < pOutWin
->GetOutputSizePixel().Height() )
431 pTextView
->Scroll( 0, pTextView
->GetStartDocPos().Y() );
432 pVScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
433 SetScrollBarRanges();
435 else if( rTextHint
.GetId() == TEXT_HINT_FORMATPARA
)
437 DoDelayedSyntaxHighlight( (USHORT
)rTextHint
.GetValue() );
442 void XMLFileWindow::InvalidateWindow()
444 pOutWin
->Invalidate();
445 Window::Invalidate();
449 void XMLFileWindow::Command( const CommandEvent
& rCEvt
)
451 switch(rCEvt
.GetCommand())
454 case COMMAND_STARTAUTOSCROLL
:
455 case COMMAND_AUTOSCROLL
:
457 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
458 if( !pWData
|| COMMAND_WHEEL_ZOOM
!= pWData
->GetMode() )
459 HandleScrollCommand( rCEvt
, pHScrollbar
, pVScrollbar
);
463 Window::Command(rCEvt
);
467 void XMLFileWindow::HandleWheelCommand( const CommandEvent
& rCEvt
)
469 pTextView
->Command(rCEvt
);
470 HandleScrollCommand( rCEvt
, pHScrollbar
, pVScrollbar
);
473 void XMLFileWindow::GetFocus()
475 pOutWin
->GrabFocus();
478 void XMLFileWindow::ShowWindow( const rtl::OUString
& rFileName
)
480 String
aFileName( rFileName
);
481 SvFileStream
aStream( aFileName
, STREAM_READ
);
483 // since the xml files we load are utf-8 encoded, we need to set
484 // this encoding at the SvFileStream, else the TextEngine will
485 // use its default encoding which is not UTF8
486 const sal_Char
*pCharSet
= rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8
);
487 rtl_TextEncoding eDestEnc
= rtl_getTextEncodingFromMimeCharset( pCharSet
);
488 aStream
.SetStreamCharSet( eDestEnc
);
490 if( Read( aStream
) )
492 long nPrevTextWidth
= nCurTextWidth
;
493 nCurTextWidth
= pTextEngine
->CalcTextWidth() + 25; // kleine Toleranz
494 if ( nCurTextWidth
!= nPrevTextWidth
)
495 SetScrollBarRanges();
497 TextPaM
aPaM( pTextView
->CursorStartOfDoc() );
498 TextSelection
aSelection( aPaM
, aPaM
);
499 pTextView
->SetSelection( aSelection
, true );
505 void XMLFileWindow::showLine( sal_Int32 nLine
)
507 TextPaM
aPaM( pTextView
->CursorStartOfDoc() );
509 aPaM
= pTextView
->CursorDown( aPaM
);
511 TextSelection
aSelection( pTextView
->CursorEndOfLine( aPaM
), aPaM
);
512 pTextView
->SetSelection( aSelection
, true );
516 XMLSourceFileDialog::XMLSourceFileDialog( Window
* pParent
, ResMgr
& rResMgr
, const com::sun::star::uno::Reference
< com::sun::star::lang::XMultiServiceFactory
>& rxMSF
)
517 : WorkWindow( pParent
, ResId( DLG_XML_SOURCE_FILE_DIALOG
, rResMgr
) ),
518 mnOutputHeight( LogicToPixel( Size( 80, 80 ), MAP_APPFONT
).Height() ),
522 maPBValidate( this, ResId( PB_VALIDATE
, rResMgr
) )
527 maPBValidate
.SetClickHdl(LINK( this, XMLSourceFileDialog
, ClickHdl_Impl
) );
528 maLBOutput
.SetSelectHdl(LINK(this, XMLSourceFileDialog
, SelectHdl_Impl
) );
529 mpTextWindow
= new XMLFileWindow( this );
530 mpTextWindow
->SetHelpId( HID_XML_FILTER_OUTPUT_WINDOW
);
531 maLBOutput
.SetHelpId( HID_XML_FILTER_TEST_VALIDATE_OUPUT
);
536 XMLSourceFileDialog::~XMLSourceFileDialog()
538 if( maFileURL
.getLength() )
539 osl::File::remove( maFileURL
);
544 void XMLSourceFileDialog::ShowWindow( const rtl::OUString
& rFileName
, const filter_info_impl
* pFilterInfo
)
547 if( maFileURL
.getLength() )
549 osl::File::remove( maFileURL
);
551 mpTextWindow
= new XMLFileWindow( this );
554 maPBValidate
.Enable(TRUE
);
558 mpFilterInfo
= pFilterInfo
;
559 maFileURL
= rFileName
;
560 mpTextWindow
->ShowWindow( rFileName
);
565 void XMLSourceFileDialog::Resize()
567 bool bOutputVisible
= maLBOutput
.IsVisible() != 0;
569 Point
aSpacing( LogicToPixel( Point( 6, 6 ), MAP_APPFONT
) );
570 Size
aButton( maPBValidate
.GetSizePixel() );
572 Size
aDialogSize( GetOutputSizePixel() );
574 // Point aButtonPos( aSpacing.X(), aSpacing.Y() );
575 // maPBValidate.SetPosSizePixel( aButtonPos, aButton );
577 Size
aOutputSize( aDialogSize
.Width(), bOutputVisible
? mnOutputHeight
: 0 );
579 Point
aTextWindowPos( 0, 2* aSpacing
.Y() + aButton
.Height() );
580 Size
aTextWindowSize( aDialogSize
.Width(), aDialogSize
.Height() - aTextWindowPos
.Y() - aOutputSize
.Height() );
582 mpTextWindow
->SetPosSizePixel( aTextWindowPos
, aTextWindowSize
);
586 Point
aOutputPos( 0, aTextWindowPos
.Y() + aTextWindowSize
.Height() );
587 maLBOutput
.SetPosSizePixel( aOutputPos
, aOutputSize
);
592 IMPL_LINK(XMLSourceFileDialog
, SelectHdl_Impl
, ListBox
*, pListBox
)
594 USHORT nEntry
= pListBox
->GetSelectEntryPos();
595 if( LISTBOX_ENTRY_NOTFOUND
!= nEntry
)
597 int nLine
= (int)(sal_IntPtr
)pListBox
->GetEntryData(nEntry
);
609 IMPL_LINK(XMLSourceFileDialog
, ClickHdl_Impl
, PushButton
*, /* pButton */ )
615 void XMLSourceFileDialog::onValidate()
620 maPBValidate
.Enable(FALSE
);
625 Reference
< XImportFilter
> xImporter( mxMSF
->createInstance( OUString::createFromAscii( "com.sun.star.documentconversion.XSLTValidate" ) ), UNO_QUERY
);
628 osl::File
aInputFile( maFileURL
);
629 /* osl::File::RC rc = */ aInputFile
.open( OpenFlag_Read
);
631 Reference
< XInputStream
> xIS( new comphelper::OSLInputStreamWrapper( aInputFile
) );
633 Sequence
< PropertyValue
> aSourceData(3);
634 aSourceData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) );
635 aSourceData
[0].Value
<<= xIS
;
637 aSourceData
[1].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ) );
638 aSourceData
[1].Value
<<= maFileURL
;
640 aSourceData
[2].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorHandler" ) );
641 Reference
< XErrorHandler
> xHandle( new XMLErrorHandler( this, maLBOutput
) );
642 aSourceData
[2].Value
<<= xHandle
;
644 Reference
< XDocumentHandler
> xWriter( mxMSF
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), UNO_QUERY
);
645 Reference
< XOutputStream
> xOS( mxMSF
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pipe" ) ) ), UNO_QUERY
);
646 Reference
< XActiveDataSource
> xDocSrc( xWriter
, UNO_QUERY
);
647 xDocSrc
->setOutputStream( xOS
);
649 Sequence
< OUString
> aFilterUserData( mpFilterInfo
->getFilterUserData() );
650 xImporter
->importer( aSourceData
, xWriter
, aFilterUserData
);
655 String
sErr( e
.Message
);
656 USHORT nEntry
= maLBOutput
.InsertEntry( sErr
);
657 maLBOutput
.SetEntryData( nEntry
, (void*)-1 );
660 if( 0 == maLBOutput
.GetEntryCount() )
662 String
sErr( RESID( STR_NO_ERRORS_FOUND
) );
663 USHORT nEntry
= maLBOutput
.InsertEntry( sErr
);
664 maLBOutput
.SetEntryData( nEntry
, (void*)-1 );
670 void XMLSourceFileDialog::showLine( sal_Int32 nLine
)
672 mpTextWindow
->showLine( nLine
);
676 ///////////////////////////////////////////////////////////////////////
678 void lcl_Highlight(const String
& rSource
, SwTextPortions
& aPortionList
)
680 const sal_Unicode cOpenBracket
= '<';
681 const sal_Unicode cCloseBracket
= '>';
682 const sal_Unicode cSlash
= '/';
683 const sal_Unicode cExclamation
= '!';
684 // const sal_Unicode cQuote = '"';
685 // const sal_Unicode cSQuote = '\'';
686 const sal_Unicode cMinus
= '-';
687 const sal_Unicode cSpace
= ' ';
688 const sal_Unicode cTab
= 0x09;
689 const sal_Unicode cLF
= 0x0a;
690 const sal_Unicode cCR
= 0x0d;
693 const USHORT nStrLen
= rSource
.Len();
694 USHORT nInsert
= 0; // Anzahl der eingefuegten Portions
695 USHORT nActPos
= 0; //Position, an der '<' gefunden wurde
696 USHORT nOffset
= 0; //Offset von nActPos zur '<'
697 USHORT nPortStart
= USHRT_MAX
; // fuer die TextPortion
698 USHORT nPortEnd
= 0; //
700 while(nActPos
< nStrLen
)
702 svtools::ColorConfigEntry eFoundType
= svtools::HTMLUNKNOWN
;
703 if(rSource
.GetChar(nActPos
) == cOpenBracket
&& nActPos
< nStrLen
- 2 )
705 // 'leere' Portion einfuegen
706 if(nPortEnd
< nActPos
- 1 )
709 // am Anfang nicht verschieben
710 aText
.nStart
= nPortEnd
;
713 aText
.nEnd
= nActPos
- 1;
714 aText
.eType
= svtools::HTMLUNKNOWN
;
715 aPortionList
.Insert(aText
, nInsert
++);
717 sal_Unicode cFollowFirst
= rSource
.GetChar((xub_StrLen
)(nActPos
+ 1));
718 sal_Unicode cFollowNext
= rSource
.GetChar((xub_StrLen
)(nActPos
+ 2));
719 if(cExclamation
== cFollowFirst
)
721 // "<!" SGML oder Kommentar
722 if(cMinus
== cFollowNext
&&
723 nActPos
< nStrLen
- 3 && cMinus
== rSource
.GetChar((xub_StrLen
)(nActPos
+ 3)))
725 eFoundType
= svtools::HTMLCOMMENT
;
728 eFoundType
= svtools::HTMLSGML
;
729 nPortStart
= nActPos
;
730 nPortEnd
= nActPos
+ 1;
732 else if(cSlash
== cFollowFirst
)
734 // "</" Slash ignorieren
735 nPortStart
= nActPos
;
739 if(svtools::HTMLUNKNOWN
== eFoundType
)
741 //jetzt koennte hier ein keyword folgen
742 USHORT nSrchPos
= nActPos
;
743 while(++nSrchPos
< nStrLen
- 1)
745 sal_Unicode cNext
= rSource
.GetChar(nSrchPos
);
746 if( cNext
== cSpace
||
751 else if(cNext
== cCloseBracket
)
756 if(nSrchPos
> nActPos
+ 1)
758 //irgend ein String wurde gefunden
759 String sToken
= rSource
.Copy(nActPos
+ 1, nSrchPos
- nActPos
- 1 );
760 sToken
.ToUpperAscii();
761 // int nToken = ::GetHTMLToken(sToken);
765 eFoundType
= svtools::HTMLKEYWORD
;
767 nPortStart
= nActPos
;
774 DBG_ERROR("Token nicht erkannt!")
775 DBG_ERROR(ByteString(sToken, gsl_getSystemTextEncoding()).GetBuffer())
782 // jetzt muss noch '>' gesucht werden
783 if(svtools::HTMLUNKNOWN
!= eFoundType
)
786 for(USHORT i
= nPortEnd
; i
< nStrLen
; i
++)
787 if(cCloseBracket
== rSource
.GetChar(i
))
793 if(!bFound
&& (eFoundType
== svtools::HTMLCOMMENT
))
795 // Kommentar ohne Ende in dieser Zeile
797 nPortEnd
= nStrLen
- 1;
800 if(bFound
||(eFoundType
== svtools::HTMLCOMMENT
))
802 SwTextPortion aText2
;
804 aText2
.nStart
= nPortStart
+ 1;
805 aText2
.nEnd
= nPortEnd
;
806 aText2
.eType
= eFoundType
;
807 aPortionList
.Insert(aText2
, nInsert
++);
808 eFoundType
= svtools::HTMLUNKNOWN
;
815 if(nInsert
&& nPortEnd
< nActPos
- 1)
818 aText
.nStart
= nPortEnd
+ 1;
819 aText
.nEnd
= nActPos
- 1;
820 aText
.eType
= svtools::HTMLUNKNOWN
;
821 aPortionList
.Insert(aText
, nInsert
++);
825 void XMLFileWindow::DoDelayedSyntaxHighlight( USHORT nPara
)
827 if ( !bHighlighting
)
829 aSyntaxLineTable
.Insert( nPara
, (void*)(USHORT
)1 );
830 aSyntaxIdleTimer
.Start();
834 void XMLFileWindow::ImpDoHighlight( const String
& rSource
, USHORT nLineOff
)
836 SwTextPortions aPortionList
;
837 lcl_Highlight(rSource
, aPortionList
);
839 USHORT nCount
= aPortionList
.Count();
843 SwTextPortion
& rLast
= aPortionList
[nCount
-1];
844 if ( rLast
.nStart
> rLast
.nEnd
) // Nur bis Bug von MD behoeben
847 aPortionList
.Remove( nCount
);
853 // Wenn haufig gleiche Farbe, dazwischen Blank ohne Farbe,
854 // ggf. zusammenfassen, oder zumindest das Blank,
855 // damit weniger Attribute
856 BOOL bOptimizeHighlight
= TRUE
; // war in der BasicIDE static
857 if ( bOptimizeHighlight
)
859 // Es muessen nur die Blanks und Tabs mit attributiert werden.
860 // Wenn zwei gleiche Attribute hintereinander eingestellt werden,
861 // optimiert das die TextEngine.
863 for ( USHORT i
= 0; i
< nCount
; i
++ )
865 SwTextPortion
& r
= aPortionList
[i
];
866 DBG_ASSERT( r
.nLine
== aPortionList
[0].nLine
, "doch mehrere Zeilen ?" );
867 if ( r
.nStart
> r
.nEnd
) // Nur bis Bug von MD behoeben
870 if ( r
.nStart
> nLastEnd
)
872 // Kann ich mich drauf verlassen, dass alle ausser
873 // Blank und Tab gehighlightet wird ?!
877 if ( ( i
== (nCount
-1) ) && ( r
.nEnd
< rSource
.Len() ) )
878 r
.nEnd
= rSource
.Len();
882 svtools::ColorConfig aConfig
;
883 for ( USHORT i
= 0; i
< aPortionList
.Count(); i
++ )
885 SwTextPortion
& r
= aPortionList
[i
];
886 if ( r
.nStart
> r
.nEnd
) // Nur bis Bug von MD behoeben
888 // USHORT nCol = r.eType;
889 if(r
.eType
!= svtools::HTMLSGML
&&
890 r
.eType
!= svtools::HTMLCOMMENT
&&
891 r
.eType
!= svtools::HTMLKEYWORD
&&
892 r
.eType
!= svtools::HTMLUNKNOWN
)
893 r
.eType
= (svtools::ColorConfigEntry
)svtools::HTMLUNKNOWN
;
894 Color
aColor((ColorData
)aConfig
.GetColorValue((svtools::ColorConfigEntry
)r
.eType
).nColor
);
895 USHORT nLine
= nLineOff
+r
.nLine
; //
896 pTextEngine
->SetAttrib( TextAttribFontColor( aColor
), nLine
, r
.nStart
, r
.nEnd
+1 );
900 IMPL_LINK( XMLFileWindow
, SyntaxTimerHdl
, Timer
*, pTimer
)
902 Time aSyntaxCheckStart
;
903 DBG_ASSERT( pTextView
, "Noch keine View, aber Syntax-Highlight ?!" );
904 pTextEngine
->SetUpdateMode( FALSE
);
906 bHighlighting
= TRUE
;
909 // zuerst wird der Bereich um dem Cursor bearbeitet
910 TextSelection aSel
= pTextView
->GetSelection();
911 USHORT nCur
= (USHORT
)aSel
.GetStart().GetPara();
916 if(aSyntaxLineTable
.Count())
917 for(USHORT i
= 0; i
< 80 && nCount
< 40; i
++, nCur
++)
919 void * p
= aSyntaxLineTable
.Get(nCur
);
922 DoSyntaxHighlight( nCur
);
923 aSyntaxLineTable
.Remove( nCur
);
925 if(!aSyntaxLineTable
.Count())
927 if((Time().GetTime() - aSyntaxCheckStart
.GetTime()) > MAX_HIGHLIGHTTIME
)
929 pTimer
->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT
);
935 // wenn dann noch etwas frei ist, wird von Beginn an weitergearbeitet
936 void* p
= aSyntaxLineTable
.First();
937 while ( p
&& nCount
< MAX_SYNTAX_HIGHLIGHT
)
939 nLine
= (USHORT
)aSyntaxLineTable
.GetCurKey();
940 DoSyntaxHighlight( nLine
);
941 USHORT nC
= (USHORT
)aSyntaxLineTable
.GetCurKey();
942 p
= aSyntaxLineTable
.Next();
943 aSyntaxLineTable
.Remove(nC
);
945 if(Time().GetTime() - aSyntaxCheckStart
.GetTime() > MAX_HIGHLIGHTTIME
)
947 pTimer
->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT
);
951 // os: #43050# hier wird ein TextView-Problem umpopelt:
952 // waehrend des Highlightings funktionierte das Scrolling nicht
953 TextView
* pTmp
= pTextEngine
->GetActiveView();
954 pTextEngine
->SetActiveView(0);
955 pTextEngine
->SetUpdateMode( TRUE
);
956 pTextEngine
->SetActiveView(pTmp
);
957 pTextView
->ShowCursor(FALSE
, FALSE
);
959 if(aSyntaxLineTable
.Count() && !pTimer
->IsActive())
961 // SyntaxTimerHdl wird gerufen, wenn Text-Aenderung
962 // => gute Gelegenheit, Textbreite zu ermitteln!
963 long nPrevTextWidth
= nCurTextWidth
;
964 nCurTextWidth
= pTextEngine
->CalcTextWidth() + 25; // kleine Toleranz
965 if ( nCurTextWidth
!= nPrevTextWidth
)
966 SetScrollBarRanges();
967 bHighlighting
= FALSE
;
972 void XMLFileWindow::DoSyntaxHighlight( USHORT nPara
)
974 // Durch das DelayedSyntaxHighlight kann es passieren,
975 // dass die Zeile nicht mehr existiert!
976 if ( nPara
< pTextEngine
->GetParagraphCount() )
978 pTextEngine
->RemoveAttribs( nPara
);
979 String
aSource( pTextEngine
->GetText( nPara
) );
980 pTextEngine
->SetUpdateMode( FALSE
);
981 ImpDoHighlight( aSource
, nPara
);
982 // os: #43050# hier wird ein TextView-Problem umpopelt:
983 // waehrend des Highlightings funktionierte das Scrolling nicht
984 TextView
* pTmp
= pTextEngine
->GetActiveView();
985 pTmp
->SetAutoScroll(FALSE
);
986 pTextEngine
->SetActiveView(0);
987 pTextEngine
->SetUpdateMode( TRUE
);
988 pTextEngine
->SetActiveView(pTmp
);
989 // Bug 72887 show the cursor
990 pTmp
->SetAutoScroll(TRUE
);
991 pTmp
->ShowCursor( FALSE
/*pTmp->IsAutoScroll()*/ );