merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / edit / xtextedt.cxx
blob91b4025e25b79305958e85c21ffc91b84d149185
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xtextedt.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <svtools/xtextedt.hxx>
35 #include <vcl/svapp.hxx> // International
36 #include <unotools/textsearch.hxx>
37 #include <com/sun/star/util/SearchOptions.hpp>
38 #include <com/sun/star/util/SearchFlags.hpp>
40 using namespace ::com::sun::star;
44 \f// -------------------------------------------------------------------------
45 // class ExtTextEngine
46 // -------------------------------------------------------------------------
47 ExtTextEngine::ExtTextEngine() : maGroupChars( String::CreateFromAscii( "(){}[]", 6 ) )
51 ExtTextEngine::~ExtTextEngine()
55 TextSelection ExtTextEngine::MatchGroup( const TextPaM& rCursor ) const
57 TextSelection aSel( rCursor );
58 USHORT nPos = rCursor.GetIndex();
59 ULONG nPara = rCursor.GetPara();
60 ULONG nParas = GetParagraphCount();
61 if ( ( nPara < nParas ) && ( nPos < GetTextLen( nPara ) ) )
63 USHORT nMatchChar = maGroupChars.Search( GetText( rCursor.GetPara() ).GetChar( nPos ) );
64 if ( nMatchChar != STRING_NOTFOUND )
66 if ( ( nMatchChar % 2 ) == 0 )
68 // Vorwaerts suchen...
69 sal_Unicode nSC = maGroupChars.GetChar( nMatchChar );
70 sal_Unicode nEC = maGroupChars.GetChar( nMatchChar+1 );
72 USHORT nCur = nPos+1;
73 USHORT nLevel = 1;
74 while ( nLevel && ( nPara < nParas ) )
76 XubString aStr = GetText( nPara );
77 while ( nCur < aStr.Len() )
79 if ( aStr.GetChar( nCur ) == nSC )
80 nLevel++;
81 else if ( aStr.GetChar( nCur ) == nEC )
83 nLevel--;
84 if ( !nLevel )
85 break; // while nCur...
87 nCur++;
90 if ( nLevel )
92 nPara++;
93 nCur = 0;
96 if ( nLevel == 0 ) // gefunden
98 aSel.GetStart() = rCursor;
99 aSel.GetEnd() = TextPaM( nPara, nCur+1 );
102 else
104 // Rueckwaerts suchen...
105 xub_Unicode nEC = maGroupChars.GetChar( nMatchChar );
106 xub_Unicode nSC = maGroupChars.GetChar( nMatchChar-1 );
108 USHORT nCur = rCursor.GetIndex()-1;
109 USHORT nLevel = 1;
110 while ( nLevel )
112 if ( GetTextLen( nPara ) )
114 XubString aStr = GetText( nPara );
115 while ( nCur )
117 if ( aStr.GetChar( nCur ) == nSC )
119 nLevel--;
120 if ( !nLevel )
121 break; // while nCur...
123 else if ( aStr.GetChar( nCur ) == nEC )
124 nLevel++;
126 nCur--;
130 if ( nLevel )
132 if ( nPara )
134 nPara--;
135 nCur = GetTextLen( nPara )-1; // egal ob negativ, weil if Len()
137 else
138 break;
142 if ( nLevel == 0 ) // gefunden
144 aSel.GetStart() = rCursor;
145 aSel.GetStart().GetIndex()++; // hinter das Zeichen
146 aSel.GetEnd() = TextPaM( nPara, nCur );
151 return aSel;
154 BOOL ExtTextEngine::Search( TextSelection& rSel, const util::SearchOptions& rSearchOptions, BOOL bForward )
156 TextSelection aSel( rSel );
157 aSel.Justify();
159 BOOL bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) );
161 TextPaM aStartPaM( aSel.GetEnd() );
162 if ( aSel.HasRange() && ( ( bSearchInSelection && bForward ) || ( !bSearchInSelection && !bForward ) ) )
164 aStartPaM = aSel.GetStart();
167 bool bFound = false;
168 ULONG nStartNode, nEndNode;
170 if ( bSearchInSelection )
171 nEndNode = bForward ? aSel.GetEnd().GetPara() : aSel.GetStart().GetPara();
172 else
173 nEndNode = bForward ? (GetParagraphCount()-1) : 0;
175 nStartNode = aStartPaM.GetPara();
177 util::SearchOptions aOptions( rSearchOptions );
178 aOptions.Locale = Application::GetSettings().GetLocale();
179 utl::TextSearch aSearcher( rSearchOptions );
181 // ueber die Absaetze iterieren...
182 for ( ULONG nNode = nStartNode;
183 bForward ? ( nNode <= nEndNode) : ( nNode >= nEndNode );
184 bForward ? nNode++ : nNode-- )
186 String aText = GetText( nNode );
187 USHORT nStartPos = 0;
188 USHORT nEndPos = aText.Len();
189 if ( nNode == nStartNode )
191 if ( bForward )
192 nStartPos = aStartPaM.GetIndex();
193 else
194 nEndPos = aStartPaM.GetIndex();
196 if ( ( nNode == nEndNode ) && bSearchInSelection )
198 if ( bForward )
199 nEndPos = aSel.GetEnd().GetIndex();
200 else
201 nStartPos = aSel.GetStart().GetIndex();
204 if ( bForward )
205 bFound = aSearcher.SearchFrwrd( aText, &nStartPos, &nEndPos );
206 else
207 bFound = aSearcher.SearchBkwrd( aText, &nEndPos, &nStartPos );
209 if ( bFound )
211 rSel.GetStart().GetPara() = nNode;
212 rSel.GetStart().GetIndex() = nStartPos;
213 rSel.GetEnd().GetPara() = nNode;
214 rSel.GetEnd().GetIndex() = nEndPos;
215 // Ueber den Absatz selektieren?
216 // Select over the paragraph?
217 // FIXME This should be max long...
218 if( nEndPos == sal::static_int_cast<USHORT>(-1) ) // USHORT for 0 and -1 !
220 if ( (rSel.GetEnd().GetPara()+1) < GetParagraphCount() )
222 rSel.GetEnd().GetPara()++;
223 rSel.GetEnd().GetIndex() = 0;
225 else
227 rSel.GetEnd().GetIndex() = nStartPos;
228 bFound = false;
232 break;
235 if ( !bForward && !nNode ) // Bei rueckwaertsuche, wenn nEndNode = 0:
236 break;
239 return bFound;
243 \f// -------------------------------------------------------------------------
244 // class ExtTextView
245 // -------------------------------------------------------------------------
246 ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow )
247 : TextView( pEng, pWindow )
251 ExtTextView::~ExtTextView()
255 BOOL ExtTextView::MatchGroup()
257 TextSelection aTmpSel( GetSelection() );
258 aTmpSel.Justify();
259 if ( ( aTmpSel.GetStart().GetPara() != aTmpSel.GetEnd().GetPara() ) ||
260 ( ( aTmpSel.GetEnd().GetIndex() - aTmpSel.GetStart().GetIndex() ) > 1 ) )
262 return FALSE;
265 TextSelection aMatchSel = ((ExtTextEngine*)GetTextEngine())->MatchGroup( aTmpSel.GetStart() );
266 if ( aMatchSel.HasRange() )
267 SetSelection( aMatchSel );
269 return aMatchSel.HasRange() ? TRUE : FALSE;
272 BOOL ExtTextView::Search( const util::SearchOptions& rSearchOptions, BOOL bForward )
274 BOOL bFound = FALSE;
275 TextSelection aSel( GetSelection() );
276 if ( ((ExtTextEngine*)GetTextEngine())->Search( aSel, rSearchOptions, bForward ) )
278 bFound = TRUE;
279 // Erstmal den Anfang des Wortes als Selektion einstellen,
280 // damit das ganze Wort in den sichtbaren Bereich kommt.
281 SetSelection( aSel.GetStart() );
282 ShowCursor( TRUE, FALSE );
284 else
286 aSel = GetSelection().GetEnd();
289 SetSelection( aSel );
290 ShowCursor();
292 return bFound;
295 USHORT ExtTextView::Replace( const util::SearchOptions& rSearchOptions, BOOL bAll, BOOL bForward )
297 USHORT nFound = 0;
299 if ( !bAll )
301 if ( GetSelection().HasRange() )
303 InsertText( rSearchOptions.replaceString );
304 nFound = 1;
305 Search( rSearchOptions, bForward ); // gleich zum naechsten
307 else
309 if( Search( rSearchOptions, bForward ) )
310 nFound = 1;
313 else
315 // Der Writer ersetzt alle, vom Anfang bis Ende...
317 ExtTextEngine* pTextEngine = (ExtTextEngine*)GetTextEngine();
319 // HideSelection();
320 TextSelection aSel;
322 BOOL bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) );
323 if ( bSearchInSelection )
325 aSel = GetSelection();
326 aSel.Justify();
329 TextSelection aSearchSel( aSel );
331 BOOL bFound = pTextEngine->Search( aSel, rSearchOptions, TRUE );
332 if ( bFound )
333 pTextEngine->UndoActionStart( XTEXTUNDO_REPLACEALL );
334 while ( bFound )
336 nFound++;
338 TextPaM aNewStart = pTextEngine->ImpInsertText( aSel, rSearchOptions.replaceString );
339 aSel = aSearchSel;
340 aSel.GetStart() = aNewStart;
341 bFound = pTextEngine->Search( aSel, rSearchOptions, TRUE );
343 if ( nFound )
345 SetSelection( aSel.GetStart() );
346 pTextEngine->FormatAndUpdate( this );
347 pTextEngine->UndoActionEnd( XTEXTUNDO_REPLACEALL );
350 return nFound;
353 BOOL ExtTextView::ImpIndentBlock( BOOL bRight )
355 BOOL bDone = FALSE;
357 TextSelection aSel = GetSelection();
358 aSel.Justify();
360 HideSelection();
361 GetTextEngine()->UndoActionStart( bRight ? XTEXTUNDO_INDENTBLOCK : XTEXTUNDO_UNINDENTBLOCK );
363 ULONG nStartPara = aSel.GetStart().GetPara();
364 ULONG nEndPara = aSel.GetEnd().GetPara();
365 if ( aSel.HasRange() && !aSel.GetEnd().GetIndex() )
367 nEndPara--; // den dann nicht einruecken...
370 for ( ULONG nPara = nStartPara; nPara <= nEndPara; nPara++ )
372 if ( bRight )
374 // Tabs hinzufuegen
375 GetTextEngine()->ImpInsertText( TextPaM( nPara, 0 ), '\t' );
376 bDone = TRUE;
378 else
380 // Tabs/Blanks entfernen
381 String aText = GetTextEngine()->GetText( nPara );
382 if ( aText.Len() && (
383 ( aText.GetChar( 0 ) == '\t' ) ||
384 ( aText.GetChar( 0 ) == ' ' ) ) )
386 GetTextEngine()->ImpDeleteText( TextSelection( TextPaM( nPara, 0 ), TextPaM( nPara, 1 ) ) );
387 bDone = TRUE;
392 GetTextEngine()->UndoActionEnd( bRight ? XTEXTUNDO_INDENTBLOCK : XTEXTUNDO_UNINDENTBLOCK );
394 BOOL bRange = aSel.HasRange();
395 if ( bRight )
397 aSel.GetStart().GetIndex()++;
398 if ( bRange && ( aSel.GetEnd().GetPara() == nEndPara ) )
399 aSel.GetEnd().GetIndex()++;
401 else
403 if ( aSel.GetStart().GetIndex() )
404 aSel.GetStart().GetIndex()--;
405 if ( bRange && aSel.GetEnd().GetIndex() )
406 aSel.GetEnd().GetIndex()--;
409 ImpSetSelection( aSel );
410 GetTextEngine()->FormatAndUpdate( this );
412 return bDone;
415 BOOL ExtTextView::IndentBlock()
417 return ImpIndentBlock( TRUE );
420 BOOL ExtTextView::UnindentBlock()
422 return ImpIndentBlock( FALSE );