katespell.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2004-2005 Anders Lund <anders@alweb.dk> 00003 Copyright (C) 2003 Clarence Dang <dang@kde.org> 00004 Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> 00005 Copyright (C) 2001-2004 Christoph Cullmann <cullmann@kde.org> 00006 Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org> 00007 Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Library General Public 00011 License version 2 as published by the Free Software Foundation. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 Boston, MA 02110-1301, USA. 00022 */ 00023 00024 #include "katespell.h" 00025 #include "katespell.moc" 00026 00027 #include "kateview.h" 00028 00029 #include <kaction.h> 00030 #include <kstdaction.h> 00031 #include <kspell.h> 00032 #include <ksconfig.h> 00033 #include <kdebug.h> 00034 #include <kmessagebox.h> 00035 00036 KateSpell::KateSpell( KateView* view ) 00037 : QObject( view ) 00038 , m_view (view) 00039 , m_kspell (0) 00040 { 00041 } 00042 00043 KateSpell::~KateSpell() 00044 { 00045 // kspell stuff 00046 if( m_kspell ) 00047 { 00048 m_kspell->setAutoDelete(true); 00049 m_kspell->cleanUp(); // need a way to wait for this to complete 00050 delete m_kspell; 00051 } 00052 } 00053 00054 void KateSpell::createActions( KActionCollection* ac ) 00055 { 00056 KStdAction::spelling( this, SLOT(spellcheck()), ac ); 00057 KAction *a = new KAction( i18n("Spelling (from cursor)..."), "spellcheck", 0, this, SLOT(spellcheckFromCursor()), ac, "tools_spelling_from_cursor" ); 00058 a->setWhatsThis(i18n("Check the document's spelling from the cursor and forward")); 00059 00060 m_spellcheckSelection = new KAction( i18n("Spellcheck Selection..."), "spellcheck", 0, this, SLOT(spellcheckSelection()), ac, "tools_spelling_selection" ); 00061 m_spellcheckSelection->setWhatsThis(i18n("Check spelling of the selected text")); 00062 } 00063 00064 void KateSpell::updateActions () 00065 { 00066 m_spellcheckSelection->setEnabled (m_view->hasSelection ()); 00067 } 00068 00069 void KateSpell::spellcheckFromCursor() 00070 { 00071 spellcheck( KateTextCursor(m_view->cursorLine(), m_view->cursorColumnReal()) ); 00072 } 00073 00074 void KateSpell::spellcheckSelection() 00075 { 00076 KateTextCursor from( m_view->selStartLine(), m_view->selStartCol() ); 00077 KateTextCursor to( m_view->selEndLine(), m_view->selEndCol() ); 00078 spellcheck( from, to ); 00079 } 00080 00081 void KateSpell::spellcheck() 00082 { 00083 spellcheck( KateTextCursor( 0, 0 ) ); 00084 } 00085 00086 void KateSpell::spellcheck( const KateTextCursor &from, const KateTextCursor &to ) 00087 { 00088 m_spellStart = from; 00089 m_spellEnd = to; 00090 00091 if ( to.line() == 0 && to.col() == 0 ) 00092 { 00093 int lln = m_view->doc()->lastLine(); 00094 m_spellEnd.setLine( lln ); 00095 m_spellEnd.setCol( m_view->doc()->lineLength( lln ) ); 00096 } 00097 00098 m_spellPosCursor = from; 00099 m_spellLastPos = 0; 00100 00101 QString mt = m_view->doc()->mimeType()/*->name()*/; 00102 00103 KSpell::SpellerType type = KSpell::Text; 00104 if ( mt == "text/x-tex" || mt == "text/x-latex" ) 00105 type = KSpell::TeX; 00106 else if ( mt == "text/html" || mt == "text/xml" || mt == "text/docbook" || mt == "application/x-php") 00107 type = KSpell::HTML; 00108 00109 KSpellConfig *ksc = new KSpellConfig; 00110 QStringList ksEncodings; 00111 ksEncodings << "US-ASCII" << "ISO 8859-1" << "ISO 8859-2" << "ISO 8859-3" 00112 << "ISO 8859-4" << "ISO 8859-5" << "ISO 8859-7" << "ISO 8859-8" 00113 << "ISO 8859-9" << "ISO 8859-13" << "ISO 8859-15" << "UTF-8" 00114 << "KOI8-R" << "KOI8-U" << "CP1251" << "CP1255"; 00115 00116 int enc = ksEncodings.findIndex( m_view->doc()->encoding() ); 00117 if ( enc > -1 ) 00118 { 00119 ksc->setEncoding( enc ); 00120 kdDebug(13020)<<"KateSpell::spellCheck(): using encoding: "<<enc<<" ("<<ksEncodings[enc]<<") and KSpell::Type "<<type<<" (for '"<<mt<<"')"<<endl; 00121 } 00122 else 00123 kdDebug(13020)<<"KateSpell::spellCheck(): using encoding: "<<enc<<" and KSpell::Type "<<type<<" (for '"<<mt<<"')"<<endl; 00124 00125 m_kspell = new KSpell( m_view, i18n("Spellcheck"), 00126 this, SLOT(ready(KSpell *)), ksc, true, true, type ); 00127 00128 connect( m_kspell, SIGNAL(death()), 00129 this, SLOT(spellCleanDone()) ); 00130 00131 connect( m_kspell, SIGNAL(misspelling(const QString&, const QStringList&, unsigned int)), 00132 this, SLOT(misspelling(const QString&, const QStringList&, unsigned int)) ); 00133 connect( m_kspell, SIGNAL(corrected(const QString&, const QString&, unsigned int)), 00134 this, SLOT(corrected(const QString&, const QString&, unsigned int)) ); 00135 connect( m_kspell, SIGNAL(done(const QString&)), 00136 this, SLOT(spellResult(const QString&)) ); 00137 } 00138 00139 void KateSpell::ready(KSpell *) 00140 { 00141 m_kspell->setProgressResolution( 1 ); 00142 00143 m_kspell->check( m_view->doc()->text( m_spellStart.line(), m_spellStart.col(), m_spellEnd.line(), m_spellEnd.col() ) ); 00144 00145 kdDebug (13020) << "SPELLING READY STATUS: " << m_kspell->status () << endl; 00146 } 00147 00148 void KateSpell::locatePosition( uint pos, uint& line, uint& col ) 00149 { 00150 uint remains; 00151 00152 while ( m_spellLastPos < pos ) 00153 { 00154 remains = pos - m_spellLastPos; 00155 uint l = m_view->doc()->lineLength( m_spellPosCursor.line() ) - m_spellPosCursor.col(); 00156 if ( l > remains ) 00157 { 00158 m_spellPosCursor.setCol( m_spellPosCursor.col() + remains ); 00159 m_spellLastPos = pos; 00160 } 00161 else 00162 { 00163 m_spellPosCursor.setLine( m_spellPosCursor.line() + 1 ); 00164 m_spellPosCursor.setCol(0); 00165 m_spellLastPos += l + 1; 00166 } 00167 } 00168 00169 line = m_spellPosCursor.line(); 00170 col = m_spellPosCursor.col(); 00171 } 00172 00173 void KateSpell::misspelling( const QString& origword, const QStringList&, unsigned int pos ) 00174 { 00175 uint line, col; 00176 00177 locatePosition( pos, line, col ); 00178 00179 m_view->setCursorPositionInternal (line, col, 1); 00180 m_view->setSelection( line, col, line, col + origword.length() ); 00181 } 00182 00183 void KateSpell::corrected( const QString& originalword, const QString& newword, unsigned int pos ) 00184 { 00185 uint line, col; 00186 00187 locatePosition( pos, line, col ); 00188 00189 m_view->doc()->removeText( line, col, line, col + originalword.length() ); 00190 m_view->doc()->insertText( line, col, newword ); 00191 } 00192 00193 void KateSpell::spellResult( const QString& ) 00194 { 00195 m_view->clearSelection(); 00196 m_kspell->cleanUp(); 00197 } 00198 00199 void KateSpell::spellCleanDone() 00200 { 00201 KSpell::spellStatus status = m_kspell->status(); 00202 00203 if( status == KSpell::Error ) { 00204 KMessageBox::sorry( 0, 00205 i18n("The spelling program could not be started. " 00206 "Please make sure you have set the correct spelling program " 00207 "and that it is properly configured and in your PATH.")); 00208 } else if( status == KSpell::Crashed ) { 00209 KMessageBox::sorry( 0, 00210 i18n("The spelling program seems to have crashed.")); 00211 } 00212 00213 delete m_kspell; 00214 m_kspell = 0; 00215 00216 kdDebug (13020) << "SPELLING END" << endl; 00217 } 00218 //END 00219 00220 00221 // kate: space-indent on; indent-width 2; replace-tabs on;