/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xmlfilterdialogstrings.hrc" #include "xmlfiltersettingsdialog.hxx" #include "xmlfileview.hxx" #include "xmlfileview.hrc" #include "xmlfilterhelpids.hrc" #include using namespace osl; using namespace com::sun::star::lang; using namespace com::sun::star::beans; using namespace com::sun::star::uno; using namespace com::sun::star::io; using namespace com::sun::star::xml; using namespace com::sun::star::xml::sax; using ::rtl::OUString; #define MAX_SYNTAX_HIGHLIGHT 20 #define MAX_HIGHLIGHTTIME 200 #define SYNTAX_HIGHLIGHT_TIMEOUT 200 struct SwTextPortion { sal_uInt16 nLine; sal_uInt16 nStart, nEnd; svtools::ColorConfigEntry eType; }; typedef std::deque SwTextPortions; class XMLErrorHandler : public ::cppu::WeakImplHelper1< XErrorHandler > { public: XMLErrorHandler( XMLSourceFileDialog* pParent, ListBox& rListBox ); // Methods virtual void SAL_CALL error( const Any& aSAXParseException ) throw (SAXException, RuntimeException); virtual void SAL_CALL fatalError( const Any& aSAXParseException ) throw (SAXException, RuntimeException); virtual void SAL_CALL warning( const Any& aSAXParseException ) throw (SAXException, RuntimeException); private: XMLSourceFileDialog* mpParent; ListBox& mrListBox; }; XMLErrorHandler::XMLErrorHandler( XMLSourceFileDialog* pParent, ListBox& rListBox ) : mpParent( pParent ), mrListBox( rListBox ) { } // XMLErrorHandler void SAL_CALL XMLErrorHandler::error( const Any& aSAXParseException ) throw (SAXException, RuntimeException) { ::SolarMutexGuard aGuard; SAXParseException e; if( aSAXParseException >>= e ) { String sErr( String::CreateFromInt32( e.LineNumber ) ); sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) ); sErr += String( e.Message ); sal_uInt16 nEntry = mrListBox.InsertEntry( sErr ); mrListBox.SetEntryData( nEntry, (void*)(sal_IntPtr)e.LineNumber ); } } void SAL_CALL XMLErrorHandler::fatalError( const Any& aSAXParseException ) throw (SAXException, RuntimeException) { ::SolarMutexGuard aGuard; SAXParseException e; if( aSAXParseException >>= e ) { String sErr( String::CreateFromInt32( e.LineNumber ) ); sErr += String( RTL_CONSTASCII_USTRINGPARAM( " : " ) ); sErr += String( e.Message ); sal_uInt16 nEntry = mrListBox.InsertEntry( sErr ); mrListBox.SetEntryData( nEntry, (void*)(sal_IntPtr)e.LineNumber ); } } void SAL_CALL XMLErrorHandler::warning( const Any& /* aSAXParseException */ ) throw (SAXException, RuntimeException) { } XMLFileWindow::XMLFileWindow( Window* pParent ) : Window( pParent, WB_BORDER|WB_CLIPCHILDREN ), pTextEngine(0), pOutWin(0), pHScrollbar(0), pVScrollbar(0), nCurTextWidth(0), nStartLine(USHRT_MAX), eSourceEncoding(osl_getThreadTextEncoding()), bHighlighting(false) { CreateTextEngine(); } XMLFileWindow::~XMLFileWindow() { if ( pTextEngine ) { EndListening( *pTextEngine ); pTextEngine->RemoveView( pTextView ); delete pHScrollbar; delete pVScrollbar; delete pTextView; delete pTextEngine; } delete pOutWin; } void XMLFileWindow::DataChanged( const DataChangedEvent& rDCEvt ) { Window::DataChanged( rDCEvt ); switch ( rDCEvt.GetType() ) { case DATACHANGED_SETTINGS: // ScrollBars neu anordnen bzw. Resize ausloesen, da sich // ScrollBar-Groesse geaendert haben kann. Dazu muss dann im // Resize-Handler aber auch die Groesse der ScrollBars aus // den Settings abgefragt werden. if( rDCEvt.GetFlags() & SETTINGS_STYLE ) Resize(); break; } } void XMLFileWindow::Resize() { // ScrollBars, etc. passiert in Adjust... if ( pTextView ) { long nVisY = pTextView->GetStartDocPos().Y(); pTextView->ShowCursor(); Size aOutSz( GetOutputSizePixel() ); long nMaxVisAreaStart = pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height(); if ( nMaxVisAreaStart < 0 ) nMaxVisAreaStart = 0; if ( pTextView->GetStartDocPos().Y() > nMaxVisAreaStart ) { Point aStartDocPos( pTextView->GetStartDocPos() ); aStartDocPos.Y() = nMaxVisAreaStart; pTextView->SetStartDocPos( aStartDocPos ); pTextView->ShowCursor(); } long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize(); Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd ); Point aScrollPos(0, aOutSz.Height() - nScrollStd); pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); aScrollSz.Width() = aScrollSz.Height(); aScrollSz.Height() = aOutSz.Height() - aScrollSz.Height(); aScrollPos = Point(aOutSz.Width() - nScrollStd, 0); pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); aOutSz.Width() -= nScrollStd; aOutSz.Height() -= nScrollStd; pOutWin->SetOutputSizePixel(aOutSz); InitScrollBars(); // Zeile im ersten Resize setzen if(USHRT_MAX != nStartLine) { if(nStartLine < pTextEngine->GetParagraphCount()) { TextSelection aSel(TextPaM( nStartLine, 0 ), TextPaM( nStartLine, 0x0 )); pTextView->SetSelection(aSel); pTextView->ShowCursor(); } nStartLine = USHRT_MAX; } if ( nVisY != pTextView->GetStartDocPos().Y() ) InvalidateWindow(); } } void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt ) { Window::DataChanged( rDCEvt ); switch( rDCEvt.GetType() ) { case DATACHANGED_SETTINGS: // den Settings abgefragt werden. if( rDCEvt.GetFlags() & SETTINGS_STYLE ) { const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); SetBackground( rCol ); Font aFont( pTextView->GetTextEngine()->GetFont() ); aFont.SetFillColor( rCol ); pTextView->GetTextEngine()->SetFont( aFont ); } break; } } void TextViewOutWin::MouseMove( const MouseEvent &rEvt ) { if ( pTextView ) pTextView->MouseMove( rEvt ); } void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt ) { if ( pTextView ) pTextView->MouseButtonUp( rEvt ); } void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt ) { GrabFocus(); if ( pTextView ) pTextView->MouseButtonDown( rEvt ); } void TextViewOutWin::Command( const CommandEvent& rCEvt ) { switch(rCEvt.GetCommand()) { case COMMAND_CONTEXTMENU: break; case COMMAND_WHEEL: case COMMAND_STARTAUTOSCROLL: case COMMAND_AUTOSCROLL: { const CommandWheelData* pWData = rCEvt.GetWheelData(); if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() ) { ((XMLFileWindow*)GetParent())->HandleWheelCommand( rCEvt ); } } break; default: if ( pTextView ) pTextView->Command( rCEvt ); else Window::Command(rCEvt); } } void TextViewOutWin::KeyInput( const KeyEvent& rKEvt ) { if(!TextEngine::DoesKeyChangeText( rKEvt )) pTextView->KeyInput( rKEvt ); } void TextViewOutWin::Paint( const Rectangle& rRect ) { pTextView->Paint( rRect ); } void XMLFileWindow::CreateTextEngine() { const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); pOutWin = new TextViewOutWin(this, 0); pOutWin->SetBackground(Wallpaper(rCol)); pOutWin->SetPointer(Pointer(POINTER_TEXT)); pOutWin->Show(); //Scrollbars anlegen pHScrollbar = new ScrollBar(this, WB_3DLOOK |WB_HSCROLL|WB_DRAG); pHScrollbar->SetScrollHdl(LINK(this, XMLFileWindow, ScrollHdl)); pHScrollbar->Show(); pVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG); pVScrollbar->SetScrollHdl(LINK(this, XMLFileWindow, ScrollHdl)); pHScrollbar->EnableDrag(); pVScrollbar->Show(); pTextEngine = new TextEngine; pTextView = new TextView( pTextEngine, pOutWin ); pTextView->SetAutoIndentMode(sal_True); pOutWin->SetTextView(pTextView); pTextEngine->SetUpdateMode( sal_False ); pTextEngine->InsertView( pTextView ); Font aFont; aFont.SetTransparent( sal_False ); aFont.SetFillColor( rCol ); SetPointFont( aFont ); aFont = GetFont(); aFont.SetFillColor( rCol ); pOutWin->SetFont( aFont ); pTextEngine->SetFont( aFont ); aSyntaxIdleTimer.SetTimeout( SYNTAX_HIGHLIGHT_TIMEOUT ); aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, XMLFileWindow, SyntaxTimerHdl ) ); pTextEngine->EnableUndo( sal_False ); pTextEngine->SetUpdateMode( sal_True ); pTextView->HideCursor(); InitScrollBars(); StartListening( *pTextEngine ); } void XMLFileWindow::SetScrollBarRanges() { pHScrollbar->SetRange( Range( 0, nCurTextWidth-1 ) ); pVScrollbar->SetRange( Range(0, pTextEngine->GetTextHeight()-1) ); } void XMLFileWindow::InitScrollBars() { SetScrollBarRanges(); Size aOutSz( pOutWin->GetOutputSizePixel() ); pVScrollbar->SetVisibleSize( aOutSz.Height() ); pVScrollbar->SetPageSize( aOutSz.Height() * 8 / 10 ); pVScrollbar->SetLineSize( pOutWin->GetTextHeight() ); pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); pHScrollbar->SetVisibleSize( aOutSz.Width() ); pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 ); pHScrollbar->SetLineSize( pOutWin->GetTextWidth( 'x' ) ); pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() ); } IMPL_LINK(XMLFileWindow, ScrollHdl, ScrollBar*, pScroll) { if(pScroll == pVScrollbar) { long nDiff = pTextView->GetStartDocPos().Y() - pScroll->GetThumbPos(); GetTextView()->Scroll( 0, nDiff ); pTextView->ShowCursor( sal_False, sal_True ); pScroll->SetThumbPos( pTextView->GetStartDocPos().Y() ); } else { long nDiff = pTextView->GetStartDocPos().X() - pScroll->GetThumbPos(); GetTextView()->Scroll( nDiff, 0 ); pTextView->ShowCursor( sal_False, sal_True ); pScroll->SetThumbPos( pTextView->GetStartDocPos().X() ); } return 0; } void XMLFileWindow::Notify( SfxBroadcaster& /* rBC */, const SfxHint& rHint ) { if ( rHint.ISA( TextHint ) ) { const TextHint& rTextHint = (const TextHint&)rHint; if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED ) { pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() ); pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); } else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED ) { if ( (long)pTextEngine->GetTextHeight() < pOutWin->GetOutputSizePixel().Height() ) pTextView->Scroll( 0, pTextView->GetStartDocPos().Y() ); pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); SetScrollBarRanges(); } else if( rTextHint.GetId() == TEXT_HINT_FORMATPARA ) { DoDelayedSyntaxHighlight( (sal_uInt16)rTextHint.GetValue() ); } } } void XMLFileWindow::InvalidateWindow() { pOutWin->Invalidate(); Window::Invalidate(); } void XMLFileWindow::Command( const CommandEvent& rCEvt ) { switch(rCEvt.GetCommand()) { case COMMAND_WHEEL: case COMMAND_STARTAUTOSCROLL: case COMMAND_AUTOSCROLL: { const CommandWheelData* pWData = rCEvt.GetWheelData(); if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() ) HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar ); } break; default: Window::Command(rCEvt); } } void XMLFileWindow::HandleWheelCommand( const CommandEvent& rCEvt ) { pTextView->Command(rCEvt); HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar ); } void XMLFileWindow::GetFocus() { pOutWin->GrabFocus(); } void XMLFileWindow::ShowWindow( const rtl::OUString& rFileName ) { String aFileName( rFileName ); SvFileStream aStream( aFileName, STREAM_READ ); // since the xml files we load are utf-8 encoded, we need to set // this encoding at the SvFileStream, else the TextEngine will // use its default encoding which is not UTF8 const sal_Char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 ); rtl_TextEncoding eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet ); aStream.SetStreamCharSet( eDestEnc ); if( Read( aStream ) ) { long nPrevTextWidth = nCurTextWidth; nCurTextWidth = pTextEngine->CalcTextWidth() + 25; // kleine Toleranz if ( nCurTextWidth != nPrevTextWidth ) SetScrollBarRanges(); TextPaM aPaM( pTextView->CursorStartOfDoc() ); TextSelection aSelection( aPaM, aPaM ); pTextView->SetSelection( aSelection, true ); Window::Show(); } } void XMLFileWindow::showLine( sal_Int32 nLine ) { TextPaM aPaM( pTextView->CursorStartOfDoc() ); while( nLine-- ) aPaM = pTextView->CursorDown( aPaM ); TextSelection aSelection( pTextView->CursorEndOfLine( aPaM ), aPaM ); pTextView->SetSelection( aSelection, true ); } XMLSourceFileDialog::XMLSourceFileDialog( Window* pParent, ResMgr& rResMgr, const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rxMSF ) : WorkWindow( pParent, ResId( DLG_XML_SOURCE_FILE_DIALOG, rResMgr ) ), mnOutputHeight( LogicToPixel( Size( 80, 80 ), MAP_APPFONT ).Height() ), mxMSF( rxMSF ), mrResMgr( rResMgr ), maLBOutput( this ), maPBValidate( this, ResId( PB_VALIDATE, rResMgr ) ) { FreeResource(); maPBValidate.SetClickHdl(LINK( this, XMLSourceFileDialog, ClickHdl_Impl ) ); maLBOutput.SetSelectHdl(LINK(this, XMLSourceFileDialog, SelectHdl_Impl ) ); mpTextWindow = new XMLFileWindow( this ); mpTextWindow->SetHelpId( HID_XML_FILTER_OUTPUT_WINDOW ); maLBOutput.SetHelpId( HID_XML_FILTER_TEST_VALIDATE_OUPUT ); Resize(); } XMLSourceFileDialog::~XMLSourceFileDialog() { if( maFileURL.getLength() ) osl::File::remove( maFileURL ); delete mpTextWindow; } void XMLSourceFileDialog::ShowWindow( const rtl::OUString& rFileName, const filter_info_impl* pFilterInfo ) { EnterWait(); if( maFileURL.getLength() ) { osl::File::remove( maFileURL ); delete mpTextWindow; mpTextWindow = new XMLFileWindow( this ); maLBOutput.Hide(); maLBOutput.Clear(); maPBValidate.Enable(sal_True); Resize(); } mpFilterInfo = pFilterInfo; maFileURL = rFileName; mpTextWindow->ShowWindow( rFileName ); WorkWindow::Show(); LeaveWait(); } void XMLSourceFileDialog::Resize() { bool bOutputVisible = maLBOutput.IsVisible() != 0; Point aSpacing( LogicToPixel( Point( 6, 6 ), MAP_APPFONT ) ); Size aButton( maPBValidate.GetSizePixel() ); Size aDialogSize( GetOutputSizePixel() ); Size aOutputSize( aDialogSize.Width(), bOutputVisible ? mnOutputHeight : 0 ); Point aTextWindowPos( 0, 2* aSpacing.Y() + aButton.Height() ); Size aTextWindowSize( aDialogSize.Width(), aDialogSize.Height() - aTextWindowPos.Y() - aOutputSize.Height() ); mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize ); if( bOutputVisible ) { Point aOutputPos( 0, aTextWindowPos.Y() + aTextWindowSize.Height() ); maLBOutput.SetPosSizePixel( aOutputPos, aOutputSize ); } } IMPL_LINK(XMLSourceFileDialog, SelectHdl_Impl, ListBox *, pListBox ) { sal_uInt16 nEntry = pListBox->GetSelectEntryPos(); if( LISTBOX_ENTRY_NOTFOUND != nEntry ) { int nLine = (int)(sal_IntPtr)pListBox->GetEntryData(nEntry); if( -1 != nLine ) { if( nLine > 0 ) nLine--; showLine( nLine ); } } return 0; } IMPL_LINK(XMLSourceFileDialog, ClickHdl_Impl, PushButton *, /* pButton */ ) { onValidate(); return 0; } void XMLSourceFileDialog::onValidate() { EnterWait(); maLBOutput.Show(); maPBValidate.Enable(sal_False); Resize(); try { Reference< XImportFilter > xImporter( mxMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.documentconversion.XSLTValidate" )) ), UNO_QUERY ); if( xImporter.is() ) { osl::File aInputFile( maFileURL ); /* osl::File::RC rc = */ aInputFile.open( osl_File_OpenFlag_Read ); Reference< XInputStream > xIS( new comphelper::OSLInputStreamWrapper( aInputFile ) ); Sequence< PropertyValue > aSourceData(3); aSourceData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) ); aSourceData[0].Value <<= xIS; aSourceData[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ) ); aSourceData[1].Value <<= maFileURL; aSourceData[2].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ErrorHandler" ) ); Reference< XErrorHandler > xHandle( new XMLErrorHandler( this, maLBOutput ) ); aSourceData[2].Value <<= xHandle; Reference< XDocumentHandler > xWriter( mxMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), UNO_QUERY ); Reference< XOutputStream > xOS( mxMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pipe" ) ) ), UNO_QUERY ); Reference< XActiveDataSource > xDocSrc( xWriter, UNO_QUERY ); xDocSrc->setOutputStream( xOS ); Sequence< OUString > aFilterUserData( mpFilterInfo->getFilterUserData() ); xImporter->importer( aSourceData, xWriter, aFilterUserData ); } } catch(const Exception& e) { String sErr( e.Message ); sal_uInt16 nEntry = maLBOutput.InsertEntry( sErr ); maLBOutput.SetEntryData( nEntry, (void*)-1 ); } if( 0 == maLBOutput.GetEntryCount() ) { String sErr( RESID( STR_NO_ERRORS_FOUND ) ); sal_uInt16 nEntry = maLBOutput.InsertEntry( sErr ); maLBOutput.SetEntryData( nEntry, (void*)-1 ); } LeaveWait(); } void XMLSourceFileDialog::showLine( sal_Int32 nLine ) { mpTextWindow->showLine( nLine ); } /////////////////////////////////////////////////////////////////////// void lcl_Highlight(const String& rSource, SwTextPortions& aPortionList) { const sal_Unicode cOpenBracket = '<'; const sal_Unicode cCloseBracket= '>'; const sal_Unicode cSlash = '/'; const sal_Unicode cExclamation = '!'; const sal_Unicode cMinus = '-'; const sal_Unicode cSpace = ' '; const sal_Unicode cTab = 0x09; const sal_Unicode cLF = 0x0a; const sal_Unicode cCR = 0x0d; const sal_uInt16 nStrLen = rSource.Len(); sal_uInt16 nInsert = 0; // Number of inserted Portions sal_uInt16 nActPos = 0; // Position, at the '<' was found sal_uInt16 nOffset = 0; // Offset of nActPos for '<' sal_uInt16 nPortStart = USHRT_MAX; // For the TextPortion sal_uInt16 nPortEnd = 0; // SwTextPortion aText; while(nActPos < nStrLen) { svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN; if(rSource.GetChar(nActPos) == cOpenBracket && nActPos < nStrLen - 2 ) { // 'leere' Portion einfuegen if(nPortEnd < nActPos - 1 ) { aText.nLine = 0; // am Anfang nicht verschieben aText.nStart = nPortEnd; if(nInsert) aText.nStart += 1; aText.nEnd = nActPos - 1; aText.eType = svtools::HTMLUNKNOWN; aPortionList.push_back( aText ); nInsert++; } sal_Unicode cFollowFirst = rSource.GetChar((xub_StrLen)(nActPos + 1)); sal_Unicode cFollowNext = rSource.GetChar((xub_StrLen)(nActPos + 2)); if(cExclamation == cFollowFirst) { // " nActPos + 1) { //irgend ein String wurde gefunden String sToken = rSource.Copy(nActPos + 1, nSrchPos - nActPos - 1 ); sToken.ToUpperAscii(); { //Token gefunden eFoundType = svtools::HTMLKEYWORD; nPortEnd = nSrchPos; nPortStart = nActPos; } } } // jetzt muss noch '>' gesucht werden if(svtools::HTMLUNKNOWN != eFoundType) { sal_Bool bFound = sal_False; for(sal_uInt16 i = nPortEnd; i < nStrLen; i++) if(cCloseBracket == rSource.GetChar(i)) { bFound = sal_True; nPortEnd = i; break; } if(!bFound && (eFoundType == svtools::HTMLCOMMENT)) { // Kommentar ohne Ende in dieser Zeile bFound = sal_True; nPortEnd = nStrLen - 1; } if(bFound ||(eFoundType == svtools::HTMLCOMMENT)) { SwTextPortion aText2; aText2.nLine = 0; aText2.nStart = nPortStart + 1; aText2.nEnd = nPortEnd; aText2.eType = eFoundType; aPortionList.push_back( aText2 ); nInsert++; eFoundType = svtools::HTMLUNKNOWN; } } } nActPos++; } if(nInsert && nPortEnd < nActPos - 1) { aText.nLine = 0; aText.nStart = nPortEnd + 1; aText.nEnd = nActPos - 1; aText.eType = svtools::HTMLUNKNOWN; aPortionList.push_back( aText ); nInsert++; } } void XMLFileWindow::DoDelayedSyntaxHighlight( sal_uInt16 nPara ) { if ( !bHighlighting ) { aSyntaxLineTable.Insert( nPara, (void*)(sal_uInt16)1 ); aSyntaxIdleTimer.Start(); } } void XMLFileWindow::ImpDoHighlight( const String& rSource, sal_uInt16 nLineOff ) { SwTextPortions aPortionList; lcl_Highlight(rSource, aPortionList); size_t nCount = aPortionList.size(); if ( !nCount ) return; SwTextPortion& rLast = aPortionList[nCount-1]; if ( rLast.nStart > rLast.nEnd ) // Nur bis Bug von MD behoeben { nCount--; aPortionList.pop_back(); if ( !nCount ) return; } // Evtl. Optimieren: // Wenn haufig gleiche Farbe, dazwischen Blank ohne Farbe, // ggf. zusammenfassen, oder zumindest das Blank, // damit weniger Attribute sal_Bool bOptimizeHighlight = sal_True; // war in der BasicIDE static if ( bOptimizeHighlight ) { // Es muessen nur die Blanks und Tabs mit attributiert werden. // Wenn zwei gleiche Attribute hintereinander eingestellt werden, // optimiert das die TextEngine. sal_uInt16 nLastEnd = 0; for ( size_t i = 0; i < nCount; i++ ) { SwTextPortion& r = aPortionList[i]; DBG_ASSERT( r.nLine == aPortionList[0].nLine, "doch mehrere Zeilen ?" ); if ( r.nStart > r.nEnd ) // Nur bis Bug von MD behoeben continue; if ( r.nStart > nLastEnd ) { // Kann ich mich drauf verlassen, dass alle ausser // Blank und Tab gehighlightet wird ?! r.nStart = nLastEnd; } nLastEnd = r.nEnd+1; if ( ( i == (nCount-1) ) && ( r.nEnd < rSource.Len() ) ) r.nEnd = rSource.Len(); } } svtools::ColorConfig aConfig; for ( size_t i = 0; i < aPortionList.size(); i++ ) { SwTextPortion& r = aPortionList[i]; if ( r.nStart > r.nEnd ) // Nur bis Bug von MD behoeben continue; if(r.eType != svtools::HTMLSGML && r.eType != svtools::HTMLCOMMENT && r.eType != svtools::HTMLKEYWORD && r.eType != svtools::HTMLUNKNOWN) r.eType = (svtools::ColorConfigEntry)svtools::HTMLUNKNOWN; Color aColor((ColorData)aConfig.GetColorValue((svtools::ColorConfigEntry)r.eType).nColor); sal_uInt16 nLine = nLineOff+r.nLine; // pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLine, r.nStart, r.nEnd+1 ); } } IMPL_LINK( XMLFileWindow, SyntaxTimerHdl, Timer *, pTimer ) { Time aSyntaxCheckStart( Time::SYSTEM ); DBG_ASSERT( pTextView, "Noch keine View, aber Syntax-Highlight ?!" ); pTextEngine->SetUpdateMode( sal_False ); bHighlighting = sal_True; sal_uInt16 nLine; sal_uInt16 nCount = 0; // zuerst wird der Bereich um dem Cursor bearbeitet TextSelection aSel = pTextView->GetSelection(); sal_uInt16 nCur = (sal_uInt16)aSel.GetStart().GetPara(); if(nCur > 40) nCur -= 40; else nCur = 0; if(aSyntaxLineTable.Count()) for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++) { void * p = aSyntaxLineTable.Get(nCur); if(p) { DoSyntaxHighlight( nCur ); aSyntaxLineTable.Remove( nCur ); nCount++; if(!aSyntaxLineTable.Count()) break; if((Time( Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME ) { pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT ); break; } } } // wenn dann noch etwas frei ist, wird von Beginn an weitergearbeitet void* p = aSyntaxLineTable.First(); while ( p && nCount < MAX_SYNTAX_HIGHLIGHT) { nLine = (sal_uInt16)aSyntaxLineTable.GetCurKey(); DoSyntaxHighlight( nLine ); sal_uInt16 nC = (sal_uInt16)aSyntaxLineTable.GetCurKey(); p = aSyntaxLineTable.Next(); aSyntaxLineTable.Remove(nC); nCount ++; if(Time( Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME) { pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT ); break; } } // os: #43050# hier wird ein TextView-Problem umpopelt: // waehrend des Highlightings funktionierte das Scrolling nicht TextView* pTmp = pTextEngine->GetActiveView(); pTextEngine->SetActiveView(0); pTextEngine->SetUpdateMode( sal_True ); pTextEngine->SetActiveView(pTmp); pTextView->ShowCursor(sal_False, sal_False); if(aSyntaxLineTable.Count() && !pTimer->IsActive()) pTimer->Start(); // SyntaxTimerHdl wird gerufen, wenn Text-Aenderung // => gute Gelegenheit, Textbreite zu ermitteln! long nPrevTextWidth = nCurTextWidth; nCurTextWidth = pTextEngine->CalcTextWidth() + 25; // kleine Toleranz if ( nCurTextWidth != nPrevTextWidth ) SetScrollBarRanges(); bHighlighting = sal_False; return 0; } void XMLFileWindow::DoSyntaxHighlight( sal_uInt16 nPara ) { // Durch das DelayedSyntaxHighlight kann es passieren, // dass die Zeile nicht mehr existiert! if ( nPara < pTextEngine->GetParagraphCount() ) { pTextEngine->RemoveAttribs( nPara ); String aSource( pTextEngine->GetText( nPara ) ); pTextEngine->SetUpdateMode( sal_False ); ImpDoHighlight( aSource, nPara ); // os: #43050# hier wird ein TextView-Problem umpopelt: // waehrend des Highlightings funktionierte das Scrolling nicht TextView* pTmp = pTextEngine->GetActiveView(); pTmp->SetAutoScroll(sal_False); pTextEngine->SetActiveView(0); pTextEngine->SetUpdateMode( sal_True ); pTextEngine->SetActiveView(pTmp); // Bug 72887 show the cursor pTmp->SetAutoScroll(sal_True); pTmp->ShowCursor( sal_False/*pTmp->IsAutoScroll()*/ ); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */