Kate
kateplaintextsearch.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries and the Kate part. 00002 * 00003 * Copyright (C) 2009-2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de> 00004 * Copyright (C) 2007 Sebastian Pipping <webmaster@hartwork.org> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 */ 00021 00022 //BEGIN includes 00023 #include "kateplaintextsearch.h" 00024 00025 #include "kateregexpsearch.h" 00026 00027 #include <ktexteditor/document.h> 00028 00029 #include <kdebug.h> 00030 //END includes 00031 00032 00033 //BEGIN d'tor, c'tor 00034 // 00035 // KateSearch Constructor 00036 // 00037 KatePlainTextSearch::KatePlainTextSearch ( KTextEditor::Document *document, Qt::CaseSensitivity caseSensitivity, bool wholeWords ) 00038 : m_document (document) 00039 , m_caseSensitivity (caseSensitivity) 00040 , m_wholeWords (wholeWords) 00041 { 00042 } 00043 00044 // 00045 // KateSearch Destructor 00046 // 00047 KatePlainTextSearch::~KatePlainTextSearch() 00048 { 00049 } 00050 //END 00051 00052 KTextEditor::Range KatePlainTextSearch::search (const QString & text, const KTextEditor::Range & inputRange, bool backwards) 00053 { 00054 // abuse regex for whole word plaintext search 00055 if (m_wholeWords) 00056 { 00057 // escape dot and friends 00058 const QString workPattern = "\\b" + QRegExp::escape(text) + "\\b"; 00059 00060 return KateRegExpSearch(m_document, m_caseSensitivity).search(workPattern, inputRange, backwards)[0]; 00061 } 00062 00063 if (text.isEmpty() || !inputRange.isValid() || (inputRange.start() == inputRange.end())) 00064 { 00065 return KTextEditor::Range::invalid(); 00066 } 00067 00068 // split multi-line needle into single lines 00069 const QStringList needleLines = text.split("\n"); 00070 00071 if (needleLines.count() > 1) 00072 { 00073 // multi-line plaintext search (both forwards or backwards) 00074 const int forMin = inputRange.start().line(); // first line in range 00075 const int forMax = inputRange.end().line() + 1 - needleLines.count(); // last line in range 00076 const int forInit = backwards ? forMax : forMin; 00077 const int forInc = backwards ? -1 : +1; 00078 00079 for (int j = forInit; (forMin <= j) && (j <= forMax); j += forInc) 00080 { 00081 // try to match all lines 00082 const int startCol = m_document->lineLength(j) - needleLines[0].length(); 00083 for (int k = 0; k < needleLines.count(); k++) 00084 { 00085 // which lines to compare 00086 const QString & needleLine = needleLines[k]; 00087 const QString & hayLine = m_document->line(j + k); 00088 00089 // position specific comparison (first, middle, last) 00090 if (k == 0) { 00091 // first line 00092 if (forMin == j && startCol < inputRange.start().column()) 00093 break; 00094 if (!hayLine.endsWith(needleLine, m_caseSensitivity)) 00095 break; 00096 } else if (k == needleLines.count() - 1) { 00097 // last line 00098 const int maxRight = (j + k == inputRange.end().line()) ? inputRange.end().column() : hayLine.length(); 00099 00100 if (hayLine.startsWith(needleLine, m_caseSensitivity) && needleLine.length() <= maxRight) 00101 return KTextEditor::Range(j, startCol, j + k, needleLine.length()); 00102 } else { 00103 // mid lines 00104 if (hayLine.compare(needleLine, m_caseSensitivity) != 0) { 00105 break; 00106 } 00107 } 00108 } 00109 } 00110 00111 // not found 00112 return KTextEditor::Range::invalid(); 00113 } 00114 else 00115 { 00116 // single-line plaintext search (both forward of backward mode) 00117 const int startCol = inputRange.start().column(); 00118 const int endCol = inputRange.end().column(); // first not included 00119 const int startLine = inputRange.start().line(); 00120 const int endLine = inputRange.end().line(); 00121 const int forInc = backwards ? -1 : +1; 00122 00123 for (int line = backwards ? endLine : startLine; (startLine <= line) && (line <= endLine); line += forInc) 00124 { 00125 if ((line < 0) || (m_document->lines() <= line)) 00126 { 00127 kWarning() << "line " << line << " is not within interval [0.." << m_document->lines() << ") ... returning invalid range"; 00128 return KTextEditor::Range::invalid(); 00129 } 00130 00131 const QString textLine = m_document->line(line); 00132 00133 const int offset = (line == startLine) ? startCol : 0; 00134 const int line_end = (line == endLine) ? endCol : textLine.length(); 00135 const int foundAt = backwards ? textLine.lastIndexOf(text, line_end-text.length(), m_caseSensitivity) : 00136 textLine.indexOf(text, offset, m_caseSensitivity); 00137 00138 if ((offset <= foundAt) && (foundAt + text.length() <= line_end)) 00139 return KTextEditor::Range(line, foundAt, line, foundAt + text.length()); 00140 } 00141 } 00142 return KTextEditor::Range::invalid(); 00143 } 00144 00145 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE 4.6 API Reference