1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xtextedt.cxx,v $
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 );
74 while ( nLevel
&& ( nPara
< nParas
) )
76 XubString aStr
= GetText( nPara
);
77 while ( nCur
< aStr
.Len() )
79 if ( aStr
.GetChar( nCur
) == nSC
)
81 else if ( aStr
.GetChar( nCur
) == nEC
)
85 break; // while nCur...
96 if ( nLevel
== 0 ) // gefunden
98 aSel
.GetStart() = rCursor
;
99 aSel
.GetEnd() = TextPaM( nPara
, nCur
+1 );
104 // Rueckwaerts suchen...
105 xub_Unicode nEC
= maGroupChars
.GetChar( nMatchChar
);
106 xub_Unicode nSC
= maGroupChars
.GetChar( nMatchChar
-1 );
108 USHORT nCur
= rCursor
.GetIndex()-1;
112 if ( GetTextLen( nPara
) )
114 XubString aStr
= GetText( nPara
);
117 if ( aStr
.GetChar( nCur
) == nSC
)
121 break; // while nCur...
123 else if ( aStr
.GetChar( nCur
) == nEC
)
135 nCur
= GetTextLen( nPara
)-1; // egal ob negativ, weil if Len()
142 if ( nLevel
== 0 ) // gefunden
144 aSel
.GetStart() = rCursor
;
145 aSel
.GetStart().GetIndex()++; // hinter das Zeichen
146 aSel
.GetEnd() = TextPaM( nPara
, nCur
);
154 BOOL
ExtTextEngine::Search( TextSelection
& rSel
, const util::SearchOptions
& rSearchOptions
, BOOL bForward
)
156 TextSelection
aSel( rSel
);
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();
168 ULONG nStartNode
, nEndNode
;
170 if ( bSearchInSelection
)
171 nEndNode
= bForward
? aSel
.GetEnd().GetPara() : aSel
.GetStart().GetPara();
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
)
192 nStartPos
= aStartPaM
.GetIndex();
194 nEndPos
= aStartPaM
.GetIndex();
196 if ( ( nNode
== nEndNode
) && bSearchInSelection
)
199 nEndPos
= aSel
.GetEnd().GetIndex();
201 nStartPos
= aSel
.GetStart().GetIndex();
205 bFound
= aSearcher
.SearchFrwrd( aText
, &nStartPos
, &nEndPos
);
207 bFound
= aSearcher
.SearchBkwrd( aText
, &nEndPos
, &nStartPos
);
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;
227 rSel
.GetEnd().GetIndex() = nStartPos
;
235 if ( !bForward
&& !nNode
) // Bei rueckwaertsuche, wenn nEndNode = 0:
243 \f// -------------------------------------------------------------------------
245 // -------------------------------------------------------------------------
246 ExtTextView::ExtTextView( ExtTextEngine
* pEng
, Window
* pWindow
)
247 : TextView( pEng
, pWindow
)
251 ExtTextView::~ExtTextView()
255 BOOL
ExtTextView::MatchGroup()
257 TextSelection
aTmpSel( GetSelection() );
259 if ( ( aTmpSel
.GetStart().GetPara() != aTmpSel
.GetEnd().GetPara() ) ||
260 ( ( aTmpSel
.GetEnd().GetIndex() - aTmpSel
.GetStart().GetIndex() ) > 1 ) )
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
)
275 TextSelection
aSel( GetSelection() );
276 if ( ((ExtTextEngine
*)GetTextEngine())->Search( aSel
, rSearchOptions
, bForward
) )
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
);
286 aSel
= GetSelection().GetEnd();
289 SetSelection( aSel
);
295 USHORT
ExtTextView::Replace( const util::SearchOptions
& rSearchOptions
, BOOL bAll
, BOOL bForward
)
301 if ( GetSelection().HasRange() )
303 InsertText( rSearchOptions
.replaceString
);
305 Search( rSearchOptions
, bForward
); // gleich zum naechsten
309 if( Search( rSearchOptions
, bForward
) )
315 // Der Writer ersetzt alle, vom Anfang bis Ende...
317 ExtTextEngine
* pTextEngine
= (ExtTextEngine
*)GetTextEngine();
322 BOOL bSearchInSelection
= (0 != (rSearchOptions
.searchFlag
& util::SearchFlags::REG_NOT_BEGINOFLINE
) );
323 if ( bSearchInSelection
)
325 aSel
= GetSelection();
329 TextSelection
aSearchSel( aSel
);
331 BOOL bFound
= pTextEngine
->Search( aSel
, rSearchOptions
, TRUE
);
333 pTextEngine
->UndoActionStart( XTEXTUNDO_REPLACEALL
);
338 TextPaM aNewStart
= pTextEngine
->ImpInsertText( aSel
, rSearchOptions
.replaceString
);
340 aSel
.GetStart() = aNewStart
;
341 bFound
= pTextEngine
->Search( aSel
, rSearchOptions
, TRUE
);
345 SetSelection( aSel
.GetStart() );
346 pTextEngine
->FormatAndUpdate( this );
347 pTextEngine
->UndoActionEnd( XTEXTUNDO_REPLACEALL
);
353 BOOL
ExtTextView::ImpIndentBlock( BOOL bRight
)
357 TextSelection aSel
= GetSelection();
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
++ )
375 GetTextEngine()->ImpInsertText( TextPaM( nPara
, 0 ), '\t' );
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 ) ) );
392 GetTextEngine()->UndoActionEnd( bRight
? XTEXTUNDO_INDENTBLOCK
: XTEXTUNDO_UNINDENTBLOCK
);
394 BOOL bRange
= aSel
.HasRange();
397 aSel
.GetStart().GetIndex()++;
398 if ( bRange
&& ( aSel
.GetEnd().GetPara() == nEndPara
) )
399 aSel
.GetEnd().GetIndex()++;
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 );
415 BOOL
ExtTextView::IndentBlock()
417 return ImpIndentBlock( TRUE
);
420 BOOL
ExtTextView::UnindentBlock()
422 return ImpIndentBlock( FALSE
);