xref: /AOO41X/main/filter/source/xsltdialog/xmlfileview.cxx (revision 9e0fc027f109ec4ffcb6033aeec742a099701108)
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(USHRT_MAX),
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( (sal_uInt16)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_uInt16 nPara)822 void XMLFileWindow::DoDelayedSyntaxHighlight( sal_uInt16 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_uInt16 nLineOff)831 void XMLFileWindow::ImpDoHighlight( const String& rSource, sal_uInt16 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_uInt16 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_uInt16 nLine;
905     sal_uInt16 nCount  = 0;
906     // zuerst wird der Bereich um dem Cursor bearbeitet
907     TextSelection aSel = pTextView->GetSelection();
908     sal_uInt16 nCur = (sal_uInt16)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_uInt16)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_uInt16 nPara)969 void XMLFileWindow::DoSyntaxHighlight( sal_uInt16 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