1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
27 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
28 #include <com/sun/star/xml/sax/SAXParseException.hpp>
29 #include <com/sun/star/xml/XImportFilter.hpp>
30 #include <com/sun/star/io/XActiveDataSource.hpp>
31 #include <comphelper/oslfile2streamwrap.hxx>
32 
33 #include <rtl/tencinfo.h>
34 #include <vcl/svapp.hxx>
35 #include <vos/mutex.hxx>
36 #include <svtools/textview.hxx>
37 #ifndef _SCRBAR_HXX //autogen
38 #include <vcl/scrbar.hxx>
39 #endif
40 #include <tools/stream.hxx>
41 #include <tools/time.hxx>
42 #include <osl/file.hxx>
43 #include <vcl/msgbox.hxx>
44 #include <svtools/colorcfg.hxx>
45 #include <svtools/htmltokn.h>
46 #include <svtools/txtattr.hxx>
47 
48 #include "xmlfilterdialogstrings.hrc"
49 #include "xmlfiltersettingsdialog.hxx"
50 #include "xmlfileview.hxx"
51 #include "xmlfileview.hrc"
52 #include "xmlfilterhelpids.hrc"
53 
54 #include <deque>
55 
56 using namespace rtl;
57 using namespace osl;
58 using namespace com::sun::star::lang;
59 using namespace com::sun::star::beans;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::io;
62 using namespace com::sun::star::xml;
63 using namespace com::sun::star::xml::sax;
64 
65 
66 #define MAX_SYNTAX_HIGHLIGHT 20
67 #define MAX_HIGHLIGHTTIME 200
68 #define SYNTAX_HIGHLIGHT_TIMEOUT 200
69 
70 
71 struct SwTextPortion
72 {
73 	sal_uInt16 nLine;
74 	sal_uInt16 nStart, nEnd;
75 	svtools::ColorConfigEntry eType;
76 };
77 
78 typedef std::deque<SwTextPortion> SwTextPortions;
79 
80 class XMLErrorHandler : public ::cppu::WeakImplHelper1< XErrorHandler >
81 {
82 public:
83 	XMLErrorHandler( XMLSourceFileDialog* pParent, ListBox& rListBox );
84 
85     // Methods
86     virtual void SAL_CALL error( const Any& aSAXParseException ) throw (SAXException, RuntimeException);
87     virtual void SAL_CALL fatalError( const Any& aSAXParseException ) throw (SAXException, RuntimeException);
88     virtual void SAL_CALL warning( const Any& aSAXParseException ) throw (SAXException, RuntimeException);
89 
90 private:
91 	XMLSourceFileDialog*	mpParent;
92 	ListBox&	mrListBox;
93 };
94 
XMLErrorHandler(XMLSourceFileDialog * pParent,ListBox & rListBox)95 XMLErrorHandler::XMLErrorHandler( XMLSourceFileDialog* pParent, ListBox& rListBox )
96 :	mpParent( pParent ),
97 	mrListBox( rListBox )
98 {
99 }
100 
101 // XMLErrorHandler
error(const Any & aSAXParseException)102 void SAL_CALL XMLErrorHandler::error( const Any& aSAXParseException ) throw (SAXException, RuntimeException)
103 {
104 	vos::OGuard aGuard( Application::GetSolarMutex() );
105 
106 	SAXParseException e;
107 	if( aSAXParseException >>= e )
108 	{
109 		String sErr( String::CreateFromInt32( e.LineNumber ) );
110 		sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
111 		sErr += String( e.Message );
112 		sal_uInt16 nEntry = mrListBox.InsertEntry( sErr );
113 		mrListBox.SetEntryData( nEntry, (void*)e.LineNumber );
114 	}
115 }
116 
fatalError(const Any & aSAXParseException)117 void SAL_CALL XMLErrorHandler::fatalError( const Any& aSAXParseException ) throw (SAXException, RuntimeException)
118 {
119 	vos::OGuard aGuard( Application::GetSolarMutex() );
120 
121 	SAXParseException e;
122 	if( aSAXParseException >>= e )
123 	{
124 		String sErr( String::CreateFromInt32( e.LineNumber ) );
125 		sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
126 		sErr += String( e.Message );
127 		sal_uInt16 nEntry = mrListBox.InsertEntry( sErr );
128 		mrListBox.SetEntryData( nEntry, (void*)e.LineNumber );
129 	}
130 }
131 
warning(const Any &)132 void SAL_CALL XMLErrorHandler::warning( const Any& /* aSAXParseException */ ) throw (SAXException, RuntimeException)
133 {
134 /*
135 	SAXParseException e;
136 	if( aSAXParseException >>= e )
137 	{
138 		String sErr( String::CreateFromInt32( e.LineNumber ) );
139 		sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) );
140 		sErr += String( e.Message );
141 		sal_uInt16 nEntry = mrListBox.InsertEntry( sErr );
142 		mrListBox.SetEntryData( nEntry, (void*)e.LineNumber );
143 	}
144 */
145 }
146 
147 
XMLFileWindow(Window * pParent)148 XMLFileWindow::XMLFileWindow( Window* pParent ) :
149 	Window( pParent, WB_BORDER|WB_CLIPCHILDREN ),
150 	pTextEngine(0),
151 	pOutWin(0),
152 	pHScrollbar(0),
153 	pVScrollbar(0),
154 	nCurTextWidth(0),
155     nStartLine(SAL_MAX_UINT32),
156     eSourceEncoding(gsl_getSystemTextEncoding()),
157 	bHighlighting(false)
158 {
159 	CreateTextEngine();
160 }
161 
~XMLFileWindow()162 XMLFileWindow::~XMLFileWindow()
163 {
164 	if ( pTextEngine )
165 	{
166 		EndListening( *pTextEngine );
167 		pTextEngine->RemoveView( pTextView );
168 
169 		delete pHScrollbar;
170 		delete pVScrollbar;
171 
172 		delete pTextView;
173 		delete pTextEngine;
174 	}
175 	delete pOutWin;
176 }
177 
DataChanged(const DataChangedEvent & rDCEvt)178 void XMLFileWindow::DataChanged( const DataChangedEvent& rDCEvt )
179 {
180 	Window::DataChanged( rDCEvt );
181 
182 	switch ( rDCEvt.GetType() )
183 	{
184 	case DATACHANGED_SETTINGS:
185 		// ScrollBars neu anordnen bzw. Resize ausloesen, da sich
186 		// ScrollBar-Groesse geaendert haben kann. Dazu muss dann im
187 		// Resize-Handler aber auch die Groesse der ScrollBars aus
188 		// den Settings abgefragt werden.
189 		if( rDCEvt.GetFlags() & SETTINGS_STYLE )
190 			Resize();
191 		break;
192 	}
193 }
194 
Resize()195 void XMLFileWindow::Resize()
196 {
197 	// ScrollBars, etc. passiert in Adjust...
198 	if ( pTextView )
199 	{
200 		long nVisY = pTextView->GetStartDocPos().Y();
201 		pTextView->ShowCursor();
202 		Size aOutSz( GetOutputSizePixel() );
203 		long nMaxVisAreaStart = pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height();
204 		if ( nMaxVisAreaStart < 0 )
205 			nMaxVisAreaStart = 0;
206 		if ( pTextView->GetStartDocPos().Y() > nMaxVisAreaStart )
207 		{
208 			Point aStartDocPos( pTextView->GetStartDocPos() );
209 			aStartDocPos.Y() = nMaxVisAreaStart;
210 			pTextView->SetStartDocPos( aStartDocPos );
211 			pTextView->ShowCursor();
212 		}
213         long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize();
214 		Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd );
215 		Point aScrollPos(0, aOutSz.Height() - nScrollStd);
216 
217 		pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz);
218 
219 		aScrollSz.Width() = aScrollSz.Height();
220 		aScrollSz.Height() = aOutSz.Height() - aScrollSz.Height();
221 		aScrollPos = Point(aOutSz.Width() - nScrollStd, 0);
222 
223 		pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz);
224 		aOutSz.Width() 	-= nScrollStd;
225 		aOutSz.Height() 	-= nScrollStd;
226 		pOutWin->SetOutputSizePixel(aOutSz);
227         InitScrollBars();
228 
229         // Zeile im ersten Resize setzen
230 		if(USHRT_MAX != nStartLine)
231 		{
232 			if(nStartLine < pTextEngine->GetParagraphCount())
233 			{
234 				TextSelection aSel(TextPaM( nStartLine, 0 ), TextPaM( nStartLine, 0x0 ));
235 				pTextView->SetSelection(aSel);
236 				pTextView->ShowCursor();
237 			}
238 			nStartLine = USHRT_MAX;
239 		}
240 
241 		if ( nVisY != pTextView->GetStartDocPos().Y() )
242 			InvalidateWindow();
243 	}
244 
245 }
246 
DataChanged(const DataChangedEvent & rDCEvt)247 void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt )
248 {
249 	Window::DataChanged( rDCEvt );
250 
251 	switch( rDCEvt.GetType() )
252 	{
253 	case DATACHANGED_SETTINGS:
254 		// den Settings abgefragt werden.
255 		if( rDCEvt.GetFlags() & SETTINGS_STYLE )
256 		{
257 			const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor();
258 			SetBackground( rCol );
259 			Font aFont( pTextView->GetTextEngine()->GetFont() );
260 			aFont.SetFillColor( rCol );
261 			pTextView->GetTextEngine()->SetFont( aFont );
262 		}
263 		break;
264 	}
265 }
266 
MouseMove(const MouseEvent & rEvt)267 void TextViewOutWin::MouseMove( const MouseEvent &rEvt )
268 {
269 	if ( pTextView )
270 		pTextView->MouseMove( rEvt );
271 }
272 
MouseButtonUp(const MouseEvent & rEvt)273 void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt )
274 {
275 	if ( pTextView )
276 		pTextView->MouseButtonUp( rEvt );
277 }
278 
MouseButtonDown(const MouseEvent & rEvt)279 void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt )
280 {
281 	GrabFocus();
282 	if ( pTextView )
283 		pTextView->MouseButtonDown( rEvt );
284 }
285 
Command(const CommandEvent & rCEvt)286 void TextViewOutWin::Command( const CommandEvent& rCEvt )
287 {
288 	switch(rCEvt.GetCommand())
289 	{
290 		case COMMAND_CONTEXTMENU:
291 		break;
292 		case COMMAND_WHEEL:
293 		case COMMAND_STARTAUTOSCROLL:
294 		case COMMAND_AUTOSCROLL:
295 		{
296 			const CommandWheelData* pWData = rCEvt.GetWheelData();
297 			if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() )
298 			{
299 				((XMLFileWindow*)GetParent())->HandleWheelCommand( rCEvt );
300 			}
301 		}
302 		break;
303 
304 		default:
305 			if ( pTextView )
306 				pTextView->Command( rCEvt );
307 		else
308 			Window::Command(rCEvt);
309 	}
310 }
311 
KeyInput(const KeyEvent & rKEvt)312 void TextViewOutWin::KeyInput( const KeyEvent& rKEvt )
313 {
314 	if(!TextEngine::DoesKeyChangeText( rKEvt ))
315 		pTextView->KeyInput( rKEvt );
316 }
317 
Paint(const Rectangle & rRect)318 void  TextViewOutWin::Paint( const Rectangle& rRect )
319 {
320 	pTextView->Paint( rRect );
321 }
322 
CreateTextEngine()323 void XMLFileWindow::CreateTextEngine()
324 {
325 	const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor();
326 	pOutWin = new TextViewOutWin(this, 0);
327 	pOutWin->SetBackground(Wallpaper(rCol));
328 	pOutWin->SetPointer(Pointer(POINTER_TEXT));
329 	pOutWin->Show();
330 
331 	//Scrollbars anlegen
332 	pHScrollbar = new ScrollBar(this, WB_3DLOOK |WB_HSCROLL|WB_DRAG);
333 	pHScrollbar->SetScrollHdl(LINK(this, XMLFileWindow, ScrollHdl));
334 	pHScrollbar->Show();
335 
336 	pVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG);
337 	pVScrollbar->SetScrollHdl(LINK(this, XMLFileWindow, ScrollHdl));
338 	pHScrollbar->EnableDrag();
339 	pVScrollbar->Show();
340 
341 	pTextEngine = new TextEngine;
342 	pTextView = new TextView( pTextEngine, pOutWin );
343 	pTextView->SetAutoIndentMode(sal_True);
344 	pOutWin->SetTextView(pTextView);
345 
346 	pTextEngine->SetUpdateMode( sal_False );
347 	pTextEngine->InsertView( pTextView );
348 
349 	Font aFont;
350 	aFont.SetTransparent( sal_False );
351 	aFont.SetFillColor( rCol );
352 	SetPointFont( aFont );
353 	aFont = GetFont();
354 	aFont.SetFillColor( rCol );
355 	pOutWin->SetFont( aFont );
356 	pTextEngine->SetFont( aFont );
357 
358     aSyntaxIdleTimer.SetTimeout( SYNTAX_HIGHLIGHT_TIMEOUT );
359 	aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, XMLFileWindow, SyntaxTimerHdl ) );
360 
361 	pTextEngine->EnableUndo( sal_False );
362 	pTextEngine->SetUpdateMode( sal_True );
363 
364 //	pTextView->ShowCursor( sal_True, sal_True );
365 	pTextView->HideCursor();
366 
367 	InitScrollBars();
368 	StartListening( *pTextEngine );
369 }
370 
SetScrollBarRanges()371 void XMLFileWindow::SetScrollBarRanges()
372 {
373 	pHScrollbar->SetRange( Range( 0, nCurTextWidth-1 ) );
374 	pVScrollbar->SetRange( Range(0, pTextEngine->GetTextHeight()-1) );
375 }
376 
InitScrollBars()377 void XMLFileWindow::InitScrollBars()
378 {
379 	SetScrollBarRanges();
380 
381     Size aOutSz( pOutWin->GetOutputSizePixel() );
382     pVScrollbar->SetVisibleSize( aOutSz.Height() );
383 	pVScrollbar->SetPageSize(  aOutSz.Height() * 8 / 10 );
384 	pVScrollbar->SetLineSize( pOutWin->GetTextHeight() );
385 	pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() );
386 	pHScrollbar->SetVisibleSize( aOutSz.Width() );
387 	pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 );
388 	pHScrollbar->SetLineSize( pOutWin->GetTextWidth( 'x' ) );
389 	pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() );
390 
391 }
392 
IMPL_LINK(XMLFileWindow,ScrollHdl,ScrollBar *,pScroll)393 IMPL_LINK(XMLFileWindow, ScrollHdl, ScrollBar*, pScroll)
394 {
395 	if(pScroll == pVScrollbar)
396 	{
397 		long nDiff = pTextView->GetStartDocPos().Y() - pScroll->GetThumbPos();
398 		GetTextView()->Scroll( 0, nDiff );
399 		pTextView->ShowCursor( sal_False, sal_True );
400 		pScroll->SetThumbPos( pTextView->GetStartDocPos().Y() );
401 	}
402 	else
403 	{
404 		long nDiff = pTextView->GetStartDocPos().X() - pScroll->GetThumbPos();
405 		GetTextView()->Scroll( nDiff, 0 );
406 		pTextView->ShowCursor( sal_False, sal_True );
407 		pScroll->SetThumbPos( pTextView->GetStartDocPos().X() );
408 	}
409 	return 0;
410 }
411 
Notify(SfxBroadcaster &,const SfxHint & rHint)412 void XMLFileWindow::Notify( SfxBroadcaster& /* rBC */, const SfxHint& rHint )
413 {
414 	if ( rHint.ISA( TextHint ) )
415 	{
416 		const TextHint& rTextHint = (const TextHint&)rHint;
417 		if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED )
418 		{
419 			pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() );
420 			pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() );
421 		}
422 		else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
423 		{
424 			if ( (long)pTextEngine->GetTextHeight() < pOutWin->GetOutputSizePixel().Height() )
425 				pTextView->Scroll( 0, pTextView->GetStartDocPos().Y() );
426 			pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() );
427 			SetScrollBarRanges();
428 		}
429 		else if( rTextHint.GetId() == TEXT_HINT_FORMATPARA )
430 		{
431             DoDelayedSyntaxHighlight( rTextHint.GetValue() );
432 		}
433 	}
434 }
435 
InvalidateWindow()436 void XMLFileWindow::InvalidateWindow()
437 {
438 	pOutWin->Invalidate();
439 	Window::Invalidate();
440 
441 }
442 
Command(const CommandEvent & rCEvt)443 void XMLFileWindow::Command( const CommandEvent& rCEvt )
444 {
445 	switch(rCEvt.GetCommand())
446 	{
447 		case COMMAND_WHEEL:
448 		case COMMAND_STARTAUTOSCROLL:
449 		case COMMAND_AUTOSCROLL:
450 		{
451 			const CommandWheelData* pWData = rCEvt.GetWheelData();
452 			if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() )
453 				HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar );
454 		}
455 		break;
456 		default:
457 			Window::Command(rCEvt);
458 	}
459 }
460 
HandleWheelCommand(const CommandEvent & rCEvt)461 void XMLFileWindow::HandleWheelCommand( const CommandEvent& rCEvt )
462 {
463 	pTextView->Command(rCEvt);
464 	HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar );
465 }
466 
GetFocus()467 void XMLFileWindow::GetFocus()
468 {
469 	pOutWin->GrabFocus();
470 }
471 
ShowWindow(const rtl::OUString & rFileName)472 void XMLFileWindow::ShowWindow( const rtl::OUString& rFileName )
473 {
474 	String aFileName( rFileName );
475 	SvFileStream aStream( aFileName, STREAM_READ );
476 
477 	// since the xml files we load are utf-8 encoded, we need to set
478 	// this encoding at the SvFileStream, else the TextEngine will
479 	// use its default encoding which is not UTF8
480 	const sal_Char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
481 	rtl_TextEncoding eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet );
482 	aStream.SetStreamCharSet( eDestEnc );
483 
484 	if( Read( aStream ) )
485 	{
486 		long nPrevTextWidth = nCurTextWidth;
487 		nCurTextWidth = pTextEngine->CalcTextWidth() + 25;	// kleine Toleranz
488 		if ( nCurTextWidth != nPrevTextWidth )
489 			SetScrollBarRanges();
490 
491 		TextPaM aPaM( pTextView->CursorStartOfDoc() );
492 		TextSelection aSelection( aPaM, aPaM );
493 		pTextView->SetSelection( aSelection, true );
494 
495 		Window::Show();
496 	}
497 }
498 
showLine(sal_Int32 nLine)499 void XMLFileWindow::showLine( sal_Int32 nLine )
500 {
501 	TextPaM aPaM( pTextView->CursorStartOfDoc() );
502 	while( nLine-- )
503 		aPaM = pTextView->CursorDown( aPaM );
504 
505 	TextSelection aSelection( pTextView->CursorEndOfLine( aPaM ), aPaM );
506 	pTextView->SetSelection( aSelection, true );
507 }
508 
509 
XMLSourceFileDialog(Window * pParent,ResMgr & rResMgr,const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> & rxMSF)510 XMLSourceFileDialog::XMLSourceFileDialog( Window* pParent, ResMgr& rResMgr, const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rxMSF  )
511 :	WorkWindow( pParent, ResId( DLG_XML_SOURCE_FILE_DIALOG, rResMgr ) ),
512 	mnOutputHeight( LogicToPixel( Size( 80, 80 ), MAP_APPFONT ).Height() ),
513 	mxMSF( rxMSF ),
514 	mrResMgr( rResMgr ),
515 	maLBOutput( this ),
516 	maPBValidate( this, ResId( PB_VALIDATE, rResMgr ) )
517 {
518 
519 	FreeResource();
520 
521 	maPBValidate.SetClickHdl(LINK( this, XMLSourceFileDialog, ClickHdl_Impl ) );
522 	maLBOutput.SetSelectHdl(LINK(this, XMLSourceFileDialog, SelectHdl_Impl ) );
523 	mpTextWindow = new XMLFileWindow( this );
524 	mpTextWindow->SetHelpId( HID_XML_FILTER_OUTPUT_WINDOW );
525 	maLBOutput.SetHelpId( HID_XML_FILTER_TEST_VALIDATE_OUPUT );
526 
527 	Resize();
528 }
529 
~XMLSourceFileDialog()530 XMLSourceFileDialog::~XMLSourceFileDialog()
531 {
532 	if( maFileURL.getLength() )
533 		osl::File::remove( maFileURL );
534 
535 	delete mpTextWindow;
536 }
537 
ShowWindow(const rtl::OUString & rFileName,const filter_info_impl * pFilterInfo)538 void XMLSourceFileDialog::ShowWindow( const rtl::OUString& rFileName, const filter_info_impl* pFilterInfo )
539 {
540 	EnterWait();
541 	if( maFileURL.getLength() )
542 	{
543 		osl::File::remove( maFileURL );
544 		delete mpTextWindow;
545 		mpTextWindow = new XMLFileWindow( this );
546 		maLBOutput.Hide();
547 		maLBOutput.Clear();
548 		maPBValidate.Enable(sal_True);
549 		Resize();
550 	}
551 
552 	mpFilterInfo = pFilterInfo;
553 	maFileURL = rFileName;
554 	mpTextWindow->ShowWindow( rFileName );
555 	WorkWindow::Show();
556 	LeaveWait();
557 }
558 
Resize()559 void XMLSourceFileDialog::Resize()
560 {
561 	bool bOutputVisible = maLBOutput.IsVisible() != 0;
562 
563 	Point aSpacing( LogicToPixel( Point( 6, 6 ), MAP_APPFONT ) );
564 	Size aButton( maPBValidate.GetSizePixel() );
565 
566 	Size aDialogSize( GetOutputSizePixel() );
567 
568 //	Point aButtonPos( aSpacing.X(), aSpacing.Y() );
569 //	maPBValidate.SetPosSizePixel( aButtonPos, aButton );
570 
571 	Size aOutputSize( aDialogSize.Width(), bOutputVisible ? mnOutputHeight : 0 );
572 
573 	Point aTextWindowPos( 0, 2* aSpacing.Y() + aButton.Height() );
574 	Size aTextWindowSize( aDialogSize.Width(), aDialogSize.Height() - aTextWindowPos.Y() - aOutputSize.Height()  );
575 
576 	mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
577 
578 	if( bOutputVisible )
579 	{
580 		Point aOutputPos( 0, aTextWindowPos.Y() + aTextWindowSize.Height() );
581 		maLBOutput.SetPosSizePixel( aOutputPos, aOutputSize );
582 	}
583 }
584 
585 
IMPL_LINK(XMLSourceFileDialog,SelectHdl_Impl,ListBox *,pListBox)586 IMPL_LINK(XMLSourceFileDialog, SelectHdl_Impl, ListBox *, pListBox )
587 {
588 	sal_uInt16 nEntry = pListBox->GetSelectEntryPos();
589 	if( LISTBOX_ENTRY_NOTFOUND != nEntry )
590 	{
591 		int nLine = (int)(sal_IntPtr)pListBox->GetEntryData(nEntry);
592 		if( -1 != nLine )
593 		{
594 			if( nLine > 0 )
595 				nLine--;
596 
597 			showLine( nLine );
598 		}
599 	}
600 	return 0;
601 }
602 
603 IMPL_LINK(XMLSourceFileDialog, ClickHdl_Impl, PushButton *, /* pButton */ )
604 {
605 	onValidate();
606 	return 0;
607 }
608 
onValidate()609 void XMLSourceFileDialog::onValidate()
610 {
611 	EnterWait();
612 
613 	maLBOutput.Show();
614 	maPBValidate.Enable(sal_False);
615 	Resize();
616 
617 	try
618 	{
619 		Reference< XImportFilter > xImporter( mxMSF->createInstance( OUString::createFromAscii( "com.sun.star.documentconversion.XSLTValidate" ) ), UNO_QUERY );
620 		if( xImporter.is() )
621 		{
622 			osl::File aInputFile( maFileURL );
623 			/* osl::File::RC rc = */ aInputFile.open( OpenFlag_Read );
624 
625 			Reference< XInputStream > xIS( new comphelper::OSLInputStreamWrapper( aInputFile ) );
626 
627 			Sequence< PropertyValue > aSourceData(3);
628 			aSourceData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) );
629 			aSourceData[0].Value <<= xIS;
630 
631 			aSourceData[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ) );
632 			aSourceData[1].Value <<= maFileURL;
633 
634 			aSourceData[2].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorHandler" ) );
635 			Reference< XErrorHandler > xHandle( new XMLErrorHandler( this, maLBOutput ) );
636 			aSourceData[2].Value <<= xHandle;
637 
638 			Reference< XDocumentHandler > xWriter( mxMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), UNO_QUERY );
639 			Reference< XOutputStream > xOS( mxMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pipe" ) ) ), UNO_QUERY );
640 			Reference< XActiveDataSource > xDocSrc( xWriter, UNO_QUERY );
641 			xDocSrc->setOutputStream( xOS );
642 
643 			Sequence< OUString > aFilterUserData( mpFilterInfo->getFilterUserData() );
644 			xImporter->importer( aSourceData, xWriter, aFilterUserData );
645 		}
646 	}
647 	catch(Exception& e)
648 	{
649 		String sErr( e.Message );
650 		sal_uInt16 nEntry = maLBOutput.InsertEntry( sErr );
651 		maLBOutput.SetEntryData( nEntry, (void*)-1 );
652 	}
653 
654 	if( 0 == maLBOutput.GetEntryCount() )
655 	{
656 		String sErr( RESID( STR_NO_ERRORS_FOUND ) );
657 		sal_uInt16 nEntry = maLBOutput.InsertEntry( sErr );
658 		maLBOutput.SetEntryData( nEntry, (void*)-1 );
659 	}
660 
661 	LeaveWait();
662 }
663 
showLine(sal_Int32 nLine)664 void XMLSourceFileDialog::showLine( sal_Int32 nLine )
665 {
666 	mpTextWindow->showLine( nLine );
667 }
668 
669 
670 ///////////////////////////////////////////////////////////////////////
671 
lcl_Highlight(const String & rSource,SwTextPortions & aPortionList)672 void lcl_Highlight(const String& rSource, SwTextPortions& aPortionList)
673 {
674 	const sal_Unicode cOpenBracket = '<';
675 	const sal_Unicode cCloseBracket= '>';
676 	const sal_Unicode cSlash		= '/';
677 	const sal_Unicode cExclamation = '!';
678 //	const sal_Unicode cQuote		= '"';
679 //	const sal_Unicode cSQuote      = '\'';
680 	const sal_Unicode cMinus		= '-';
681 	const sal_Unicode cSpace		= ' ';
682 	const sal_Unicode cTab			= 0x09;
683 	const sal_Unicode cLF          = 0x0a;
684 	const sal_Unicode cCR          = 0x0d;
685 
686 
687 	const sal_uInt16 nStrLen = rSource.Len();
688 	sal_uInt16 nInsert = 0;			// Number of inserted Portions
689 	sal_uInt16 nActPos = 0;			// Position, at the '<' was found
690 	sal_uInt16 nOffset = 0; 		// Offset of nActPos for '<'
691 	sal_uInt16 nPortStart = USHRT_MAX; 	// For the TextPortion
692 	sal_uInt16 nPortEnd  = 	0;  //
693 	SwTextPortion aText;
694 	while(nActPos < nStrLen)
695 	{
696 		svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN;
697 		if(rSource.GetChar(nActPos) == cOpenBracket && nActPos < nStrLen - 2 )
698 		{
699 			// 'leere' Portion einfuegen
700 			if(nPortEnd < nActPos - 1 )
701 			{
702 				aText.nLine = 0;
703 				// am Anfang nicht verschieben
704 				aText.nStart = nPortEnd;
705 				if(nInsert)
706 					aText.nStart += 1;
707 				aText.nEnd = nActPos - 1;
708 				aText.eType = svtools::HTMLUNKNOWN;
709 				aPortionList.push_back( aText );
710 				nInsert++;
711 			}
712 			sal_Unicode cFollowFirst = rSource.GetChar((xub_StrLen)(nActPos + 1));
713 			sal_Unicode cFollowNext = rSource.GetChar((xub_StrLen)(nActPos + 2));
714 			if(cExclamation == cFollowFirst)
715 			{
716 				// "<!" SGML oder Kommentar
717 				if(cMinus == cFollowNext &&
718 					nActPos < nStrLen - 3 && cMinus == rSource.GetChar((xub_StrLen)(nActPos + 3)))
719 				{
720 					eFoundType = svtools::HTMLCOMMENT;
721 				}
722 				else
723 					eFoundType = svtools::HTMLSGML;
724 				nPortStart = nActPos;
725 				nPortEnd = nActPos + 1;
726 			}
727 			else if(cSlash == cFollowFirst)
728 			{
729 				// "</" Slash ignorieren
730 				nPortStart = nActPos;
731 				nActPos++;
732 				nOffset++;
733 			}
734 			if(svtools::HTMLUNKNOWN == eFoundType)
735 			{
736 				//jetzt koennte hier ein keyword folgen
737 				sal_uInt16 nSrchPos = nActPos;
738 				while(++nSrchPos < nStrLen - 1)
739 				{
740 					sal_Unicode cNext = rSource.GetChar(nSrchPos);
741 					if( cNext == cSpace	||
742 						cNext == cTab 	||
743 						cNext == cLF 	||
744 						cNext == cCR)
745 						break;
746 					else if(cNext == cCloseBracket)
747 					{
748 						break;
749 					}
750 				}
751 				if(nSrchPos > nActPos + 1)
752 				{
753 					//irgend ein String wurde gefunden
754 					String sToken = rSource.Copy(nActPos + 1, nSrchPos - nActPos - 1 );
755 					sToken.ToUpperAscii();
756 //					int nToken = ::GetHTMLToken(sToken);
757 //					if(nToken)
758 					{
759 						//Token gefunden
760 						eFoundType = svtools::HTMLKEYWORD;
761 						nPortEnd = nSrchPos;
762 						nPortStart = nActPos;
763 					}
764 /*
765 					else
766 					{
767 						//was war das denn?
768 #ifdef DEBUG
769 						DBG_ERROR("Token nicht erkannt!")
770 						DBG_ERROR(ByteString(sToken, gsl_getSystemTextEncoding()).GetBuffer())
771 #endif
772 					}
773 */
774 
775 				}
776 			}
777 			// jetzt muss noch '>' gesucht werden
778 			if(svtools::HTMLUNKNOWN != eFoundType)
779 			{
780 				sal_Bool bFound = sal_False;
781 				for(sal_uInt16 i = nPortEnd; i < nStrLen; i++)
782 					if(cCloseBracket == rSource.GetChar(i))
783 					{
784 						bFound = sal_True;
785 						nPortEnd = i;
786 						break;
787 					}
788 				if(!bFound && (eFoundType == svtools::HTMLCOMMENT))
789 				{
790 					// Kommentar ohne Ende in dieser Zeile
791 					bFound  = sal_True;
792 					nPortEnd = nStrLen - 1;
793 				}
794 
795 				if(bFound ||(eFoundType == svtools::HTMLCOMMENT))
796 				{
797 					SwTextPortion aText2;
798 					aText2.nLine = 0;
799 					aText2.nStart = nPortStart + 1;
800 					aText2.nEnd = nPortEnd;
801 					aText2.eType = eFoundType;
802 					aPortionList.push_back( aText2 );
803 					nInsert++;
804 					eFoundType = svtools::HTMLUNKNOWN;
805 				}
806 
807 			}
808 		}
809 		nActPos++;
810 	}
811 	if(nInsert && nPortEnd < nActPos - 1)
812 	{
813 		aText.nLine = 0;
814 		aText.nStart = nPortEnd + 1;
815 		aText.nEnd = nActPos - 1;
816 		aText.eType = svtools::HTMLUNKNOWN;
817 		aPortionList.push_back( aText );
818 		nInsert++;
819 	}
820 }
821 
DoDelayedSyntaxHighlight(sal_uInt32 nPara)822 void XMLFileWindow::DoDelayedSyntaxHighlight( sal_uInt32 nPara )
823 {
824 	if ( !bHighlighting )
825 	{
826 		aSyntaxLineTable.Insert( nPara, (void*)(sal_uInt16)1 );
827 		aSyntaxIdleTimer.Start();
828 	}
829 }
830 
ImpDoHighlight(const String & rSource,sal_uInt32 nLineOff)831 void XMLFileWindow::ImpDoHighlight( const String& rSource, sal_uInt32 nLineOff )
832 {
833 	SwTextPortions aPortionList;
834 	lcl_Highlight(rSource, aPortionList);
835 
836 	size_t nCount = aPortionList.size();
837 	if ( !nCount )
838 		return;
839 
840 	SwTextPortion& rLast = aPortionList[nCount-1];
841 	if ( rLast.nStart > rLast.nEnd ) 	// Nur bis Bug von MD behoeben
842 	{
843 		nCount--;
844 		aPortionList.pop_back();
845 		if ( !nCount )
846 			return;
847 	}
848 
849 	// Evtl. Optimieren:
850 	// Wenn haufig gleiche Farbe, dazwischen Blank ohne Farbe,
851 	// ggf. zusammenfassen, oder zumindest das Blank,
852 	// damit weniger Attribute
853 	sal_Bool bOptimizeHighlight = sal_True; // war in der BasicIDE static
854 	if ( bOptimizeHighlight )
855 	{
856 		// Es muessen nur die Blanks und Tabs mit attributiert werden.
857 		// Wenn zwei gleiche Attribute hintereinander eingestellt werden,
858 		// optimiert das die TextEngine.
859 		sal_uInt16 nLastEnd = 0;
860 		for ( size_t i = 0; i < nCount; i++ )
861 		{
862 			SwTextPortion& r = aPortionList[i];
863 			DBG_ASSERT( r.nLine == aPortionList[0].nLine, "doch mehrere Zeilen ?" );
864 			if ( r.nStart > r.nEnd ) 	// Nur bis Bug von MD behoeben
865 				continue;
866 
867 			if ( r.nStart > nLastEnd )
868 			{
869 				// Kann ich mich drauf verlassen, dass alle ausser
870 				// Blank und Tab gehighlightet wird ?!
871 				r.nStart = nLastEnd;
872 			}
873 			nLastEnd = r.nEnd+1;
874 			if ( ( i == (nCount-1) ) && ( r.nEnd < rSource.Len() ) )
875 				r.nEnd = rSource.Len();
876 		}
877 	}
878 
879 	svtools::ColorConfig aConfig;
880 	for ( size_t i = 0; i < aPortionList.size(); i++ )
881 	{
882 		SwTextPortion& r = aPortionList[i];
883 		if ( r.nStart > r.nEnd ) 	// Nur bis Bug von MD behoeben
884 			continue;
885 //		sal_uInt16 nCol = r.eType;
886         if(r.eType !=  svtools::HTMLSGML    &&
887             r.eType != svtools::HTMLCOMMENT &&
888             r.eType != svtools::HTMLKEYWORD &&
889             r.eType != svtools::HTMLUNKNOWN)
890                 r.eType = (svtools::ColorConfigEntry)svtools::HTMLUNKNOWN;
891         Color aColor((ColorData)aConfig.GetColorValue((svtools::ColorConfigEntry)r.eType).nColor);
892         sal_uInt32 nLine = nLineOff+r.nLine; //
893         pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLine, r.nStart, r.nEnd+1 );
894 	}
895 }
896 
IMPL_LINK(XMLFileWindow,SyntaxTimerHdl,Timer *,pTimer)897 IMPL_LINK( XMLFileWindow, SyntaxTimerHdl, Timer *, pTimer )
898 {
899     Time aSyntaxCheckStart;
900     DBG_ASSERT( pTextView, "Noch keine View, aber Syntax-Highlight ?!" );
901 	pTextEngine->SetUpdateMode( sal_False );
902 
903 	bHighlighting = sal_True;
904 	sal_uInt32 nLine;
905 	sal_uInt16 nCount  = 0;
906 	// zuerst wird der Bereich um dem Cursor bearbeitet
907 	TextSelection aSel = pTextView->GetSelection();
908     sal_uInt32 nCur = aSel.GetStart().GetPara();
909 	if(nCur > 40)
910 		nCur -= 40;
911 	else
912 		nCur = 0;
913 	if(aSyntaxLineTable.Count())
914 		for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++)
915 		{
916 			void * p = aSyntaxLineTable.Get(nCur);
917 			if(p)
918 			{
919 				DoSyntaxHighlight( nCur );
920 				aSyntaxLineTable.Remove( nCur );
921 				nCount++;
922                 if(!aSyntaxLineTable.Count())
923                     break;
924                 if((Time().GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME )
925                 {
926                     pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT );
927                     break;
928                 }
929             }
930 		}
931 
932 	// wenn dann noch etwas frei ist, wird von Beginn an weitergearbeitet
933 	void* p = aSyntaxLineTable.First();
934 	while ( p && nCount < MAX_SYNTAX_HIGHLIGHT)
935 	{
936 		nLine = (sal_uInt32)aSyntaxLineTable.GetCurKey();
937 		DoSyntaxHighlight( nLine );
938 		sal_uInt16 nC = (sal_uInt16)aSyntaxLineTable.GetCurKey();
939 		p = aSyntaxLineTable.Next();
940 		aSyntaxLineTable.Remove(nC);
941 		nCount ++;
942         if(Time().GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME)
943         {
944             pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT );
945             break;
946         }
947 	}
948 	// os: #43050# hier wird ein TextView-Problem umpopelt:
949 	// waehrend des Highlightings funktionierte das Scrolling nicht
950 	TextView* pTmp = pTextEngine->GetActiveView();
951 	pTextEngine->SetActiveView(0);
952 	pTextEngine->SetUpdateMode( sal_True );
953 	pTextEngine->SetActiveView(pTmp);
954 	pTextView->ShowCursor(sal_False, sal_False);
955 
956 	if(aSyntaxLineTable.Count() && !pTimer->IsActive())
957 		pTimer->Start();
958 	// SyntaxTimerHdl wird gerufen, wenn Text-Aenderung
959 	// => gute Gelegenheit, Textbreite zu ermitteln!
960 	long nPrevTextWidth = nCurTextWidth;
961 	nCurTextWidth = pTextEngine->CalcTextWidth() + 25;	// kleine Toleranz
962 	if ( nCurTextWidth != nPrevTextWidth )
963 		SetScrollBarRanges();
964 	bHighlighting = sal_False;
965 
966     return 0;
967 }
968 
DoSyntaxHighlight(sal_uInt32 nPara)969 void XMLFileWindow::DoSyntaxHighlight( sal_uInt32 nPara )
970 {
971 	// Durch das DelayedSyntaxHighlight kann es passieren,
972 	// dass die Zeile nicht mehr existiert!
973 	if ( nPara < pTextEngine->GetParagraphCount() )
974 	{
975 		pTextEngine->RemoveAttribs( nPara );
976 		String aSource( pTextEngine->GetText( nPara ) );
977 		pTextEngine->SetUpdateMode( sal_False );
978 		ImpDoHighlight( aSource, nPara );
979 		// os: #43050# hier wird ein TextView-Problem umpopelt:
980 		// waehrend des Highlightings funktionierte das Scrolling nicht
981 		TextView* pTmp = pTextEngine->GetActiveView();
982 		pTmp->SetAutoScroll(sal_False);
983 		pTextEngine->SetActiveView(0);
984 		pTextEngine->SetUpdateMode( sal_True );
985 		pTextEngine->SetActiveView(pTmp);
986 		// Bug 72887 show the cursor
987 		pTmp->SetAutoScroll(sal_True);
988 		pTmp->ShowCursor( sal_False/*pTmp->IsAutoScroll()*/ );
989 	}
990 }
991