00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "katesearch.h"
00024
#include "katesearch.moc"
00025
00026
#include "kateview.h"
00027
#include "katedocument.h"
00028
#include "katesupercursor.h"
00029
#include "katearbitraryhighlight.h"
00030
#include "kateconfig.h"
00031
00032
#include <klocale.h>
00033
#include <kstdaction.h>
00034
#include <kmessagebox.h>
00035
#include <kstringhandler.h>
00036
#include <kdebug.h>
00037
#include <kfinddialog.h>
00038
#include <kreplacedialog.h>
00039
00040
#include <qlayout.h>
00041
#include <qlabel.h>
00042
00043
00044
QStringList KateSearch::s_searchList =
QStringList();
00045 QStringList KateSearch::s_replaceList = QStringList();
00046
QString KateSearch::s_pattern =
QString();
00047
static const bool arbitraryHLExample =
false;
00048
00049 KateSearch::KateSearch( KateView* view )
00050 :
QObject( view, "kate search" )
00051 , m_view( view )
00052 , m_doc( view->doc() )
00053 , replacePrompt( new
KateReplacePrompt( view ) )
00054 {
00055 m_arbitraryHLList =
new KateSuperRangeList();
00056
if (arbitraryHLExample) m_doc->arbitraryHL()->addHighlightToView(m_arbitraryHLList, m_view);
00057
00058 connect(replacePrompt,SIGNAL(clicked()),
this,SLOT(replaceSlot()));
00059 }
00060
00061 KateSearch::~KateSearch()
00062 {
00063
delete m_arbitraryHLList;
00064 }
00065
00066
void KateSearch::createActions(
KActionCollection* ac )
00067 {
00068
KStdAction::find(
this, SLOT(
find()), ac )->
setWhatsThis(
00069 i18n(
"Look up the first occurrence of a piece of text or regular expression."));
00070
KStdAction::findNext(
this, SLOT(slotFindNext()), ac )->
setWhatsThis(
00071 i18n(
"Look up the next occurrence of the search phrase."));
00072
KStdAction::findPrev(
this, SLOT(slotFindPrev()), ac,
"edit_find_prev" )->
setWhatsThis(
00073 i18n(
"Look up the previous occurrence of the search phrase."));
00074
KStdAction::replace(
this, SLOT(
replace()), ac )->
setWhatsThis(
00075 i18n(
"Look up a piece of text or regular expression and replace the result with some given text."));
00076 }
00077
00078
void KateSearch::addToList( QStringList& list,
const QString& s )
00079 {
00080
if( list.count() > 0 ) {
00081 QStringList::Iterator it = list.find( s );
00082
if( *it != 0L )
00083 list.remove( it );
00084
if( list.count() >= 16 )
00085 list.remove( list.fromLast() );
00086 }
00087 list.prepend( s );
00088 }
00089
00090
void KateSearch::find()
00091 {
00092
00093
long searchf = KateViewConfig::global()->searchFlags();
00094
if (m_doc->hasSelection() && m_doc->selStartLine() != m_doc->selEndLine())
00095 searchf |= KFindDialog::SelectedText;
00096
00097 KFindDialog *findDialog =
new KFindDialog ( m_view,
"", searchf,
00098 s_searchList, m_doc->hasSelection() );
00099
00100 findDialog->setPattern (getSearchText());
00101
00102
00103
if( findDialog->exec() == QDialog::Accepted ) {
00104 s_searchList = findDialog->findHistory () ;
00105
00106
find( QString(s_searchList.first()), findDialog->options(),
true,
true );
00107 }
00108
00109
delete findDialog;
00110 m_view->repaintText ();
00111 }
00112
00113
void KateSearch::find(
const QString &pattern,
long flags,
bool add,
bool shownotfound )
00114 {
00115 KateViewConfig::global()->setSearchFlags( flags );
00116
if( add )
00117 addToList( s_searchList, pattern );
00118
00119 s_pattern = pattern;
00120
00121 SearchFlags searchFlags;
00122
00123 searchFlags.caseSensitive = KateViewConfig::global()->searchFlags() & KFindDialog::CaseSensitive;
00124 searchFlags.wholeWords = KateViewConfig::global()->searchFlags() & KFindDialog::WholeWordsOnly;
00125 searchFlags.fromBeginning = !(KateViewConfig::global()->searchFlags() & KFindDialog::FromCursor)
00126 && !(KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText);
00127 searchFlags.backward = KateViewConfig::global()->searchFlags() & KFindDialog::FindBackwards;
00128 searchFlags.selected = KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText;
00129 searchFlags.prompt =
false;
00130 searchFlags.replace =
false;
00131 searchFlags.finished =
false;
00132 searchFlags.regExp = KateViewConfig::global()->searchFlags() & KFindDialog::RegularExpression;
00133
00134
if ( searchFlags.selected )
00135 {
00136 s.selBegin =
KateTextCursor( doc()->selStartLine(), doc()->selStartCol() );
00137 s.selEnd =
KateTextCursor( doc()->selEndLine(), doc()->selEndCol() );
00138 s.cursor = s.flags.backward ? s.selEnd : s.selBegin;
00139 }
else {
00140 s.cursor = getCursor();
00141 }
00142
00143 s.wrappedEnd = s.cursor;
00144 s.wrapped =
false;
00145 s.showNotFound = shownotfound;
00146
00147 search( searchFlags );
00148 }
00149
00150
void KateSearch::replace()
00151 {
00152
if (!doc()->isReadWrite())
return;
00153
00154
00155
long searchf = KateViewConfig::global()->searchFlags();
00156
if (m_doc->hasSelection() && m_doc->selStartLine() != m_doc->selEndLine())
00157 searchf |= KFindDialog::SelectedText;
00158
00159 KReplaceDialog *replaceDialog =
new KReplaceDialog ( m_view,
"", searchf,
00160 s_searchList, s_replaceList, m_doc->hasSelection() );
00161
00162 replaceDialog->setPattern (getSearchText());
00163
00164
if( replaceDialog->exec() == QDialog::Accepted ) {
00165
long opts = replaceDialog->options();
00166 m_replacement = replaceDialog->replacement();
00167 s_searchList = replaceDialog->findHistory () ;
00168 s_replaceList = replaceDialog->replacementHistory () ;
00169
00170
00171
replace( QString(s_searchList.first()), m_replacement, opts );
00172 }
00173
00174
delete replaceDialog;
00175 m_view->update ();
00176 }
00177
00178
void KateSearch::replace(
const QString& pattern,
const QString &replacement,
long flags )
00179 {
00180
if (!doc()->isReadWrite())
return;
00181
00182 addToList( s_searchList, pattern );
00183 s_pattern = pattern;
00184 addToList( s_replaceList, replacement );
00185 m_replacement = replacement;
00186 KateViewConfig::global()->setSearchFlags( flags );
00187
00188 SearchFlags searchFlags;
00189 searchFlags.caseSensitive = KateViewConfig::global()->searchFlags() & KFindDialog::CaseSensitive;
00190 searchFlags.wholeWords = KateViewConfig::global()->searchFlags() & KFindDialog::WholeWordsOnly;
00191 searchFlags.fromBeginning = !(KateViewConfig::global()->searchFlags() & KFindDialog::FromCursor)
00192 && !(KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText);
00193 searchFlags.backward = KateViewConfig::global()->searchFlags() & KFindDialog::FindBackwards;
00194 searchFlags.selected = KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText;
00195 searchFlags.prompt = KateViewConfig::global()->searchFlags() & KReplaceDialog::PromptOnReplace;
00196 searchFlags.replace =
true;
00197 searchFlags.finished =
false;
00198 searchFlags.regExp = KateViewConfig::global()->searchFlags() & KFindDialog::RegularExpression;
00199 searchFlags.useBackRefs = KateViewConfig::global()->searchFlags() & KReplaceDialog::BackReference;
00200
if ( searchFlags.selected )
00201 {
00202 s.selBegin =
KateTextCursor( doc()->selStartLine(), doc()->selStartCol() );
00203 s.selEnd =
KateTextCursor( doc()->selEndLine(), doc()->selEndCol() );
00204 s.cursor = s.flags.backward ? s.selEnd : s.selBegin;
00205 }
else {
00206 s.cursor = getCursor();
00207 }
00208
00209 s.wrappedEnd = s.cursor;
00210 s.wrapped =
false;
00211
00212 search( searchFlags );
00213 }
00214
00215
void KateSearch::findAgain(
bool back )
00216 {
00217 SearchFlags searchFlags;
00218 searchFlags.caseSensitive = KateViewConfig::global()->searchFlags() & KFindDialog::CaseSensitive;
00219 searchFlags.wholeWords = KateViewConfig::global()->searchFlags() & KFindDialog::WholeWordsOnly;
00220 searchFlags.fromBeginning = !(KateViewConfig::global()->searchFlags() & KFindDialog::FromCursor)
00221 && !(KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText);
00222 searchFlags.backward = KateViewConfig::global()->searchFlags() & KFindDialog::FindBackwards;
00223 searchFlags.selected = KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText;
00224 searchFlags.prompt = KateViewConfig::global()->searchFlags() & KReplaceDialog::PromptOnReplace;
00225 searchFlags.replace =
false;
00226 searchFlags.finished =
false;
00227 searchFlags.regExp = KateViewConfig::global()->searchFlags() & KFindDialog::RegularExpression;
00228
00229 searchFlags.backward = searchFlags.backward !=
back;
00230 searchFlags.fromBeginning =
false;
00231 searchFlags.prompt =
true;
00232 s.cursor = getCursor();
00233
00234 search( searchFlags );
00235 }
00236
00237
void KateSearch::search( SearchFlags flags )
00238 {
00239 s.flags = flags;
00240
00241
if( s.flags.fromBeginning ) {
00242
if( !s.flags.backward ) {
00243 s.cursor.setPos(0, 0);
00244 }
else {
00245 s.cursor.setLine(doc()->numLines() - 1);
00246 s.cursor.setCol(doc()->lineLength( s.cursor.line() ));
00247 }
00248 }
00249
00250
if((!s.flags.backward &&
00251 s.cursor.col() == 0 &&
00252 s.cursor.line() == 0 ) ||
00253 ( s.flags.backward &&
00254 s.cursor.col() == doc()->lineLength( s.cursor.line() ) &&
00255 s.cursor.line() == (((
int)doc()->numLines()) - 1) ) ) {
00256 s.flags.finished =
true;
00257 }
00258
00259
if( s.flags.replace ) {
00260 replaces = 0;
00261
if( s.flags.prompt )
00262 promptReplace();
00263
else
00264 replaceAll();
00265 }
else {
00266 findAgain();
00267 }
00268 }
00269
00270
void KateSearch::wrapSearch()
00271 {
00272
if( s.flags.selected )
00273 {
00274 s.cursor = s.flags.backward ? s.selEnd : s.selBegin;
00275 }
00276
else
00277 {
00278
if( !s.flags.backward ) {
00279 s.cursor.setPos(0, 0);
00280 }
else {
00281 s.cursor.setLine(doc()->numLines() - 1);
00282 s.cursor.setCol(doc()->lineLength( s.cursor.line() ) );
00283 }
00284 }
00285
00286
00287
00288 s.wrapped = s.flags.replace;
00289
00290 replaces = 0;
00291 s.flags.finished =
true;
00292 }
00293
00294
void KateSearch::findAgain()
00295 {
00296
if( s_pattern.isEmpty() ) {
00297
find();
00298
return;
00299 }
00300
00301
if ( doSearch( s_pattern ) ) {
00302 exposeFound( s.cursor, s.matchedLength );
00303 }
else if( !s.flags.finished ) {
00304
if( askContinue() ) {
00305 wrapSearch();
00306 findAgain();
00307 }
else {
00308
if (arbitraryHLExample) m_arbitraryHLList->clear();
00309 }
00310 }
else {
00311
if (arbitraryHLExample) m_arbitraryHLList->clear();
00312
if ( s.showNotFound )
00313
KMessageBox::sorry( view(),
00314 i18n(
"Search string '%1' not found!")
00315 .arg( KStringHandler::csqueeze( s_pattern ) ),
00316 i18n(
"Find"));
00317 }
00318 }
00319
00320
void KateSearch::replaceAll()
00321 {
00322 doc()->editStart ();
00323
00324
while( doSearch( s_pattern ) )
00325 replaceOne();
00326
00327 doc()->editEnd ();
00328
00329
if( !s.flags.finished ) {
00330
if( askContinue() ) {
00331 wrapSearch();
00332 replaceAll();
00333 }
00334 }
else {
00335
KMessageBox::information( view(),
00336 i18n(
"%n replacement made.",
"%n replacements made.",replaces),
00337 i18n(
"Replace") );
00338 }
00339 }
00340
00341
void KateSearch::promptReplace()
00342 {
00343
if ( doSearch( s_pattern ) ) {
00344 exposeFound( s.cursor, s.matchedLength );
00345 replacePrompt->show();
00346 replacePrompt->setFocus ();
00347 }
else if( !s.flags.finished && askContinue() ) {
00348 wrapSearch();
00349 promptReplace();
00350 }
else {
00351
if (arbitraryHLExample) m_arbitraryHLList->clear();
00352 replacePrompt->hide();
00353
KMessageBox::information( view(),
00354 i18n(
"%n replacement made.",
"%n replacements made.",replaces),
00355 i18n(
"Replace") );
00356 }
00357 }
00358
00359
void KateSearch::replaceOne()
00360 {
00361 QString replaceWith = m_replacement;
00362
if ( s.flags.regExp && s.flags.useBackRefs ) {
00363
00364
QRegExp br(
"\\\\(\\d+)");
00365
int pos = br.search( replaceWith );
00366
int ncaps = m_re.numCaptures();
00367
while ( pos >= 0 ) {
00368 QString sc;
00369
if ( !pos || replaceWith.at( pos-1) !=
'\\' ) {
00370
int ccap = br.cap(1).toInt();
00371
if (ccap <= ncaps ) {
00372 sc = m_re.cap( ccap );
00373 replaceWith.replace( pos, br.matchedLength(), sc );
00374 }
00375
else {
00376
kdDebug()<<
"KateSearch::replaceOne(): you don't have "<<ccap<<
" backreferences in regexp '"<<m_re.pattern()<<
"'"<<
endl;
00377 }
00378 }
00379 pos = br.search( replaceWith, pos+QMAX(br.matchedLength(), (
int)sc.length()) );
00380 }
00381 }
00382
00383 doc()->editStart();
00384 doc()->removeText( s.cursor.line(), s.cursor.col(),
00385 s.cursor.line(), s.cursor.col() + s.matchedLength );
00386 doc()->insertText( s.cursor.line(), s.cursor.col(), replaceWith );
00387 doc()->editEnd(),
00388
00389 replaces++;
00390
00391
00392 uint newlines = replaceWith.contains(
'\n');
00393
if ( newlines )
00394 {
00395
if ( ! s.flags.backward )
00396 {
00397 s.cursor.setLine( s.cursor.line() + newlines );
00398 s.cursor.setCol( replaceWith.length() - replaceWith.findRev(
'\n') );
00399 }
00400
00401
if ( s.flags.selected )
00402 s.selEnd.setLine( s.selEnd.line() + newlines );
00403 }
00404
00405
00406
00407
if( s.flags.selected && s.cursor.line() == s.selEnd.line() )
00408 {
00409 s.selEnd.setCol(s.selEnd.col() + replaceWith.length() - s.matchedLength );
00410 }
00411
00412
00413
if( s.cursor.line() == s.wrappedEnd.line() && s.cursor.col() <= s.wrappedEnd.col())
00414 {
00415 s.wrappedEnd.setCol(s.wrappedEnd.col() + replaceWith.length() - s.matchedLength );
00416 }
00417
00418
if( !s.flags.backward ) {
00419 s.cursor.setCol(s.cursor.col() + replaceWith.length());
00420 }
else if( s.cursor.col() > 0 ) {
00421 s.cursor.setCol(s.cursor.col() - 1);
00422 }
else {
00423 s.cursor.setLine(s.cursor.line() - 1);
00424
if( s.cursor.line() >= 0 ) {
00425 s.cursor.setCol(doc()->lineLength( s.cursor.line() ));
00426 }
00427 }
00428 }
00429
00430
void KateSearch::skipOne()
00431 {
00432
if( !s.flags.backward ) {
00433 s.cursor.setCol(s.cursor.col() + s.matchedLength);
00434 }
else if( s.cursor.col() > 0 ) {
00435 s.cursor.setCol(s.cursor.col() - 1);
00436 }
else {
00437 s.cursor.setLine(s.cursor.line() - 1);
00438
if( s.cursor.line() >= 0 ) {
00439 s.cursor.setCol(doc()->lineLength(s.cursor.line()));
00440 }
00441 }
00442 }
00443
00444
void KateSearch::replaceSlot() {
00445
switch( (Dialog_results)replacePrompt->result() ) {
00446
case srCancel: replacePrompt->hide();
break;
00447
case srAll: replacePrompt->hide(); replaceAll();
break;
00448
case srYes: replaceOne(); promptReplace();
break;
00449
case srLast: replacePrompt->hide(), replaceOne();
break;
00450
case srNo: skipOne(); promptReplace();
break;
00451 }
00452 }
00453
00454
bool KateSearch::askContinue()
00455 {
00456 QString made =
00457 i18n(
"%n replacement made.",
00458
"%n replacements made.",
00459 replaces );
00460
00461 QString reached = !s.flags.backward ?
00462 i18n(
"End of document reached." ) :
00463 i18n( "Beginning of
document reached." );
00464
00465
if (KateViewConfig::global()->searchFlags() & KFindDialog::SelectedText)
00466 {
00467 reached = !s.flags.backward ?
00468 i18n(
"End of selection reached." ) :
00469 i18n( "Beginning of selection reached." );
00470 }
00471
00472 QString question = !s.flags.backward ?
00473 i18n(
"Continue from the beginning?" ) :
00474 i18n( "Continue from the
end?" );
00475
00476 QString text = s.flags.replace ?
00477 made +
"\n" + reached +
"\n" + question :
00478 reached +
"\n" + question;
00479
00480
return KMessageBox::Yes ==
KMessageBox::questionYesNo(
00481 view(), text, s.flags.replace ? i18n(
"Replace") : i18n(
"Find"),
00482 KStdGuiItem::cont(), i18n(
"&Stop") );
00483 }
00484
00485 QString KateSearch::getSearchText()
00486 {
00487
00488
00489
00490
00491 QString str;
00492
00493
int getFrom = view()->config()->textToSearchMode();
00494
switch (getFrom)
00495 {
00496
case KateViewConfig::SelectionOnly:
00497
00498
if( doc()->hasSelection() )
00499 str = doc()->selection();
00500
break;
00501
00502
case KateViewConfig::SelectionWord:
00503
00504
if( doc()->hasSelection() )
00505 str = doc()->selection();
00506
else
00507 str = view()->currentWord();
00508
break;
00509
00510
case KateViewConfig::WordOnly:
00511
00512 str = view()->currentWord();
00513
break;
00514
00515
case KateViewConfig::WordSelection:
00516
00517 str = view()->currentWord();
00518
if (str.isEmpty() && doc()->hasSelection() )
00519 str = doc()->selection();
00520
break;
00521
00522
default:
00523
00524
break;
00525 }
00526
00527 str.replace(
QRegExp(
"^\\n"),
"" );
00528 str.replace(
QRegExp(
"\\n.*"),
"" );
00529
00530
return str;
00531 }
00532
00533
KateTextCursor KateSearch::getCursor()
00534 {
00535
return KateTextCursor(view()->cursorLine(), view()->cursorColumnReal());
00536 }
00537
00538
bool KateSearch::doSearch(
const QString& text )
00539 {
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
#if 0
00557
static int oldLine = -1;
00558
static int oldCol = -1;
00559
#endif
00560
00561 uint line = s.cursor.line();
00562 uint col = s.cursor.col();
00563
bool backward = s.flags.backward;
00564
bool caseSensitive = s.flags.caseSensitive;
00565
bool regExp = s.flags.regExp;
00566
bool wholeWords = s.flags.wholeWords;
00567 uint foundLine, foundCol, matchLen;
00568
bool found =
false;
00569
00570
00571
00572
do {
00573
if( regExp ) {
00574 m_re =
QRegExp( text, caseSensitive );
00575 found = doc()->searchText( line, col, m_re,
00576 &foundLine, &foundCol,
00577 &matchLen, backward );
00578 }
else if ( wholeWords ) {
00579
QRegExp re(
"\\b" + text +
"\\b", caseSensitive );
00580 found = doc()->searchText( line, col, re,
00581 &foundLine, &foundCol,
00582 &matchLen, backward );
00583 }
else {
00584 found = doc()->searchText( line, col, text,
00585 &foundLine, &foundCol,
00586 &matchLen, caseSensitive, backward );
00587 }
00588
00589
if ( found && s.flags.selected )
00590 {
00591
if ( !s.flags.backward &&
KateTextCursor( foundLine, foundCol ) >= s.selEnd
00592 || s.flags.backward &&
KateTextCursor( foundLine, foundCol ) < s.selBegin )
00593 found =
false;
00594
else if (m_doc->blockSelectionMode())
00595 {
00596
if ((
int)foundCol < s.selEnd.col() && (
int)foundCol >= s.selBegin.col())
00597
break;
00598 }
00599 }
00600
00601 line = foundLine;
00602 col = foundCol+1;
00603 }
00604
while (m_doc->blockSelectionMode() && found);
00605
00606
if( !found )
return false;
00607
00608
00609 s.cursor.setPos(foundLine, foundCol);
00610 s.matchedLength = matchLen;
00611
00612
00613
if (s.wrapped)
00614 {
00615
if (s.flags.backward)
00616 {
00617
if ( (s.cursor.line() < s.wrappedEnd.line())
00618 || ( (s.cursor.line() == s.wrappedEnd.line()) && ((s.cursor.col()+matchLen) <= uint(s.wrappedEnd.col())) ) )
00619
return false;
00620 }
00621
else
00622 {
00623
if ( (s.cursor.line() > s.wrappedEnd.line())
00624 || ( (s.cursor.line() == s.wrappedEnd.line()) && (s.cursor.col() > s.wrappedEnd.col()) ) )
00625
return false;
00626 }
00627 }
00628
00629
00630
00631
00632
00633
00634
if (arbitraryHLExample) {
00635 KateArbitraryHighlightRange* hl =
new KateArbitraryHighlightRange(
new KateSuperCursor(m_doc,
true, s.cursor),
new KateSuperCursor(m_doc,
true, s.cursor.line(), s.cursor.col() + s.matchedLength),
this);
00636 hl->setBold();
00637 hl->setTextColor(Qt::white);
00638 hl->setBGColor(Qt::black);
00639
00640 connect(hl, SIGNAL(contentsChanged()), hl, SIGNAL(eliminated()));
00641 m_arbitraryHLList->append(hl);
00642 }
00643
00644
return true;
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 }
00658
00659
void KateSearch::exposeFound(
KateTextCursor &cursor,
int slen )
00660 {
00661 view()->setCursorPositionInternal ( cursor.
line(), cursor.
col() + slen, 1 );
00662 doc()->setSelection( cursor.
line(), cursor.
col(), cursor.
line(), cursor.
col() + slen );
00663 }
00664
00665
00666
00667
00668 KateReplacePrompt::KateReplacePrompt (
QWidget *parent )
00669 :
KDialogBase ( parent, 0L, false, i18n( "Replace Confirmation" ),
00670 User3 | User2 | User1 | Close | Ok , Ok, true,
00671 i18n("Replace &All"), i18n("Re&place && Close"), i18n("&Replace") )
00672 {
00673 setButtonOK( i18n(
"&Find Next") );
00674
QWidget *page =
new QWidget(
this);
00675 setMainWidget(page);
00676
00677
QBoxLayout *topLayout =
new QVBoxLayout( page, 0,
spacingHint() );
00678
QLabel *label =
new QLabel(i18n(
"Found an occurrence of your search term. What do you want to do?"),page);
00679 topLayout->
addWidget(label );
00680 }
00681
00682 void KateReplacePrompt::slotOk ()
00683 {
00684
done(KateSearch::srNo);
00685 }
00686
00687 void KateReplacePrompt::slotClose ()
00688 {
00689
done(KateSearch::srCancel);
00690 }
00691
00692 void KateReplacePrompt::slotUser1 ()
00693 {
00694
done(KateSearch::srAll);
00695 }
00696
00697 void KateReplacePrompt::slotUser2 ()
00698 {
00699
done(KateSearch::srLast);
00700 }
00701
00702 void KateReplacePrompt::slotUser3 ()
00703 {
00704
done(KateSearch::srYes);
00705 }
00706
00707 void KateReplacePrompt::done (
int result)
00708 {
00709 setResult(result);
00710
00711 emit
clicked();
00712 }
00713
00714
00715
00716
bool SearchCommand::exec(
class Kate::View *view,
const QString &cmd, QString &msg)
00717 {
00718 QString flags, pattern, replacement;
00719
if ( cmd.startsWith(
"find" ) )
00720 {
00721
00722
static QRegExp re_find(
"find(?::([bcersw]*))?\\s+(.+)");
00723
if ( re_find.search( cmd ) < 0 )
00724 {
00725 msg = i18n(
"Usage: find[:[bcersw]] PATTERN");
00726
return false;
00727 }
00728 flags = re_find.cap( 1 );
00729 pattern = re_find.cap( 2 );
00730 }
00731
00732
else if ( cmd.startsWith(
"ifind" ) )
00733 {
00734
static QRegExp re_ifind(
"ifind(?::([bcrs]*))?\\s+(.*)");
00735
if ( re_ifind.search( cmd ) < 0 )
00736 {
00737 msg = i18n(
"Usage: ifind[:[bcrs]] PATTERN");
00738
return false;
00739 }
00740 ifindClear();
00741
return true;
00742 }
00743
00744
else if ( cmd.startsWith(
"replace" ) )
00745 {
00746
00747
static QRegExp re_rep(
"replace(?::([bceprsw]*))?\\s+([\"'])((?:[^\\\\\\\\2]|\\\\.)*)\\2\\s+\\2((?:[^\\\\\\\\2]|\\\\.)*)\\2\\s*$");
00748
00749
QRegExp re_rep1(
"replace(?::([bceprsw]*))?\\s+([\"'])((?:[^\\\\\\\\2]|\\\\.)*)\\2\\s*$");
00750
00751
QRegExp re_rep2(
"replace(?::([bceprsw]*))?\\s+(\\S+)(.*)");
00752
#define unbackslash(s) p=0;\
00753
while ( (p = pattern.find( '\\' + delim, p )) > -1 )\
00754
{\
00755
if ( !p || pattern[p-1] != '\\' )\
00756
pattern.remove( p, 1 );\
00757
p++;\
00758
}
00759
00760
if ( re_rep.search( cmd ) >= 0 )
00761 {
00762 flags = re_rep.cap(1);
00763 pattern = re_rep.cap( 3 );
00764 replacement = re_rep.cap( 4 );
00765
00766
int p(0);
00767
00768
00769 QString delim = re_rep.cap( 2 );
00770 unbackslash(pattern);
00771
00772 unbackslash(replacement);
00773 }
00774
else if ( re_rep1.search( cmd ) >= 0 )
00775 {
00776 flags = re_rep1.cap(1);
00777 pattern = re_rep1.cap( 3 );
00778
00779
int p(0);
00780 QString delim = re_rep1.cap( 2 );
00781 unbackslash(pattern);
00782 }
00783
else if ( re_rep2.search( cmd ) >= 0 )
00784 {
00785 flags = re_rep2.cap( 1 );
00786 pattern = re_rep2.cap( 2 );
00787 replacement = re_rep2.cap( 3 ).stripWhiteSpace();
00788 }
00789
else
00790 {
00791 msg = i18n(
"Usage: replace[:[bceprsw]] PATTERN [REPLACEMENT]");
00792
return false;
00793 }
00794
kdDebug()<<
"replace '"<<pattern<<
"' with '"<<replacement<<
"'"<<
endl;
00795
#undef unbackslash
00796
}
00797
00798
long f = 0;
00799
if ( flags.contains(
'b' ) ) f |= KFindDialog::FindBackwards;
00800
if ( flags.contains(
'c' ) ) f |= KFindDialog::FromCursor;
00801
if ( flags.contains(
'e' ) ) f |= KFindDialog::SelectedText;
00802
if ( flags.contains(
'r' ) ) f |= KFindDialog::RegularExpression;
00803
if ( flags.contains(
'p' ) ) f |= KReplaceDialog::PromptOnReplace;
00804
if ( flags.contains(
's' ) ) f |= KFindDialog::CaseSensitive;
00805
if ( flags.contains(
'w' ) ) f |= KFindDialog::WholeWordsOnly;
00806
00807
if ( cmd.startsWith(
"find" ) )
00808 {
00809 ((KateView*)view)->find( pattern, f );
00810
return true;
00811 }
00812
else if ( cmd.startsWith(
"replace" ) )
00813 {
00814 f |= KReplaceDialog::BackReference;
00815 ((KateView*)view)->replace( pattern, replacement, f );
00816
return true;
00817 }
00818
00819
return false;
00820 }
00821
00822
bool SearchCommand::help(
class Kate::View *,
const QString &cmd, QString &msg)
00823 {
00824
if ( cmd ==
"find" )
00825 msg = i18n(
"<p>Usage: <code>find[:bcersw] PATTERN</code></p>");
00826
00827
else if ( cmd ==
"ifind" )
00828 msg = i18n(
"<p>Usage: <code>ifind:[:bcrs] PATTERN</code>"
00829
"<br>ifind does incremental or 'as-you-type' search</p>");
00830
00831
else
00832 msg = i18n(
"<p>Usage: <code>replace[:bceprsw] PATTERN REPLACEMENT</code></p>");
00833
00834 msg += i18n(
00835
"<h4><caption>Options</h4><p>"
00836
"<b>b</b> - Search backward"
00837
"<br><b>c</b> - Search from cursor"
00838
"<br><b>r</b> - Pattern is a regular expression"
00839
"<br><b>s</b> - Case sensitive search"
00840 );
00841
00842
if ( cmd ==
"find" )
00843 msg += i18n(
00844
"<br><b>e</b> - Search in selected text only"
00845
"<br><b>w</b> - Search whole words only"
00846 );
00847
00848
if ( cmd ==
"replace" )
00849 msg += i18n(
00850
"<br><b>p</b> - Prompt for replace</p>"
00851
"<p>If REPLACEMENT is not present, an empty string is used.</p>"
00852
"<p>If you want to have whitespace in your PATTERN, you need to "
00853
"quote both PATTERN and REPLACEMENT with either single or double "
00854
"quotes. To have the quote characters in the strings, prepend them "
00855
"with a backslash.");
00856
00857 msg +=
"</p>";
00858
return true;
00859 }
00860
00861 QStringList SearchCommand::cmds()
00862 {
00863 QStringList l;
00864 l <<
"find" <<
"replace" <<
"ifind";
00865
return l;
00866 }
00867
00868
bool SearchCommand::wantsToProcessText(
const QString &cmdname )
00869 {
00870
return cmdname ==
"ifind";
00871 }
00872
00873
void SearchCommand::processText(
Kate::View *view,
const QString &cmd )
00874 {
00875
static QRegExp re_ifind(
"ifind(?::([bcrs]*))?\\s(.*)");
00876
if ( re_ifind.search( cmd ) > -1 )
00877 {
00878 QString flags = re_ifind.cap( 1 );
00879 QString pattern = re_ifind.cap( 2 );
00880
00881
00882
00883
if ( ! m_ifindFlags || pattern.isEmpty() )
00884 ifindInit( flags );
00885
00886
else if ( ! ( m_ifindFlags & KFindDialog::FromCursor ) && ! pattern.isEmpty() )
00887 m_ifindFlags |= KFindDialog::FromCursor;
00888
00889
00890
if ( ! pattern.isEmpty() )
00891 {
00892 KateView *v = (KateView*)view;
00893
00894
00895
00896
00897
00898
if ( pattern.startsWith( v->getDoc()->selection() ) &&
00899 v->getDoc()->selection().length() + 1 == pattern.length() )
00900 v->setCursorPositionInternal( v->getDoc()->selStartLine(), v->getDoc()->selStartCol() );
00901
00902 v->find( pattern, m_ifindFlags,
false );
00903 }
00904 }
00905 }
00906
00907
void SearchCommand::ifindInit(
const QString &flags )
00908 {
00909
long f = 0;
00910
if ( flags.contains(
'b' ) ) f |= KFindDialog::FindBackwards;
00911
if ( flags.contains(
'c' ) ) f |= KFindDialog::FromCursor;
00912
if ( flags.contains(
'r' ) ) f |= KFindDialog::RegularExpression;
00913
if ( flags.contains(
's' ) ) f |= KFindDialog::CaseSensitive;
00914 m_ifindFlags = f;
00915 }
00916
00917
void SearchCommand::ifindClear()
00918 {
00919 m_ifindFlags = 0;
00920 }
00921
00922
00923