/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include #include // International #include #include #include using namespace ::com::sun::star; // ------------------------------------------------------------------------- // class ExtTextEngine // ------------------------------------------------------------------------- ExtTextEngine::ExtTextEngine() : maGroupChars( String::CreateFromAscii( "(){}[]", 6 ) ) { } ExtTextEngine::~ExtTextEngine() { } TextSelection ExtTextEngine::MatchGroup( const TextPaM& rCursor ) const { TextSelection aSel( rCursor ); sal_uInt16 nPos = rCursor.GetIndex(); sal_uLong nPara = rCursor.GetPara(); sal_uLong nParas = GetParagraphCount(); if ( ( nPara < nParas ) && ( nPos < GetTextLen( nPara ) ) ) { sal_uInt16 nMatchChar = maGroupChars.Search( GetText( rCursor.GetPara() ).GetChar( nPos ) ); if ( nMatchChar != STRING_NOTFOUND ) { if ( ( nMatchChar % 2 ) == 0 ) { // Vorwaerts suchen... sal_Unicode nSC = maGroupChars.GetChar( nMatchChar ); sal_Unicode nEC = maGroupChars.GetChar( nMatchChar+1 ); sal_uInt16 nCur = nPos+1; sal_uInt16 nLevel = 1; while ( nLevel && ( nPara < nParas ) ) { XubString aStr = GetText( nPara ); while ( nCur < aStr.Len() ) { if ( aStr.GetChar( nCur ) == nSC ) nLevel++; else if ( aStr.GetChar( nCur ) == nEC ) { nLevel--; if ( !nLevel ) break; // while nCur... } nCur++; } if ( nLevel ) { nPara++; nCur = 0; } } if ( nLevel == 0 ) // gefunden { aSel.GetStart() = rCursor; aSel.GetEnd() = TextPaM( nPara, nCur+1 ); } } else { // Rueckwaerts suchen... xub_Unicode nEC = maGroupChars.GetChar( nMatchChar ); xub_Unicode nSC = maGroupChars.GetChar( nMatchChar-1 ); sal_uInt16 nCur = rCursor.GetIndex()-1; sal_uInt16 nLevel = 1; while ( nLevel ) { if ( GetTextLen( nPara ) ) { XubString aStr = GetText( nPara ); while ( nCur ) { if ( aStr.GetChar( nCur ) == nSC ) { nLevel--; if ( !nLevel ) break; // while nCur... } else if ( aStr.GetChar( nCur ) == nEC ) nLevel++; nCur--; } } if ( nLevel ) { if ( nPara ) { nPara--; nCur = GetTextLen( nPara )-1; // egal ob negativ, weil if Len() } else break; } } if ( nLevel == 0 ) // gefunden { aSel.GetStart() = rCursor; aSel.GetStart().GetIndex()++; // hinter das Zeichen aSel.GetEnd() = TextPaM( nPara, nCur ); } } } } return aSel; } sal_Bool ExtTextEngine::Search( TextSelection& rSel, const util::SearchOptions& rSearchOptions, sal_Bool bForward ) { TextSelection aSel( rSel ); aSel.Justify(); sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) ); TextPaM aStartPaM( aSel.GetEnd() ); if ( aSel.HasRange() && ( ( bSearchInSelection && bForward ) || ( !bSearchInSelection && !bForward ) ) ) { aStartPaM = aSel.GetStart(); } bool bFound = false; sal_uLong nStartNode, nEndNode; if ( bSearchInSelection ) nEndNode = bForward ? aSel.GetEnd().GetPara() : aSel.GetStart().GetPara(); else nEndNode = bForward ? (GetParagraphCount()-1) : 0; nStartNode = aStartPaM.GetPara(); util::SearchOptions aOptions( rSearchOptions ); aOptions.Locale = Application::GetSettings().GetLocale(); utl::TextSearch aSearcher( rSearchOptions ); // ueber die Absaetze iterieren... for ( sal_uLong nNode = nStartNode; bForward ? ( nNode <= nEndNode) : ( nNode >= nEndNode ); bForward ? nNode++ : nNode-- ) { String aText = GetText( nNode ); sal_uInt16 nStartPos = 0; sal_uInt16 nEndPos = aText.Len(); if ( nNode == nStartNode ) { if ( bForward ) nStartPos = aStartPaM.GetIndex(); else nEndPos = aStartPaM.GetIndex(); } if ( ( nNode == nEndNode ) && bSearchInSelection ) { if ( bForward ) nEndPos = aSel.GetEnd().GetIndex(); else nStartPos = aSel.GetStart().GetIndex(); } if ( bForward ) bFound = aSearcher.SearchFrwrd( aText, &nStartPos, &nEndPos ); else bFound = aSearcher.SearchBkwrd( aText, &nEndPos, &nStartPos ); if ( bFound ) { rSel.GetStart().GetPara() = nNode; rSel.GetStart().GetIndex() = nStartPos; rSel.GetEnd().GetPara() = nNode; rSel.GetEnd().GetIndex() = nEndPos; // Ueber den Absatz selektieren? // Select over the paragraph? // FIXME This should be max long... if( nEndPos == sal::static_int_cast(-1) ) // sal_uInt16 for 0 and -1 ! { if ( (rSel.GetEnd().GetPara()+1) < GetParagraphCount() ) { rSel.GetEnd().GetPara()++; rSel.GetEnd().GetIndex() = 0; } else { rSel.GetEnd().GetIndex() = nStartPos; bFound = false; } } break; } if ( !bForward && !nNode ) // Bei rueckwaertsuche, wenn nEndNode = 0: break; } return bFound; } // ------------------------------------------------------------------------- // class ExtTextView // ------------------------------------------------------------------------- ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow ) : TextView( pEng, pWindow ) { } ExtTextView::~ExtTextView() { } sal_Bool ExtTextView::MatchGroup() { TextSelection aTmpSel( GetSelection() ); aTmpSel.Justify(); if ( ( aTmpSel.GetStart().GetPara() != aTmpSel.GetEnd().GetPara() ) || ( ( aTmpSel.GetEnd().GetIndex() - aTmpSel.GetStart().GetIndex() ) > 1 ) ) { return sal_False; } TextSelection aMatchSel = ((ExtTextEngine*)GetTextEngine())->MatchGroup( aTmpSel.GetStart() ); if ( aMatchSel.HasRange() ) SetSelection( aMatchSel ); return aMatchSel.HasRange() ? sal_True : sal_False; } sal_Bool ExtTextView::Search( const util::SearchOptions& rSearchOptions, sal_Bool bForward ) { sal_Bool bFound = sal_False; TextSelection aSel( GetSelection() ); if ( ((ExtTextEngine*)GetTextEngine())->Search( aSel, rSearchOptions, bForward ) ) { bFound = sal_True; // Erstmal den Anfang des Wortes als Selektion einstellen, // damit das ganze Wort in den sichtbaren Bereich kommt. SetSelection( aSel.GetStart() ); ShowCursor( sal_True, sal_False ); } else { aSel = GetSelection().GetEnd(); } SetSelection( aSel ); ShowCursor(); return bFound; } sal_uInt16 ExtTextView::Replace( const util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward ) { sal_uInt16 nFound = 0; if ( !bAll ) { if ( GetSelection().HasRange() ) { InsertText( rSearchOptions.replaceString ); nFound = 1; Search( rSearchOptions, bForward ); // gleich zum naechsten } else { if( Search( rSearchOptions, bForward ) ) nFound = 1; } } else { // Der Writer ersetzt alle, vom Anfang bis Ende... ExtTextEngine* pTextEngine = (ExtTextEngine*)GetTextEngine(); // HideSelection(); TextSelection aSel; sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) ); if ( bSearchInSelection ) { aSel = GetSelection(); aSel.Justify(); } TextSelection aSearchSel( aSel ); sal_Bool bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True ); if ( bFound ) pTextEngine->UndoActionStart(); while ( bFound ) { nFound++; TextPaM aNewStart = pTextEngine->ImpInsertText( aSel, rSearchOptions.replaceString ); aSel = aSearchSel; aSel.GetStart() = aNewStart; bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True ); } if ( nFound ) { SetSelection( aSel.GetStart() ); pTextEngine->FormatAndUpdate( this ); pTextEngine->UndoActionEnd(); } } return nFound; } sal_Bool ExtTextView::ImpIndentBlock( sal_Bool bRight ) { sal_Bool bDone = sal_False; TextSelection aSel = GetSelection(); aSel.Justify(); HideSelection(); GetTextEngine()->UndoActionStart(); sal_uLong nStartPara = aSel.GetStart().GetPara(); sal_uLong nEndPara = aSel.GetEnd().GetPara(); if ( aSel.HasRange() && !aSel.GetEnd().GetIndex() ) { nEndPara--; // den dann nicht einruecken... } for ( sal_uLong nPara = nStartPara; nPara <= nEndPara; nPara++ ) { if ( bRight ) { // Tabs hinzufuegen GetTextEngine()->ImpInsertText( TextPaM( nPara, 0 ), '\t' ); bDone = sal_True; } else { // Tabs/Blanks entfernen String aText = GetTextEngine()->GetText( nPara ); if ( aText.Len() && ( ( aText.GetChar( 0 ) == '\t' ) || ( aText.GetChar( 0 ) == ' ' ) ) ) { GetTextEngine()->ImpDeleteText( TextSelection( TextPaM( nPara, 0 ), TextPaM( nPara, 1 ) ) ); bDone = sal_True; } } } GetTextEngine()->UndoActionEnd(); sal_Bool bRange = aSel.HasRange(); if ( bRight ) { aSel.GetStart().GetIndex()++; if ( bRange && ( aSel.GetEnd().GetPara() == nEndPara ) ) aSel.GetEnd().GetIndex()++; } else { if ( aSel.GetStart().GetIndex() ) aSel.GetStart().GetIndex()--; if ( bRange && aSel.GetEnd().GetIndex() ) aSel.GetEnd().GetIndex()--; } ImpSetSelection( aSel ); GetTextEngine()->FormatAndUpdate( this ); return bDone; } sal_Bool ExtTextView::IndentBlock() { return ImpIndentBlock( sal_True ); } sal_Bool ExtTextView::UnindentBlock() { return ImpIndentBlock( sal_False ); }