filter.cpp00001
00023 #include "filter.h"
00024
00025 #include "settings.h"
00026
00027 #include <kstaticdeleter.h>
00028 #include <kdebug.h>
00029
00030 #include <qstring.h>
00031
00032 namespace KSpell2
00033 {
00034
00035 static Word endWord;
00036 static KStaticDeleter<Filter> sd;
00037 static Filter* defFilter = 0;
00038
00039 class Filter::Private
00040 {
00041 public:
00042
00043
00044
00045 Settings *settings;
00046 };
00047
00048 Filter* Filter::defaultFilter()
00049 {
00050 if ( !defFilter )
00051 sd.setObject( defFilter, new Filter() );
00052 return defFilter;
00053 }
00054
00055 Word Filter::end()
00056 {
00057 return endWord;
00058 }
00059
00060 Filter::Filter()
00061 : m_currentPosition( 0 )
00062 {
00063 d = new Private;
00064 d->settings = 0;
00065 }
00066
00067 Filter::~Filter()
00068 {
00069 delete d; d = 0;
00070 }
00071
00072 void Filter::setSettings( Settings *conf )
00073 {
00074 d->settings = conf;
00075 }
00076
00077 Settings *Filter::settings() const
00078 {
00079 return d->settings;
00080 }
00081
00082 void Filter::restart()
00083 {
00084 m_currentPosition = 0;
00085 }
00086
00087 void Filter::setBuffer( const QString& buffer )
00088 {
00089 m_buffer = buffer;
00090 m_currentPosition = 0;
00091 }
00092
00093 QString Filter::buffer() const
00094 {
00095 return m_buffer;
00096 }
00097
00098 bool Filter::atEnd() const
00099 {
00100 if ( m_currentPosition >= m_buffer.length() ) {
00101 return true;
00102 } else
00103 return false;
00104 }
00105
00106 Word Filter::nextWord() const
00107 {
00108 QChar currentChar = skipToLetter( m_currentPosition );
00109
00110 if ( m_currentPosition >= m_buffer.length() ) {
00111 return Filter::end();
00112 }
00113
00114 bool allUppercase = currentChar.category() & QChar::Letter_Uppercase;
00115 bool runTogether = false;
00116
00117 QString foundWord;
00118 int start = m_currentPosition;
00119 while ( currentChar.isLetter() ) {
00120 if ( currentChar.category() & QChar::Letter_Lowercase )
00121 allUppercase = false;
00122
00123
00124
00125
00126
00127
00128
00129
00130 foundWord += currentChar;
00131 ++m_currentPosition;
00132 currentChar = m_buffer[ m_currentPosition ];
00133 }
00134
00135 if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
00136 return nextWord();
00137
00138 return Word( foundWord, start );
00139 }
00140
00141 Word Filter::previousWord() const
00142 {
00143 while ( !m_buffer[ m_currentPosition ].isLetter() &&
00144 m_currentPosition != 0) {
00145 --m_currentPosition;
00146 }
00147
00148 if ( m_currentPosition == 0 ) {
00149 return Filter::end();
00150 }
00151
00152 QString foundWord;
00153 int start = m_currentPosition;
00154 while ( m_buffer[ start ].isLetter() ) {
00155 foundWord.prepend( m_buffer[ m_currentPosition ] );
00156 --start;
00157 }
00158
00159 return Word( foundWord, start );
00160 }
00161
00162 Word Filter::wordAtPosition( unsigned int pos ) const
00163 {
00164 if ( pos > m_buffer.length() )
00165 return Filter::end();
00166
00167 int currentPosition = pos - 1;
00168 QString foundWord;
00169 while ( currentPosition >= 0 &&
00170 m_buffer[ currentPosition ].isLetter() ) {
00171 foundWord.prepend( m_buffer[ currentPosition ] );
00172 --currentPosition;
00173 }
00174
00175
00176
00177 int start = (currentPosition < 0) ? 0 : ++currentPosition;
00178 currentPosition = pos ;
00179 if ( m_buffer[ currentPosition ].isLetter() ) {
00180 while ( m_buffer[ currentPosition ].isLetter() ) {
00181 foundWord.append( m_buffer[ currentPosition ] );
00182 ++currentPosition;
00183 }
00184 }
00185
00186 return Word( foundWord, start );
00187 }
00188
00189
00190 void Filter::setCurrentPosition( int i )
00191 {
00192 m_currentPosition = i;
00193
00194
00195
00196 while ( m_buffer[m_currentPosition].isLetter() && m_currentPosition > 0 )
00197 --m_currentPosition;
00198 }
00199
00200 int Filter::currentPosition() const
00201 {
00202 return m_currentPosition;
00203 }
00204
00205 void Filter::replace( const Word& w, const QString& newWord)
00206 {
00207 int oldLen = w.word.length();
00208 int newLen = newWord.length();
00209
00210 if ( oldLen != newLen && m_currentPosition > w.start ) {
00211 if ( m_currentPosition > w.start ) {
00212 int len = newLen - oldLen;
00213 m_currentPosition += len;
00214 }
00215 }
00216 m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00217 }
00218
00219 QString Filter::context() const
00220 {
00221 int len = 60;
00222
00223
00224 int signedPosition = m_currentPosition;
00225 bool begin = ( (signedPosition - len/2)<=0 ) ? true : false;
00226
00227
00228 QString buffer = m_buffer;
00229 Word word = wordAtPosition( m_currentPosition );
00230 buffer = buffer.replace( word.start, word.word.length(),
00231 QString( "<b>%1</b>" ).arg( word.word ) );
00232
00233 QString context;
00234 if ( begin )
00235 context = QString( "%1...")
00236 .arg( buffer.mid( 0, len ) );
00237 else
00238 context = QString( "...%1..." )
00239 .arg( buffer.mid( m_currentPosition - 20, len ) );
00240
00241 context = context.replace( '\n', ' ' );
00242
00243 return context;
00244 }
00245
00246 bool Filter::trySkipLinks() const
00247 {
00248 QChar currentChar = m_buffer[ m_currentPosition ];
00249
00250 uint length = m_buffer.length();
00251
00252 if ( currentChar == ':' &&
00253 ( m_buffer[ ++m_currentPosition] == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00254
00255 while ( !m_buffer[ m_currentPosition++ ].isSpace() && m_currentPosition < length )
00256 ;
00257 return true;
00258 }
00259
00260
00261 if ( currentChar == '@' ) {
00262 while ( !m_buffer[ ++m_currentPosition ].isSpace() && m_currentPosition < length )
00263 ;
00264 return true;
00265 }
00266
00267 return false;
00268 }
00269
00270 bool Filter::ignore( const QString& word ) const
00271 {
00272 if ( d->settings ) {
00273 return d->settings->ignore( word );
00274 }
00275 return false;
00276 }
00277
00278 QChar Filter::skipToLetter( uint &fromPosition ) const
00279 {
00280
00281 QChar currentChar = m_buffer[ fromPosition ];
00282 while ( !currentChar.isLetter() &&
00283 ++fromPosition < m_buffer.length() ) {
00284 currentChar = m_buffer[ fromPosition ];
00285 }
00286 return currentChar;
00287 }
00288
00289 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00290 const QString& foundWord ) const
00291 {
00292 bool checkUpper = ( d->settings ) ?
00293 d->settings->checkUppercase () : true;
00294 bool skipRunTogether = ( d->settings ) ?
00295 d->settings->skipRunTogether() : true;
00296
00297 if ( trySkipLinks() )
00298 return true;
00299
00300 if ( wordWasUppercase && !checkUpper )
00301 return true;
00302
00303 if ( wordWasRunTogether && skipRunTogether )
00304 return true;
00305
00306 return ignore( foundWord );
00307 }
00308
00309 }
|