1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_filter.hxx"
30 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
31 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
32 #include <com/sun/star/xml/sax/SAXParseException.hpp>
33 #include <com/sun/star/xml/XImportFilter.hpp>
34 #include <com/sun/star/io/XActiveDataSource.hpp>
35 #include <comphelper/oslfile2streamwrap.hxx>
37 #include <rtl/tencinfo.h>
38 #include <vcl/svapp.hxx>
39 #include <vos/mutex.hxx>
40 #include <svtools/textview.hxx>
41 #ifndef _SCRBAR_HXX //autogen
42 #include <vcl/scrbar.hxx>
44 #include <tools/stream.hxx>
45 #include <tools/time.hxx>
46 #include <osl/file.hxx>
47 #include <vcl/msgbox.hxx>
48 #include <svtools/colorcfg.hxx>
49 #include <svtools/htmltokn.h>
50 #include <svtools/txtattr.hxx>
52 #include "xmlfilterdialogstrings.hrc"
53 #include "xmlfiltersettingsdialog.hxx"
54 #include "xmlfileview.hxx"
55 #include "xmlfileview.hrc"
56 #include "xmlfilterhelpids.hrc"
62 using namespace com::sun::star::lang
;
63 using namespace com::sun::star::beans
;
64 using namespace com::sun::star::uno
;
65 using namespace com::sun::star::io
;
66 using namespace com::sun::star::xml
;
67 using namespace com::sun::star::xml::sax
;
70 #define MAX_SYNTAX_HIGHLIGHT 20
71 #define MAX_HIGHLIGHTTIME 200
72 #define SYNTAX_HIGHLIGHT_TIMEOUT 200
78 sal_uInt16 nStart
, nEnd
;
79 svtools::ColorConfigEntry eType
;
82 typedef std::deque
<SwTextPortion
> SwTextPortions
;
84 class XMLErrorHandler
: public ::cppu::WeakImplHelper1
< XErrorHandler
>
87 XMLErrorHandler( XMLSourceFileDialog
* pParent
, ListBox
& rListBox
);
90 virtual void SAL_CALL
error( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
);
91 virtual void SAL_CALL
fatalError( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
);
92 virtual void SAL_CALL
warning( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
);
95 XMLSourceFileDialog
* mpParent
;
99 XMLErrorHandler::XMLErrorHandler( XMLSourceFileDialog
* pParent
, ListBox
& rListBox
)
100 : mpParent( pParent
),
101 mrListBox( rListBox
)
106 void SAL_CALL
XMLErrorHandler::error( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
108 vos::OGuard
aGuard( Application::GetSolarMutex() );
111 if( aSAXParseException
>>= e
)
113 String
sErr( String::CreateFromInt32( e
.LineNumber
) );
114 sErr
+= String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
115 sErr
+= String( e
.Message
);
116 sal_uInt16 nEntry
= mrListBox
.InsertEntry( sErr
);
117 mrListBox
.SetEntryData( nEntry
, (void*)e
.LineNumber
);
121 void SAL_CALL
XMLErrorHandler::fatalError( const Any
& aSAXParseException
) throw (SAXException
, RuntimeException
)
123 vos::OGuard
aGuard( Application::GetSolarMutex() );
126 if( aSAXParseException
>>= e
)
128 String
sErr( String::CreateFromInt32( e
.LineNumber
) );
129 sErr
+= String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
130 sErr
+= String( e
.Message
);
131 sal_uInt16 nEntry
= mrListBox
.InsertEntry( sErr
);
132 mrListBox
.SetEntryData( nEntry
, (void*)e
.LineNumber
);
136 void SAL_CALL
XMLErrorHandler::warning( const Any
& /* aSAXParseException */ ) throw (SAXException
, RuntimeException
)
140 if( aSAXParseException >>= e )
142 String sErr( String::CreateFromInt32( e.LineNumber ) );
143 sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
144 sErr += String( e.Message );
145 sal_uInt16 nEntry = mrListBox.InsertEntry( sErr );
146 mrListBox.SetEntryData( nEntry, (void*)e.LineNumber );
152 XMLFileWindow::XMLFileWindow( Window
* pParent
) :
153 Window( pParent
, WB_BORDER
|WB_CLIPCHILDREN
),
159 nStartLine(USHRT_MAX
),
160 eSourceEncoding(gsl_getSystemTextEncoding()),
166 XMLFileWindow::~XMLFileWindow()
170 EndListening( *pTextEngine
);
171 pTextEngine
->RemoveView( pTextView
);
182 void XMLFileWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
184 Window::DataChanged( rDCEvt
);
186 switch ( rDCEvt
.GetType() )
188 case DATACHANGED_SETTINGS
:
189 // ScrollBars neu anordnen bzw. Resize ausloesen, da sich
190 // ScrollBar-Groesse geaendert haben kann. Dazu muss dann im
191 // Resize-Handler aber auch die Groesse der ScrollBars aus
192 // den Settings abgefragt werden.
193 if( rDCEvt
.GetFlags() & SETTINGS_STYLE
)
199 void XMLFileWindow::Resize()
201 // ScrollBars, etc. passiert in Adjust...
204 long nVisY
= pTextView
->GetStartDocPos().Y();
205 pTextView
->ShowCursor();
206 Size
aOutSz( GetOutputSizePixel() );
207 long nMaxVisAreaStart
= pTextView
->GetTextEngine()->GetTextHeight() - aOutSz
.Height();
208 if ( nMaxVisAreaStart
< 0 )
209 nMaxVisAreaStart
= 0;
210 if ( pTextView
->GetStartDocPos().Y() > nMaxVisAreaStart
)
212 Point
aStartDocPos( pTextView
->GetStartDocPos() );
213 aStartDocPos
.Y() = nMaxVisAreaStart
;
214 pTextView
->SetStartDocPos( aStartDocPos
);
215 pTextView
->ShowCursor();
217 long nScrollStd
= GetSettings().GetStyleSettings().GetScrollBarSize();
218 Size
aScrollSz(aOutSz
.Width() - nScrollStd
, nScrollStd
);
219 Point
aScrollPos(0, aOutSz
.Height() - nScrollStd
);
221 pHScrollbar
->SetPosSizePixel( aScrollPos
, aScrollSz
);
223 aScrollSz
.Width() = aScrollSz
.Height();
224 aScrollSz
.Height() = aOutSz
.Height() - aScrollSz
.Height();
225 aScrollPos
= Point(aOutSz
.Width() - nScrollStd
, 0);
227 pVScrollbar
->SetPosSizePixel( aScrollPos
, aScrollSz
);
228 aOutSz
.Width() -= nScrollStd
;
229 aOutSz
.Height() -= nScrollStd
;
230 pOutWin
->SetOutputSizePixel(aOutSz
);
233 // Zeile im ersten Resize setzen
234 if(USHRT_MAX
!= nStartLine
)
236 if(nStartLine
< pTextEngine
->GetParagraphCount())
238 TextSelection
aSel(TextPaM( nStartLine
, 0 ), TextPaM( nStartLine
, 0x0 ));
239 pTextView
->SetSelection(aSel
);
240 pTextView
->ShowCursor();
242 nStartLine
= USHRT_MAX
;
245 if ( nVisY
!= pTextView
->GetStartDocPos().Y() )
251 void TextViewOutWin::DataChanged( const DataChangedEvent
& rDCEvt
)
253 Window::DataChanged( rDCEvt
);
255 switch( rDCEvt
.GetType() )
257 case DATACHANGED_SETTINGS
:
258 // den Settings abgefragt werden.
259 if( rDCEvt
.GetFlags() & SETTINGS_STYLE
)
261 const Color
&rCol
= GetSettings().GetStyleSettings().GetWindowColor();
262 SetBackground( rCol
);
263 Font
aFont( pTextView
->GetTextEngine()->GetFont() );
264 aFont
.SetFillColor( rCol
);
265 pTextView
->GetTextEngine()->SetFont( aFont
);
271 void TextViewOutWin::MouseMove( const MouseEvent
&rEvt
)
274 pTextView
->MouseMove( rEvt
);
277 void TextViewOutWin::MouseButtonUp( const MouseEvent
&rEvt
)
280 pTextView
->MouseButtonUp( rEvt
);
283 void TextViewOutWin::MouseButtonDown( const MouseEvent
&rEvt
)
287 pTextView
->MouseButtonDown( rEvt
);
290 void TextViewOutWin::Command( const CommandEvent
& rCEvt
)
292 switch(rCEvt
.GetCommand())
294 case COMMAND_CONTEXTMENU
:
297 case COMMAND_STARTAUTOSCROLL
:
298 case COMMAND_AUTOSCROLL
:
300 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
301 if( !pWData
|| COMMAND_WHEEL_ZOOM
!= pWData
->GetMode() )
303 ((XMLFileWindow
*)GetParent())->HandleWheelCommand( rCEvt
);
310 pTextView
->Command( rCEvt
);
312 Window::Command(rCEvt
);
316 void TextViewOutWin::KeyInput( const KeyEvent
& rKEvt
)
318 if(!TextEngine::DoesKeyChangeText( rKEvt
))
319 pTextView
->KeyInput( rKEvt
);
322 void TextViewOutWin::Paint( const Rectangle
& rRect
)
324 pTextView
->Paint( rRect
);
327 void XMLFileWindow::CreateTextEngine()
329 const Color
&rCol
= GetSettings().GetStyleSettings().GetWindowColor();
330 pOutWin
= new TextViewOutWin(this, 0);
331 pOutWin
->SetBackground(Wallpaper(rCol
));
332 pOutWin
->SetPointer(Pointer(POINTER_TEXT
));
336 pHScrollbar
= new ScrollBar(this, WB_3DLOOK
|WB_HSCROLL
|WB_DRAG
);
337 pHScrollbar
->SetScrollHdl(LINK(this, XMLFileWindow
, ScrollHdl
));
340 pVScrollbar
= new ScrollBar(this, WB_3DLOOK
|WB_VSCROLL
|WB_DRAG
);
341 pVScrollbar
->SetScrollHdl(LINK(this, XMLFileWindow
, ScrollHdl
));
342 pHScrollbar
->EnableDrag();
345 pTextEngine
= new TextEngine
;
346 pTextView
= new TextView( pTextEngine
, pOutWin
);
347 pTextView
->SetAutoIndentMode(sal_True
);
348 pOutWin
->SetTextView(pTextView
);
350 pTextEngine
->SetUpdateMode( sal_False
);
351 pTextEngine
->InsertView( pTextView
);
354 aFont
.SetTransparent( sal_False
);
355 aFont
.SetFillColor( rCol
);
356 SetPointFont( aFont
);
358 aFont
.SetFillColor( rCol
);
359 pOutWin
->SetFont( aFont
);
360 pTextEngine
->SetFont( aFont
);
362 aSyntaxIdleTimer
.SetTimeout( SYNTAX_HIGHLIGHT_TIMEOUT
);
363 aSyntaxIdleTimer
.SetTimeoutHdl( LINK( this, XMLFileWindow
, SyntaxTimerHdl
) );
365 pTextEngine
->EnableUndo( sal_False
);
366 pTextEngine
->SetUpdateMode( sal_True
);
368 // pTextView->ShowCursor( sal_True, sal_True );
369 pTextView
->HideCursor();
372 StartListening( *pTextEngine
);
375 void XMLFileWindow::SetScrollBarRanges()
377 pHScrollbar
->SetRange( Range( 0, nCurTextWidth
-1 ) );
378 pVScrollbar
->SetRange( Range(0, pTextEngine
->GetTextHeight()-1) );
381 void XMLFileWindow::InitScrollBars()
383 SetScrollBarRanges();
385 Size
aOutSz( pOutWin
->GetOutputSizePixel() );
386 pVScrollbar
->SetVisibleSize( aOutSz
.Height() );
387 pVScrollbar
->SetPageSize( aOutSz
.Height() * 8 / 10 );
388 pVScrollbar
->SetLineSize( pOutWin
->GetTextHeight() );
389 pVScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
390 pHScrollbar
->SetVisibleSize( aOutSz
.Width() );
391 pHScrollbar
->SetPageSize( aOutSz
.Width() * 8 / 10 );
392 pHScrollbar
->SetLineSize( pOutWin
->GetTextWidth( 'x' ) );
393 pHScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().X() );
397 IMPL_LINK(XMLFileWindow
, ScrollHdl
, ScrollBar
*, pScroll
)
399 if(pScroll
== pVScrollbar
)
401 long nDiff
= pTextView
->GetStartDocPos().Y() - pScroll
->GetThumbPos();
402 GetTextView()->Scroll( 0, nDiff
);
403 pTextView
->ShowCursor( sal_False
, sal_True
);
404 pScroll
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
408 long nDiff
= pTextView
->GetStartDocPos().X() - pScroll
->GetThumbPos();
409 GetTextView()->Scroll( nDiff
, 0 );
410 pTextView
->ShowCursor( sal_False
, sal_True
);
411 pScroll
->SetThumbPos( pTextView
->GetStartDocPos().X() );
416 void XMLFileWindow::Notify( SfxBroadcaster
& /* rBC */, const SfxHint
& rHint
)
418 if ( rHint
.ISA( TextHint
) )
420 const TextHint
& rTextHint
= (const TextHint
&)rHint
;
421 if( rTextHint
.GetId() == TEXT_HINT_VIEWSCROLLED
)
423 pHScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().X() );
424 pVScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
426 else if( rTextHint
.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED
)
428 if ( (long)pTextEngine
->GetTextHeight() < pOutWin
->GetOutputSizePixel().Height() )
429 pTextView
->Scroll( 0, pTextView
->GetStartDocPos().Y() );
430 pVScrollbar
->SetThumbPos( pTextView
->GetStartDocPos().Y() );
431 SetScrollBarRanges();
433 else if( rTextHint
.GetId() == TEXT_HINT_FORMATPARA
)
435 DoDelayedSyntaxHighlight( (sal_uInt16
)rTextHint
.GetValue() );
440 void XMLFileWindow::InvalidateWindow()
442 pOutWin
->Invalidate();
443 Window::Invalidate();
447 void XMLFileWindow::Command( const CommandEvent
& rCEvt
)
449 switch(rCEvt
.GetCommand())
452 case COMMAND_STARTAUTOSCROLL
:
453 case COMMAND_AUTOSCROLL
:
455 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
456 if( !pWData
|| COMMAND_WHEEL_ZOOM
!= pWData
->GetMode() )
457 HandleScrollCommand( rCEvt
, pHScrollbar
, pVScrollbar
);
461 Window::Command(rCEvt
);
465 void XMLFileWindow::HandleWheelCommand( const CommandEvent
& rCEvt
)
467 pTextView
->Command(rCEvt
);
468 HandleScrollCommand( rCEvt
, pHScrollbar
, pVScrollbar
);
471 void XMLFileWindow::GetFocus()
473 pOutWin
->GrabFocus();
476 void XMLFileWindow::ShowWindow( const rtl::OUString
& rFileName
)
478 String
aFileName( rFileName
);
479 SvFileStream
aStream( aFileName
, STREAM_READ
);
481 // since the xml files we load are utf-8 encoded, we need to set
482 // this encoding at the SvFileStream, else the TextEngine will
483 // use its default encoding which is not UTF8
484 const sal_Char
*pCharSet
= rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8
);
485 rtl_TextEncoding eDestEnc
= rtl_getTextEncodingFromMimeCharset( pCharSet
);
486 aStream
.SetStreamCharSet( eDestEnc
);
488 if( Read( aStream
) )
490 long nPrevTextWidth
= nCurTextWidth
;
491 nCurTextWidth
= pTextEngine
->CalcTextWidth() + 25; // kleine Toleranz
492 if ( nCurTextWidth
!= nPrevTextWidth
)
493 SetScrollBarRanges();
495 TextPaM
aPaM( pTextView
->CursorStartOfDoc() );
496 TextSelection
aSelection( aPaM
, aPaM
);
497 pTextView
->SetSelection( aSelection
, true );
503 void XMLFileWindow::showLine( sal_Int32 nLine
)
505 TextPaM
aPaM( pTextView
->CursorStartOfDoc() );
507 aPaM
= pTextView
->CursorDown( aPaM
);
509 TextSelection
aSelection( pTextView
->CursorEndOfLine( aPaM
), aPaM
);
510 pTextView
->SetSelection( aSelection
, true );
514 XMLSourceFileDialog::XMLSourceFileDialog( Window
* pParent
, ResMgr
& rResMgr
, const com::sun::star::uno::Reference
< com::sun::star::lang::XMultiServiceFactory
>& rxMSF
)
515 : WorkWindow( pParent
, ResId( DLG_XML_SOURCE_FILE_DIALOG
, rResMgr
) ),
516 mnOutputHeight( LogicToPixel( Size( 80, 80 ), MAP_APPFONT
).Height() ),
520 maPBValidate( this, ResId( PB_VALIDATE
, rResMgr
) )
525 maPBValidate
.SetClickHdl(LINK( this, XMLSourceFileDialog
, ClickHdl_Impl
) );
526 maLBOutput
.SetSelectHdl(LINK(this, XMLSourceFileDialog
, SelectHdl_Impl
) );
527 mpTextWindow
= new XMLFileWindow( this );
528 mpTextWindow
->SetHelpId( HID_XML_FILTER_OUTPUT_WINDOW
);
529 maLBOutput
.SetHelpId( HID_XML_FILTER_TEST_VALIDATE_OUPUT
);
534 XMLSourceFileDialog::~XMLSourceFileDialog()
536 if( maFileURL
.getLength() )
537 osl::File::remove( maFileURL
);
542 void XMLSourceFileDialog::ShowWindow( const rtl::OUString
& rFileName
, const filter_info_impl
* pFilterInfo
)
545 if( maFileURL
.getLength() )
547 osl::File::remove( maFileURL
);
549 mpTextWindow
= new XMLFileWindow( this );
552 maPBValidate
.Enable(sal_True
);
556 mpFilterInfo
= pFilterInfo
;
557 maFileURL
= rFileName
;
558 mpTextWindow
->ShowWindow( rFileName
);
563 void XMLSourceFileDialog::Resize()
565 bool bOutputVisible
= maLBOutput
.IsVisible() != 0;
567 Point
aSpacing( LogicToPixel( Point( 6, 6 ), MAP_APPFONT
) );
568 Size
aButton( maPBValidate
.GetSizePixel() );
570 Size
aDialogSize( GetOutputSizePixel() );
572 // Point aButtonPos( aSpacing.X(), aSpacing.Y() );
573 // maPBValidate.SetPosSizePixel( aButtonPos, aButton );
575 Size
aOutputSize( aDialogSize
.Width(), bOutputVisible
? mnOutputHeight
: 0 );
577 Point
aTextWindowPos( 0, 2* aSpacing
.Y() + aButton
.Height() );
578 Size
aTextWindowSize( aDialogSize
.Width(), aDialogSize
.Height() - aTextWindowPos
.Y() - aOutputSize
.Height() );
580 mpTextWindow
->SetPosSizePixel( aTextWindowPos
, aTextWindowSize
);
584 Point
aOutputPos( 0, aTextWindowPos
.Y() + aTextWindowSize
.Height() );
585 maLBOutput
.SetPosSizePixel( aOutputPos
, aOutputSize
);
590 IMPL_LINK(XMLSourceFileDialog
, SelectHdl_Impl
, ListBox
*, pListBox
)
592 sal_uInt16 nEntry
= pListBox
->GetSelectEntryPos();
593 if( LISTBOX_ENTRY_NOTFOUND
!= nEntry
)
595 int nLine
= (int)(sal_IntPtr
)pListBox
->GetEntryData(nEntry
);
607 IMPL_LINK(XMLSourceFileDialog
, ClickHdl_Impl
, PushButton
*, /* pButton */ )
613 void XMLSourceFileDialog::onValidate()
618 maPBValidate
.Enable(sal_False
);
623 Reference
< XImportFilter
> xImporter( mxMSF
->createInstance( OUString::createFromAscii( "com.sun.star.documentconversion.XSLTValidate" ) ), UNO_QUERY
);
626 osl::File
aInputFile( maFileURL
);
627 /* osl::File::RC rc = */ aInputFile
.open( OpenFlag_Read
);
629 Reference
< XInputStream
> xIS( new comphelper::OSLInputStreamWrapper( aInputFile
) );
631 Sequence
< PropertyValue
> aSourceData(3);
632 aSourceData
[0].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) );
633 aSourceData
[0].Value
<<= xIS
;
635 aSourceData
[1].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ) );
636 aSourceData
[1].Value
<<= maFileURL
;
638 aSourceData
[2].Name
= OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorHandler" ) );
639 Reference
< XErrorHandler
> xHandle( new XMLErrorHandler( this, maLBOutput
) );
640 aSourceData
[2].Value
<<= xHandle
;
642 Reference
< XDocumentHandler
> xWriter( mxMSF
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), UNO_QUERY
);
643 Reference
< XOutputStream
> xOS( mxMSF
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pipe" ) ) ), UNO_QUERY
);
644 Reference
< XActiveDataSource
> xDocSrc( xWriter
, UNO_QUERY
);
645 xDocSrc
->setOutputStream( xOS
);
647 Sequence
< OUString
> aFilterUserData( mpFilterInfo
->getFilterUserData() );
648 xImporter
->importer( aSourceData
, xWriter
, aFilterUserData
);
653 String
sErr( e
.Message
);
654 sal_uInt16 nEntry
= maLBOutput
.InsertEntry( sErr
);
655 maLBOutput
.SetEntryData( nEntry
, (void*)-1 );
658 if( 0 == maLBOutput
.GetEntryCount() )
660 String
sErr( RESID( STR_NO_ERRORS_FOUND
) );
661 sal_uInt16 nEntry
= maLBOutput
.InsertEntry( sErr
);
662 maLBOutput
.SetEntryData( nEntry
, (void*)-1 );
668 void XMLSourceFileDialog::showLine( sal_Int32 nLine
)
670 mpTextWindow
->showLine( nLine
);
674 ///////////////////////////////////////////////////////////////////////
676 void lcl_Highlight(const String
& rSource
, SwTextPortions
& aPortionList
)
678 const sal_Unicode cOpenBracket
= '<';
679 const sal_Unicode cCloseBracket
= '>';
680 const sal_Unicode cSlash
= '/';
681 const sal_Unicode cExclamation
= '!';
682 // const sal_Unicode cQuote = '"';
683 // const sal_Unicode cSQuote = '\'';
684 const sal_Unicode cMinus
= '-';
685 const sal_Unicode cSpace
= ' ';
686 const sal_Unicode cTab
= 0x09;
687 const sal_Unicode cLF
= 0x0a;
688 const sal_Unicode cCR
= 0x0d;
691 const sal_uInt16 nStrLen
= rSource
.Len();
692 sal_uInt16 nInsert
= 0; // Number of inserted Portions
693 sal_uInt16 nActPos
= 0; // Position, at the '<' was found
694 sal_uInt16 nOffset
= 0; // Offset of nActPos for '<'
695 sal_uInt16 nPortStart
= USHRT_MAX
; // For the TextPortion
696 sal_uInt16 nPortEnd
= 0; //
698 while(nActPos
< nStrLen
)
700 svtools::ColorConfigEntry eFoundType
= svtools::HTMLUNKNOWN
;
701 if(rSource
.GetChar(nActPos
) == cOpenBracket
&& nActPos
< nStrLen
- 2 )
703 // 'leere' Portion einfuegen
704 if(nPortEnd
< nActPos
- 1 )
707 // am Anfang nicht verschieben
708 aText
.nStart
= nPortEnd
;
711 aText
.nEnd
= nActPos
- 1;
712 aText
.eType
= svtools::HTMLUNKNOWN
;
713 aPortionList
.push_back( aText
);
716 sal_Unicode cFollowFirst
= rSource
.GetChar((xub_StrLen
)(nActPos
+ 1));
717 sal_Unicode cFollowNext
= rSource
.GetChar((xub_StrLen
)(nActPos
+ 2));
718 if(cExclamation
== cFollowFirst
)
720 // "<!" SGML oder Kommentar
721 if(cMinus
== cFollowNext
&&
722 nActPos
< nStrLen
- 3 && cMinus
== rSource
.GetChar((xub_StrLen
)(nActPos
+ 3)))
724 eFoundType
= svtools::HTMLCOMMENT
;
727 eFoundType
= svtools::HTMLSGML
;
728 nPortStart
= nActPos
;
729 nPortEnd
= nActPos
+ 1;
731 else if(cSlash
== cFollowFirst
)
733 // "</" Slash ignorieren
734 nPortStart
= nActPos
;
738 if(svtools::HTMLUNKNOWN
== eFoundType
)
740 //jetzt koennte hier ein keyword folgen
741 sal_uInt16 nSrchPos
= nActPos
;
742 while(++nSrchPos
< nStrLen
- 1)
744 sal_Unicode cNext
= rSource
.GetChar(nSrchPos
);
745 if( cNext
== cSpace
||
750 else if(cNext
== cCloseBracket
)
755 if(nSrchPos
> nActPos
+ 1)
757 //irgend ein String wurde gefunden
758 String sToken
= rSource
.Copy(nActPos
+ 1, nSrchPos
- nActPos
- 1 );
759 sToken
.ToUpperAscii();
760 // int nToken = ::GetHTMLToken(sToken);
764 eFoundType
= svtools::HTMLKEYWORD
;
766 nPortStart
= nActPos
;
773 DBG_ERROR("Token nicht erkannt!")
774 DBG_ERROR(ByteString(sToken, gsl_getSystemTextEncoding()).GetBuffer())
781 // jetzt muss noch '>' gesucht werden
782 if(svtools::HTMLUNKNOWN
!= eFoundType
)
784 sal_Bool bFound
= sal_False
;
785 for(sal_uInt16 i
= nPortEnd
; i
< nStrLen
; i
++)
786 if(cCloseBracket
== rSource
.GetChar(i
))
792 if(!bFound
&& (eFoundType
== svtools::HTMLCOMMENT
))
794 // Kommentar ohne Ende in dieser Zeile
796 nPortEnd
= nStrLen
- 1;
799 if(bFound
||(eFoundType
== svtools::HTMLCOMMENT
))
801 SwTextPortion aText2
;
803 aText2
.nStart
= nPortStart
+ 1;
804 aText2
.nEnd
= nPortEnd
;
805 aText2
.eType
= eFoundType
;
806 aPortionList
.push_back( aText2
);
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
.push_back( aText
);
826 void XMLFileWindow::DoDelayedSyntaxHighlight( sal_uInt16 nPara
)
828 if ( !bHighlighting
)
830 aSyntaxLineTable
.Insert( nPara
, (void*)(sal_uInt16
)1 );
831 aSyntaxIdleTimer
.Start();
835 void XMLFileWindow::ImpDoHighlight( const String
& rSource
, sal_uInt16 nLineOff
)
837 SwTextPortions aPortionList
;
838 lcl_Highlight(rSource
, aPortionList
);
840 size_t nCount
= aPortionList
.size();
844 SwTextPortion
& rLast
= aPortionList
[nCount
-1];
845 if ( rLast
.nStart
> rLast
.nEnd
) // Nur bis Bug von MD behoeben
848 aPortionList
.pop_back();
854 // Wenn haufig gleiche Farbe, dazwischen Blank ohne Farbe,
855 // ggf. zusammenfassen, oder zumindest das Blank,
856 // damit weniger Attribute
857 sal_Bool bOptimizeHighlight
= sal_True
; // war in der BasicIDE static
858 if ( bOptimizeHighlight
)
860 // Es muessen nur die Blanks und Tabs mit attributiert werden.
861 // Wenn zwei gleiche Attribute hintereinander eingestellt werden,
862 // optimiert das die TextEngine.
863 sal_uInt16 nLastEnd
= 0;
864 for ( size_t i
= 0; i
< nCount
; i
++ )
866 SwTextPortion
& r
= aPortionList
[i
];
867 DBG_ASSERT( r
.nLine
== aPortionList
[0].nLine
, "doch mehrere Zeilen ?" );
868 if ( r
.nStart
> r
.nEnd
) // Nur bis Bug von MD behoeben
871 if ( r
.nStart
> nLastEnd
)
873 // Kann ich mich drauf verlassen, dass alle ausser
874 // Blank und Tab gehighlightet wird ?!
878 if ( ( i
== (nCount
-1) ) && ( r
.nEnd
< rSource
.Len() ) )
879 r
.nEnd
= rSource
.Len();
883 svtools::ColorConfig aConfig
;
884 for ( size_t i
= 0; i
< aPortionList
.size(); i
++ )
886 SwTextPortion
& r
= aPortionList
[i
];
887 if ( r
.nStart
> r
.nEnd
) // Nur bis Bug von MD behoeben
889 // sal_uInt16 nCol = r.eType;
890 if(r
.eType
!= svtools::HTMLSGML
&&
891 r
.eType
!= svtools::HTMLCOMMENT
&&
892 r
.eType
!= svtools::HTMLKEYWORD
&&
893 r
.eType
!= svtools::HTMLUNKNOWN
)
894 r
.eType
= (svtools::ColorConfigEntry
)svtools::HTMLUNKNOWN
;
895 Color
aColor((ColorData
)aConfig
.GetColorValue((svtools::ColorConfigEntry
)r
.eType
).nColor
);
896 sal_uInt16 nLine
= nLineOff
+r
.nLine
; //
897 pTextEngine
->SetAttrib( TextAttribFontColor( aColor
), nLine
, r
.nStart
, r
.nEnd
+1 );
901 IMPL_LINK( XMLFileWindow
, SyntaxTimerHdl
, Timer
*, pTimer
)
903 Time aSyntaxCheckStart
;
904 DBG_ASSERT( pTextView
, "Noch keine View, aber Syntax-Highlight ?!" );
905 pTextEngine
->SetUpdateMode( sal_False
);
907 bHighlighting
= sal_True
;
909 sal_uInt16 nCount
= 0;
910 // zuerst wird der Bereich um dem Cursor bearbeitet
911 TextSelection aSel
= pTextView
->GetSelection();
912 sal_uInt16 nCur
= (sal_uInt16
)aSel
.GetStart().GetPara();
917 if(aSyntaxLineTable
.Count())
918 for(sal_uInt16 i
= 0; i
< 80 && nCount
< 40; i
++, nCur
++)
920 void * p
= aSyntaxLineTable
.Get(nCur
);
923 DoSyntaxHighlight( nCur
);
924 aSyntaxLineTable
.Remove( nCur
);
926 if(!aSyntaxLineTable
.Count())
928 if((Time().GetTime() - aSyntaxCheckStart
.GetTime()) > MAX_HIGHLIGHTTIME
)
930 pTimer
->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT
);
936 // wenn dann noch etwas frei ist, wird von Beginn an weitergearbeitet
937 void* p
= aSyntaxLineTable
.First();
938 while ( p
&& nCount
< MAX_SYNTAX_HIGHLIGHT
)
940 nLine
= (sal_uInt16
)aSyntaxLineTable
.GetCurKey();
941 DoSyntaxHighlight( nLine
);
942 sal_uInt16 nC
= (sal_uInt16
)aSyntaxLineTable
.GetCurKey();
943 p
= aSyntaxLineTable
.Next();
944 aSyntaxLineTable
.Remove(nC
);
946 if(Time().GetTime() - aSyntaxCheckStart
.GetTime() > MAX_HIGHLIGHTTIME
)
948 pTimer
->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT
);
952 // os: #43050# hier wird ein TextView-Problem umpopelt:
953 // waehrend des Highlightings funktionierte das Scrolling nicht
954 TextView
* pTmp
= pTextEngine
->GetActiveView();
955 pTextEngine
->SetActiveView(0);
956 pTextEngine
->SetUpdateMode( sal_True
);
957 pTextEngine
->SetActiveView(pTmp
);
958 pTextView
->ShowCursor(sal_False
, sal_False
);
960 if(aSyntaxLineTable
.Count() && !pTimer
->IsActive())
962 // SyntaxTimerHdl wird gerufen, wenn Text-Aenderung
963 // => gute Gelegenheit, Textbreite zu ermitteln!
964 long nPrevTextWidth
= nCurTextWidth
;
965 nCurTextWidth
= pTextEngine
->CalcTextWidth() + 25; // kleine Toleranz
966 if ( nCurTextWidth
!= nPrevTextWidth
)
967 SetScrollBarRanges();
968 bHighlighting
= sal_False
;
973 void XMLFileWindow::DoSyntaxHighlight( sal_uInt16 nPara
)
975 // Durch das DelayedSyntaxHighlight kann es passieren,
976 // dass die Zeile nicht mehr existiert!
977 if ( nPara
< pTextEngine
->GetParagraphCount() )
979 pTextEngine
->RemoveAttribs( nPara
);
980 String
aSource( pTextEngine
->GetText( nPara
) );
981 pTextEngine
->SetUpdateMode( sal_False
);
982 ImpDoHighlight( aSource
, nPara
);
983 // os: #43050# hier wird ein TextView-Problem umpopelt:
984 // waehrend des Highlightings funktionierte das Scrolling nicht
985 TextView
* pTmp
= pTextEngine
->GetActiveView();
986 pTmp
->SetAutoScroll(sal_False
);
987 pTextEngine
->SetActiveView(0);
988 pTextEngine
->SetUpdateMode( sal_True
);
989 pTextEngine
->SetActiveView(pTmp
);
990 // Bug 72887 show the cursor
991 pTmp
->SetAutoScroll(sal_True
);
992 pTmp
->ShowCursor( sal_False
/*pTmp->IsAutoScroll()*/ );