diff options
author | Timothy Pearson <[email protected]> | 2013-01-26 13:17:21 -0600 |
---|---|---|
committer | Timothy Pearson <[email protected]> | 2013-01-26 13:17:21 -0600 |
commit | dfe289850f068f19ba4a83ab4e7e22a7e09c13c9 (patch) | |
tree | c297348a55df66c571de4525646e0b9762427353 /tdespell2/filter.cpp | |
parent | b7658a0d5eca24a9d37c6e04f88298ef02389db0 (diff) | |
download | tdelibs-dfe289850f068f19ba4a83ab4e7e22a7e09c13c9.tar.gz tdelibs-dfe289850f068f19ba4a83ab4e7e22a7e09c13c9.zip |
Rename a number of libraries and executables to avoid conflicts with KDE4
Diffstat (limited to 'tdespell2/filter.cpp')
-rw-r--r-- | tdespell2/filter.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/tdespell2/filter.cpp b/tdespell2/filter.cpp new file mode 100644 index 000000000..1604bcae1 --- /dev/null +++ b/tdespell2/filter.cpp @@ -0,0 +1,309 @@ +// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- +/* + * filter.cpp + * + * Copyright (C) 2004 Zack Rusin <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "filter.h" + +#include "settings.h" + +#include <kstaticdeleter.h> +#include <kdebug.h> + +#include <tqstring.h> + +namespace KSpell2 +{ + +static Word endWord; +static KStaticDeleter<Filter> sd; +static Filter* defFilter = 0; + +class Filter::Private +{ +public: + // The reason it's not in the class directly is that + // i'm not 100% sure that having the settings() here is + // the way i want to be doing this. + Settings *settings; +}; + +Filter* Filter::defaultFilter() +{ + if ( !defFilter ) + sd.setObject( defFilter, new Filter() ); + return defFilter; +} + +Word Filter::end() +{ + return endWord; +} + +Filter::Filter() + : m_currentPosition( 0 ) +{ + d = new Private; + d->settings = 0; +} + +Filter::~Filter() +{ + delete d; d = 0; +} + +void Filter::setSettings( Settings *conf ) +{ + d->settings = conf; +} + +Settings *Filter::settings() const +{ + return d->settings; +} + +void Filter::restart() +{ + m_currentPosition = 0; +} + +void Filter::setBuffer( const TQString& buffer ) +{ + m_buffer = buffer; + m_currentPosition = 0; +} + +TQString Filter::buffer() const +{ + return m_buffer; +} + +bool Filter::atEnd() const +{ + if ( m_currentPosition >= m_buffer.length() ) { + return true; + } else + return false; +} + +Word Filter::nextWord() const +{ + TQChar currentChar = skipToLetter( m_currentPosition ); + + if ( m_currentPosition >= m_buffer.length() ) { + return Filter::end(); + } + + bool allUppercase = currentChar.category() & TQChar::Letter_Uppercase; + bool runTogether = false; + + TQString foundWord; + int start = m_currentPosition; + while ( currentChar.isLetter() ) { + if ( currentChar.category() & TQChar::Letter_Lowercase ) + allUppercase = false; + + /* FIXME: this does not work for Hebrew for example + //we consider run-together words as mixed-case words + if ( !allUppercase && + currentChar.category() & TQChar::Letter_Uppercase ) + runTogether = true; + */ + + foundWord += currentChar; + ++m_currentPosition; + currentChar = m_buffer[ m_currentPosition ]; + } + + if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) ) + return nextWord(); + + return Word( foundWord, start ); +} + +Word Filter::previousWord() const +{ + while ( !m_buffer[ m_currentPosition ].isLetter() && + m_currentPosition != 0) { + --m_currentPosition; + } + + if ( m_currentPosition == 0 ) { + return Filter::end(); + } + + TQString foundWord; + int start = m_currentPosition; + while ( m_buffer[ start ].isLetter() ) { + foundWord.prepend( m_buffer[ m_currentPosition ] ); + --start; + } + + return Word( foundWord, start ); +} + +Word Filter::wordAtPosition( unsigned int pos ) const +{ + if ( pos > m_buffer.length() ) + return Filter::end(); + + int currentPosition = pos - 1; + TQString foundWord; + while ( currentPosition >= 0 && + m_buffer[ currentPosition ].isLetter() ) { + foundWord.prepend( m_buffer[ currentPosition ] ); + --currentPosition; + } + + // currentPosition == 0 means the first char is not letter + // currentPosition == -1 means we reached the beginning + int start = (currentPosition < 0) ? 0 : ++currentPosition; + currentPosition = pos ; + if ( m_buffer[ currentPosition ].isLetter() ) { + while ( m_buffer[ currentPosition ].isLetter() ) { + foundWord.append( m_buffer[ currentPosition ] ); + ++currentPosition; + } + } + + return Word( foundWord, start ); +} + + +void Filter::setCurrentPosition( int i ) +{ + m_currentPosition = i; + + //go back to the last word so that next word returns something + //useful + while ( m_buffer[m_currentPosition].isLetter() && m_currentPosition > 0 ) + --m_currentPosition; +} + +int Filter::currentPosition() const +{ + return m_currentPosition; +} + +void Filter::replace( const Word& w, const TQString& newWord) +{ + int oldLen = w.word.length(); + int newLen = newWord.length(); + + if ( oldLen != newLen && m_currentPosition > w.start ) { + if ( m_currentPosition > w.start ) { + int len = newLen - oldLen; + m_currentPosition += len; + } + } + m_buffer = m_buffer.replace( w.start, oldLen, newWord ); +} + +TQString Filter::context() const +{ + int len = 60; + //we don't want the expression underneath casted to an unsigned int + //which would cause it to always evaluate to false + int signedPosition = m_currentPosition; + bool begin = ( (signedPosition - len/2)<=0 ) ? true : false; + + + TQString buffer = m_buffer; + Word word = wordAtPosition( m_currentPosition ); + buffer = buffer.replace( word.start, word.word.length(), + TQString( "<b>%1</b>" ).arg( word.word ) ); + + TQString context; + if ( begin ) + context = TQString( "%1...") + .arg( buffer.mid( 0, len ) ); + else + context = TQString( "...%1..." ) + .arg( buffer.mid( m_currentPosition - 20, len ) ); + + context = context.replace( '\n', ' ' ); + + return context; +} + +bool Filter::trySkipLinks() const +{ + TQChar currentChar = m_buffer[ m_currentPosition ]; + + uint length = m_buffer.length(); + //URL - if so skip + if ( currentChar == ':' && + ( m_buffer[ ++m_currentPosition] == '/' || ( m_currentPosition + 1 ) >= length ) ) { + //in both cases url is considered finished at the first whitespace occurence + while ( !m_buffer[ m_currentPosition++ ].isSpace() && m_currentPosition < length ) + ; + return true; + } + + //Email - if so skip + if ( currentChar == '@' ) { + while ( !m_buffer[ ++m_currentPosition ].isSpace() && m_currentPosition < length ) + ; + return true; + } + + return false; +} + +bool Filter::ignore( const TQString& word ) const +{ + if ( d->settings ) { + return d->settings->ignore( word ); + } + return false; +} + +TQChar Filter::skipToLetter( uint &fromPosition ) const +{ + + TQChar currentChar = m_buffer[ fromPosition ]; + while ( !currentChar.isLetter() && + ++fromPosition < m_buffer.length() ) { + currentChar = m_buffer[ fromPosition ]; + } + return currentChar; +} + +bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether, + const TQString& foundWord ) const +{ + bool checkUpper = ( d->settings ) ? + d->settings->checkUppercase () : true; + bool skipRunTogether = ( d->settings ) ? + d->settings->skipRunTogether() : true; + + if ( trySkipLinks() ) + return true; + + if ( wordWasUppercase && !checkUpper ) + return true; + + if ( wordWasRunTogether && skipRunTogether ) + return true; + + return ignore( foundWord ); +} + +} |