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