1
/* This file is part of the KDE libraries and the Kate part.
3
* Copyright (C) 2009-2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
4
* Copyright (C) 2007 Sebastian Pipping <webmaster@hartwork.org>
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public License
17
* along with this library; see the file COPYING.LIB. If not, write to
18
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA.
23
#include "kateplaintextsearch.h"
25
#include "kateregexpsearch.h"
27
#include <ktexteditor/document.h>
35
// KateSearch Constructor
37
KatePlainTextSearch::KatePlainTextSearch ( KTextEditor::Document *document, Qt::CaseSensitivity caseSensitivity, bool wholeWords )
38
: m_document (document)
39
, m_caseSensitivity (caseSensitivity)
40
, m_wholeWords (wholeWords)
45
// KateSearch Destructor
47
KatePlainTextSearch::~KatePlainTextSearch()
52
KTextEditor::Range KatePlainTextSearch::search (const QString & text, const KTextEditor::Range & inputRange, bool backwards)
54
// abuse regex for whole word plaintext search
57
// escape dot and friends
58
const QString workPattern = "\\b" + QRegExp::escape(text) + "\\b";
60
return KateRegExpSearch(m_document, m_caseSensitivity).search(workPattern, inputRange, backwards)[0];
63
if (text.isEmpty() || !inputRange.isValid() || (inputRange.start() == inputRange.end()))
65
return KTextEditor::Range::invalid();
68
// split multi-line needle into single lines
69
const QStringList needleLines = text.split("\n");
71
if (needleLines.count() > 1)
73
// multi-line plaintext search (both forwards or backwards)
74
const int forMin = inputRange.start().line(); // first line in range
75
const int forMax = inputRange.end().line() + 1 - needleLines.count(); // last line in range
76
const int forInit = backwards ? forMax : forMin;
77
const int forInc = backwards ? -1 : +1;
79
for (int j = forInit; (forMin <= j) && (j <= forMax); j += forInc)
81
// try to match all lines
82
const int startCol = m_document->lineLength(j) - needleLines[0].length();
83
for (int k = 0; k < needleLines.count(); k++)
85
// which lines to compare
86
const QString & needleLine = needleLines[k];
87
const QString & hayLine = m_document->line(j + k);
89
// position specific comparison (first, middle, last)
92
if (forMin == j && startCol < inputRange.start().column())
94
if (!hayLine.endsWith(needleLine, m_caseSensitivity))
96
} else if (k == needleLines.count() - 1) {
98
const int maxRight = (j + k == inputRange.end().line()) ? inputRange.end().column() : hayLine.length();
100
if (hayLine.startsWith(needleLine, m_caseSensitivity) && needleLine.length() <= maxRight)
101
return KTextEditor::Range(j, startCol, j + k, needleLine.length());
104
if (hayLine.compare(needleLine, m_caseSensitivity) != 0) {
112
return KTextEditor::Range::invalid();
116
// single-line plaintext search (both forward of backward mode)
117
const int startCol = inputRange.start().column();
118
const int endCol = inputRange.end().column(); // first not included
119
const int startLine = inputRange.start().line();
120
const int endLine = inputRange.end().line();
121
const int forInc = backwards ? -1 : +1;
123
for (int line = backwards ? endLine : startLine; (startLine <= line) && (line <= endLine); line += forInc)
125
if ((line < 0) || (m_document->lines() <= line))
127
kWarning() << "line " << line << " is not within interval [0.." << m_document->lines() << ") ... returning invalid range";
128
return KTextEditor::Range::invalid();
131
const QString textLine = m_document->line(line);
133
const int offset = (line == startLine) ? startCol : 0;
134
const int line_end = (line == endLine) ? endCol : textLine.length();
135
const int foundAt = backwards ? textLine.lastIndexOf(text, line_end-text.length(), m_caseSensitivity) :
136
textLine.indexOf(text, offset, m_caseSensitivity);
138
if ((offset <= foundAt) && (foundAt + text.length() <= line_end))
139
return KTextEditor::Range(line, foundAt, line, foundAt + text.length());
142
return KTextEditor::Range::invalid();
145
// kate: space-indent on; indent-width 2; replace-tabs on;