00001
00002
00003
00004
00005
00006 #include <config.h>
00007
00008 #include "kmedit.h"
00009 #include "kmlineeditspell.h"
00010
00011 #define REALLY_WANT_KMCOMPOSEWIN_H
00012 #include "kmcomposewin.h"
00013 #undef REALLY_WANT_KMCOMPOSEWIN_H
00014 #include "kmmsgdict.h"
00015 #include "kmfolder.h"
00016 #include "kmcommands.h"
00017
00018 #include <maillistdrag.h>
00019 using KPIM::MailListDrag;
00020
00021 #include <libkdepim/kfileio.h>
00022 #include <libemailfunctions/email.h>
00023
00024 #include <kcursor.h>
00025 #include <kprocess.h>
00026
00027 #include <kpopupmenu.h>
00028 #include <kdebug.h>
00029 #include <kmessagebox.h>
00030 #include <kurldrag.h>
00031
00032 #include <ktempfile.h>
00033 #include <klocale.h>
00034 #include <kapplication.h>
00035 #include <kdirwatch.h>
00036 #include <kiconloader.h>
00037
00038 #include "globalsettings.h"
00039 #include "replyphrases.h"
00040
00041 #include <kspell.h>
00042 #include <kspelldlg.h>
00043 #include <spellingfilter.h>
00044 #include <ksyntaxhighlighter.h>
00045
00046 #include <qregexp.h>
00047 #include <qbuffer.h>
00048 #include <qevent.h>
00049
00050 #include <sys/stat.h>
00051 #include <sys/types.h>
00052 #include <stdlib.h>
00053 #include <unistd.h>
00054 #include <errno.h>
00055 #include <fcntl.h>
00056 #include <assert.h>
00057
00058
00059 void KMEdit::contentsDragEnterEvent(QDragEnterEvent *e)
00060 {
00061 if (e->provides(MailListDrag::format()))
00062 e->accept(true);
00063 else
00064 return KEdit::contentsDragEnterEvent(e);
00065 }
00066
00067 void KMEdit::contentsDragMoveEvent(QDragMoveEvent *e)
00068 {
00069 if (e->provides(MailListDrag::format()))
00070 e->accept();
00071 else
00072 return KEdit::contentsDragMoveEvent(e);
00073 }
00074
00075 void KMEdit::keyPressEvent( QKeyEvent* e )
00076 {
00077 if( e->key() == Key_Return ) {
00078 int line, col;
00079 getCursorPosition( &line, &col );
00080 QString lineText = text( line );
00081
00082 lineText.truncate( lineText.length() - 1 );
00083
00084
00085 if( ( col > 0 ) && ( col < int( lineText.length() ) ) ) {
00086 bool isQuotedLine = false;
00087 uint bot = 0;
00088 while( bot < lineText.length() ) {
00089 if( ( lineText[bot] == '>' ) || ( lineText[bot] == '|' ) ) {
00090 isQuotedLine = true;
00091 ++bot;
00092 }
00093 else if( lineText[bot].isSpace() ) {
00094 ++bot;
00095 }
00096 else {
00097 break;
00098 }
00099 }
00100
00101 KEdit::keyPressEvent( e );
00102
00103
00104
00105
00106 if( isQuotedLine
00107 && ( bot != lineText.length() )
00108 && ( col >= int( bot ) ) ) {
00109
00110
00111
00112 getCursorPosition( &line, &col );
00113 QString newLine = text( line );
00114
00115
00116 unsigned int leadingWhiteSpaceCount = 0;
00117 while( ( leadingWhiteSpaceCount < newLine.length() )
00118 && newLine[leadingWhiteSpaceCount].isSpace() ) {
00119 ++leadingWhiteSpaceCount;
00120 }
00121 newLine = newLine.replace( 0, leadingWhiteSpaceCount,
00122 lineText.left( bot ) );
00123 removeParagraph( line );
00124 insertParagraph( newLine, line );
00125
00126
00127
00128 setCursorPosition( line, 0 );
00129 }
00130 }
00131 else
00132 KEdit::keyPressEvent( e );
00133 }
00134 else
00135 KEdit::keyPressEvent( e );
00136 }
00137
00138 void KMEdit::contentsDropEvent(QDropEvent *e)
00139 {
00140 if (e->provides(MailListDrag::format())) {
00141
00142 QByteArray serNums;
00143 MailListDrag::decode( e, serNums );
00144 QBuffer serNumBuffer(serNums);
00145 serNumBuffer.open(IO_ReadOnly);
00146 QDataStream serNumStream(&serNumBuffer);
00147 Q_UINT32 serNum;
00148 KMFolder *folder = 0;
00149 int idx;
00150 QPtrList<KMMsgBase> messageList;
00151 while (!serNumStream.atEnd()) {
00152 KMMsgBase *msgBase = 0;
00153 serNumStream >> serNum;
00154 KMMsgDict::instance()->getLocation(serNum, &folder, &idx);
00155 if (folder)
00156 msgBase = folder->getMsgBase(idx);
00157 if (msgBase)
00158 messageList.append( msgBase );
00159 }
00160 serNumBuffer.close();
00161 uint identity = folder ? folder->identity() : 0;
00162 KMCommand *command =
00163 new KMForwardAttachedCommand(mComposer, messageList,
00164 identity, mComposer);
00165 command->start();
00166 }
00167 else if( KURLDrag::canDecode( e ) ) {
00168 KURL::List urlList;
00169 if( KURLDrag::decode( e, urlList ) ) {
00170 KPopupMenu p;
00171 p.insertItem( i18n("Add as Text"), 0 );
00172 p.insertItem( i18n("Add as Attachment"), 1 );
00173 int id = p.exec( mapToGlobal( e->pos() ) );
00174 switch ( id) {
00175 case 0:
00176 for ( KURL::List::Iterator it = urlList.begin();
00177 it != urlList.end(); ++it ) {
00178 insert( (*it).url() );
00179 }
00180 break;
00181 case 1:
00182 for ( KURL::List::Iterator it = urlList.begin();
00183 it != urlList.end(); ++it ) {
00184 mComposer->addAttach( *it );
00185 }
00186 break;
00187 }
00188 }
00189 else if ( QTextDrag::canDecode( e ) ) {
00190 QString s;
00191 if ( QTextDrag::decode( e, s ) )
00192 insert( s );
00193 }
00194 else
00195 kdDebug(5006) << "KMEdit::contentsDropEvent, unable to add dropped object" << endl;
00196 }
00197 else {
00198 return KEdit::contentsDropEvent(e);
00199 }
00200 }
00201
00202 KMEdit::KMEdit(QWidget *parent, KMComposeWin* composer,
00203 KSpellConfig* autoSpellConfig,
00204 const char *name)
00205 : KEdit( parent, name ),
00206 mComposer( composer ),
00207 mKSpell( 0 ),
00208 mSpellConfig( autoSpellConfig ),
00209 mSpellingFilter( 0 ),
00210 mExtEditorTempFile( 0 ),
00211 mExtEditorTempFileWatcher( 0 ),
00212 mExtEditorProcess( 0 ),
00213 mUseExtEditor( false ),
00214 mWasModifiedBeforeSpellCheck( false ),
00215 mSpellChecker( 0 ),
00216 mSpellLineEdit( false )
00217 {
00218 installEventFilter(this);
00219 KCursor::setAutoHideCursor( this, true, true );
00220 setOverwriteEnabled( true );
00221 }
00222
00223
00224 void KMEdit::initializeAutoSpellChecking()
00225 {
00226 if ( mSpellChecker )
00227 return;
00228 QColor defaultColor1( 0x00, 0x80, 0x00 );
00229 QColor defaultColor2( 0x00, 0x70, 0x00 );
00230 QColor defaultColor3( 0x00, 0x60, 0x00 );
00231 QColor defaultForeground( kapp->palette().active().text() );
00232
00233 QColor c = Qt::red;
00234 KConfigGroup readerConfig( KMKernel::config(), "Reader" );
00235 QColor col1;
00236 if ( !readerConfig.readBoolEntry( "defaultColors", true ) )
00237 col1 = readerConfig.readColorEntry( "ForegroundColor", &defaultForeground );
00238 else
00239 col1 = defaultForeground;
00240 QColor col2 = readerConfig.readColorEntry( "QuotedText3", &defaultColor3 );
00241 QColor col3 = readerConfig.readColorEntry( "QuotedText2", &defaultColor2 );
00242 QColor col4 = readerConfig.readColorEntry( "QuotedText1", &defaultColor1 );
00243 QColor misspelled = readerConfig.readColorEntry( "MisspelledColor", &c );
00244 mSpellChecker = new KDictSpellingHighlighter( this, true,
00245 false,
00246 misspelled,
00247 true,
00248 col1, col2, col3, col4,
00249 mSpellConfig );
00250
00251 connect( mSpellChecker, SIGNAL(newSuggestions(const QString&, const QStringList&, unsigned int)),
00252 this, SLOT(addSuggestion(const QString&, const QStringList&, unsigned int)) );
00253 }
00254
00255
00256 QPopupMenu *KMEdit::createPopupMenu( const QPoint& pos )
00257 {
00258 enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
00259
00260 QPopupMenu *menu = KEdit::createPopupMenu( pos );
00261 if ( !QApplication::clipboard()->image().isNull() ) {
00262 int id = menu->idAt(0);
00263 menu->setItemEnabled( id - IdPaste, true);
00264 }
00265
00266 return menu;
00267 }
00268
00269 void KMEdit::deleteAutoSpellChecking()
00270 {
00271 delete mSpellChecker;
00272 mSpellChecker =0;
00273 }
00274
00275 void KMEdit::addSuggestion(const QString& text, const QStringList& lst, unsigned int )
00276 {
00277 mReplacements[text] = lst;
00278 }
00279
00280 void KMEdit::setSpellCheckingActive(bool spellCheckingActive)
00281 {
00282 if ( mSpellChecker ) {
00283 mSpellChecker->setActive(spellCheckingActive);
00284 }
00285 }
00286
00287
00288 KMEdit::~KMEdit()
00289 {
00290 removeEventFilter(this);
00291
00292 delete mKSpell;
00293 delete mSpellChecker;
00294 mSpellChecker = 0;
00295
00296 }
00297
00298
00299
00300 QString KMEdit::brokenText()
00301 {
00302 QString temp, line;
00303
00304 int num_lines = numLines();
00305 for (int i = 0; i < num_lines; ++i)
00306 {
00307 int lastLine = 0;
00308 line = textLine(i);
00309 for (int j = 0; j < (int)line.length(); ++j)
00310 {
00311 if (lineOfChar(i, j) > lastLine)
00312 {
00313 lastLine = lineOfChar(i, j);
00314 temp += '\n';
00315 }
00316 temp += line[j];
00317 }
00318 if (i + 1 < num_lines) temp += '\n';
00319 }
00320
00321 return temp;
00322 }
00323
00324
00325 unsigned int KMEdit::lineBreakColumn() const
00326 {
00327 unsigned int lineBreakColumn = 0;
00328 unsigned int numlines = numLines();
00329 while ( numlines-- ) {
00330 lineBreakColumn = QMAX( lineBreakColumn, textLine( numlines ).length() );
00331 }
00332 return lineBreakColumn;
00333 }
00334
00335
00336 bool KMEdit::eventFilter(QObject*o, QEvent* e)
00337 {
00338 if (o == this)
00339 KCursor::autoHideEventFilter(o, e);
00340
00341 if (e->type() == QEvent::KeyPress)
00342 {
00343 QKeyEvent *k = (QKeyEvent*)e;
00344
00345 if (mUseExtEditor) {
00346 if (k->key() == Key_Up)
00347 {
00348 emit focusUp();
00349 return TRUE;
00350 }
00351
00352
00353 if ( (k->key() == Key_Shift) || (k->key() == Key_Control) ||
00354 (k->key() == Key_Meta) || (k->key() == Key_Alt) )
00355 return true;
00356 if (mExtEditorTempFile) return TRUE;
00357 QString sysLine = mExtEditor;
00358 mExtEditorTempFile = new KTempFile();
00359
00360 mExtEditorTempFile->setAutoDelete(true);
00361
00362 (*mExtEditorTempFile->textStream()) << text();
00363
00364 mExtEditorTempFile->close();
00365
00366 sysLine.replace( "%f", mExtEditorTempFile->name() );
00367 mExtEditorProcess = new KProcess();
00368 mExtEditorProcess->setUseShell( true );
00369 sysLine += " ";
00370 while (!sysLine.isEmpty())
00371 {
00372 *mExtEditorProcess << sysLine.left(sysLine.find(" ")).local8Bit();
00373 sysLine.remove(0, sysLine.find(" ") + 1);
00374 }
00375 connect(mExtEditorProcess, SIGNAL(processExited(KProcess*)),
00376 SLOT(slotExternalEditorDone(KProcess*)));
00377 if (!mExtEditorProcess->start())
00378 {
00379 KMessageBox::error( topLevelWidget(),
00380 i18n("Unable to start external editor.") );
00381 killExternalEditor();
00382 } else {
00383 mExtEditorTempFileWatcher = new KDirWatch( this, "mExtEditorTempFileWatcher" );
00384 connect( mExtEditorTempFileWatcher, SIGNAL(dirty(const QString&)),
00385 SLOT(slotExternalEditorTempFileChanged(const QString&)) );
00386 mExtEditorTempFileWatcher->addFile( mExtEditorTempFile->name() );
00387 }
00388 return TRUE;
00389 } else {
00390
00391
00392 if (k->key() == Key_Up && k->state() != ShiftButton && currentLine() == 0
00393 && lineOfChar(0, currentColumn()) == 0)
00394 {
00395 deselect();
00396 emit focusUp();
00397 return TRUE;
00398 }
00399
00400
00401 if (k->key() == Key_Backtab && k->state() == ShiftButton)
00402 {
00403 deselect();
00404 emit focusUp();
00405 return TRUE;
00406 }
00407
00408 }
00409 } else if ( e->type() == QEvent::ContextMenu ) {
00410 QContextMenuEvent *event = (QContextMenuEvent*) e;
00411
00412 int para = 1, charPos, firstSpace, lastSpace;
00413
00414
00415 charPos = charAt( viewportToContents(event->pos()), ¶ );
00416 QString paraText = text( para );
00417
00418 if( !paraText.at(charPos).isSpace() )
00419 {
00420
00421 const QRegExp wordBoundary( "[\\s\\W]" );
00422 firstSpace = paraText.findRev( wordBoundary, charPos ) + 1;
00423 lastSpace = paraText.find( wordBoundary, charPos );
00424 if( lastSpace == -1 )
00425 lastSpace = paraText.length();
00426 QString word = paraText.mid( firstSpace, lastSpace - firstSpace );
00427
00428 if( !word.isEmpty() && mReplacements.contains( word ) )
00429 {
00430 KPopupMenu p;
00431 p.insertTitle( i18n("Suggestions") );
00432
00433
00434 QStringList reps = mReplacements[word];
00435 if( reps.count() > 0 )
00436 {
00437 int listPos = 0;
00438 for ( QStringList::Iterator it = reps.begin(); it != reps.end(); ++it ) {
00439 p.insertItem( *it, listPos );
00440 listPos++;
00441 }
00442 }
00443 else
00444 {
00445 p.insertItem( QString::fromLatin1("No Suggestions"), -2 );
00446 }
00447
00448
00449 int id = p.exec( mapToGlobal( event->pos() ) );
00450
00451 if( id > -1 )
00452 {
00453
00454 int parIdx = 1, txtIdx = 1;
00455 getCursorPosition(&parIdx, &txtIdx);
00456 setSelection(para, firstSpace, para, lastSpace);
00457 insert(mReplacements[word][id]);
00458
00459
00460 if ( para == parIdx && txtIdx >= lastSpace )
00461 txtIdx += mReplacements[word][id].length() - word.length();
00462 setCursorPosition(parIdx, txtIdx);
00463 }
00464
00465 return true;
00466 }
00467 }
00468 } else if ( e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut ) {
00469 QFocusEvent *fe = static_cast<QFocusEvent*>(e);
00470 if(! (fe->reason() == QFocusEvent::ActiveWindow || fe->reason() == QFocusEvent::Popup) )
00471 emit focusChanged( fe->gotFocus() );
00472 }
00473
00474 return KEdit::eventFilter(o, e);
00475 }
00476
00477
00478 int KMEdit::autoSpellChecking( bool on )
00479 {
00480 if ( textFormat() == Qt::RichText ) {
00481
00482 if ( on )
00483 KMessageBox::sorry(this, i18n("Automatic spellchecking is not possible on text with markup."));
00484 return -1;
00485 }
00486 if ( mSpellChecker ) {
00487
00488 mSpellChecker->setAutomatic( on );
00489 mSpellChecker->setActive( on );
00490 }
00491 return 1;
00492 }
00493
00494
00495 void KMEdit::slotExternalEditorTempFileChanged( const QString & fileName ) {
00496 if ( !mExtEditorTempFile )
00497 return;
00498 if ( fileName != mExtEditorTempFile->name() )
00499 return;
00500
00501 setAutoUpdate(false);
00502 clear();
00503
00504 insertLine(QString::fromLocal8Bit(KPIM::kFileToString( fileName, true, false )), -1);
00505 setAutoUpdate(true);
00506 repaint();
00507 }
00508
00509 void KMEdit::slotExternalEditorDone( KProcess * proc ) {
00510 assert(proc == mExtEditorProcess);
00511
00512 slotExternalEditorTempFileChanged( mExtEditorTempFile->name() );
00513 killExternalEditor();
00514 }
00515
00516 void KMEdit::killExternalEditor() {
00517 delete mExtEditorTempFileWatcher; mExtEditorTempFileWatcher = 0;
00518 delete mExtEditorTempFile; mExtEditorTempFile = 0;
00519 delete mExtEditorProcess; mExtEditorProcess = 0;
00520 }
00521
00522
00523 bool KMEdit::checkExternalEditorFinished() {
00524 if ( !mExtEditorProcess )
00525 return true;
00526 switch ( KMessageBox::warningYesNoCancel( topLevelWidget(),
00527 i18n("The external editor is still running.\n"
00528 "Abort the external editor or leave it open?"),
00529 i18n("External Editor"),
00530 i18n("Abort Editor"), i18n("Leave Editor Open") ) ) {
00531 case KMessageBox::Yes:
00532 killExternalEditor();
00533 return true;
00534 case KMessageBox::No:
00535 return true;
00536 default:
00537 return false;
00538 }
00539 }
00540
00541 void KMEdit::spellcheck()
00542 {
00543 if ( mKSpell )
00544 return;
00545 mWasModifiedBeforeSpellCheck = isModified();
00546 mSpellLineEdit = !mSpellLineEdit;
00547
00548
00549
00550
00551
00552
00553
00554 mKSpell = new KSpell(this, i18n("Spellcheck - KMail"), this,
00555 SLOT(slotSpellcheck2(KSpell*)));
00556
00557
00558 QStringList l = KSpellingHighlighter::personalWords();
00559 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
00560 mKSpell->addPersonal( *it );
00561 }
00562 connect (mKSpell, SIGNAL( death()),
00563 this, SLOT (slotSpellDone()));
00564 connect (mKSpell, SIGNAL (misspelling (const QString &, const QStringList &, unsigned int)),
00565 this, SLOT (slotMisspelling (const QString &, const QStringList &, unsigned int)));
00566 connect (mKSpell, SIGNAL (corrected (const QString &, const QString &, unsigned int)),
00567 this, SLOT (slotCorrected (const QString &, const QString &, unsigned int)));
00568 connect (mKSpell, SIGNAL (done(const QString &)),
00569 this, SLOT (slotSpellResult (const QString&)));
00570 }
00571
00572 void KMEdit::cut()
00573 {
00574 KEdit::cut();
00575 if ( textFormat() != Qt::RichText && mSpellChecker )
00576 mSpellChecker->restartBackgroundSpellCheck();
00577 }
00578
00579 void KMEdit::clear()
00580 {
00581 KEdit::clear();
00582 if ( textFormat() != Qt::RichText && mSpellChecker )
00583 mSpellChecker->restartBackgroundSpellCheck();
00584 }
00585
00586 void KMEdit::del()
00587 {
00588 KEdit::del();
00589 if ( textFormat() != Qt::RichText && mSpellChecker )
00590 mSpellChecker->restartBackgroundSpellCheck();
00591 }
00592
00593 void KMEdit::paste()
00594 {
00595 if ( ! QApplication::clipboard()->image().isNull() ) {
00596 emit pasteImage();
00597 }
00598 else
00599 KEdit::paste();
00600 }
00601
00602 void KMEdit::slotMisspelling(const QString &text, const QStringList &lst, unsigned int pos)
00603 {
00604 kdDebug(5006)<<"void KMEdit::slotMisspelling(const QString &text, const QStringList &lst, unsigned int pos) : "<<text <<endl;
00605 if( mSpellLineEdit )
00606 mComposer->sujectLineWidget()->spellCheckerMisspelling( text, lst, pos);
00607 else
00608 misspelling(text, lst, pos);
00609 }
00610
00611 void KMEdit::slotCorrected (const QString &oldWord, const QString &newWord, unsigned int pos)
00612 {
00613 kdDebug(5006)<<"slotCorrected (const QString &oldWord, const QString &newWord, unsigned int pos) : "<<oldWord<<endl;
00614 if( mSpellLineEdit )
00615 mComposer->sujectLineWidget()->spellCheckerCorrected( oldWord, newWord, pos);
00616 else {
00617 unsigned int l = 0;
00618 unsigned int cnt = 0;
00619 bool _bold,_underline,_italic;
00620 QColor _color;
00621 QFont _font;
00622 posToRowCol (pos, l, cnt);
00623 setCursorPosition(l, cnt+1);
00624 _bold = bold();
00625 _underline = underline();
00626 _italic = italic();
00627 _color = color();
00628 _font = currentFont();
00629 corrected(oldWord, newWord, pos);
00630 setSelection (l, cnt, l, cnt+newWord.length());
00631 setBold(_bold);
00632 setItalic(_italic);
00633 setUnderline(_underline);
00634 setColor(_color);
00635 setCurrentFont(_font);
00636 }
00637
00638 }
00639
00640 void KMEdit::slotSpellcheck2(KSpell*)
00641 {
00642 if( !mSpellLineEdit)
00643 {
00644 spellcheck_start();
00645
00646 QString quotePrefix;
00647 if(mComposer && mComposer->msg())
00648 {
00649 int languageNr = GlobalSettings::self()->replyCurrentLanguage();
00650 ReplyPhrases replyPhrases( QString::number(languageNr) );
00651 replyPhrases.readConfig();
00652
00653 quotePrefix = mComposer->msg()->formatString(
00654 replyPhrases.indentPrefix() );
00655 }
00656
00657 kdDebug(5006) << "spelling: new SpellingFilter with prefix=\"" << quotePrefix << "\"" << endl;
00658 QTextEdit plaintext;
00659 plaintext.setText(text());
00660 plaintext.setTextFormat(Qt::PlainText);
00661 mSpellingFilter = new SpellingFilter(plaintext.text(), quotePrefix, SpellingFilter::FilterUrls,
00662 SpellingFilter::FilterEmailAddresses);
00663
00664 mKSpell->check(mSpellingFilter->filteredText());
00665 }
00666 else if( mComposer )
00667 mKSpell->check( mComposer->sujectLineWidget()->text());
00668 }
00669
00670 void KMEdit::slotSpellResult(const QString &s)
00671 {
00672 if( !mSpellLineEdit)
00673 spellcheck_stop();
00674
00675 int dlgResult = mKSpell->dlgResult();
00676 if ( dlgResult == KS_CANCEL )
00677 {
00678 if( mSpellLineEdit)
00679 {
00680
00681 mSpellLineEdit = false;
00682 QString tmpText( s );
00683 tmpText = tmpText.remove('\n');
00684
00685 if( tmpText != mComposer->sujectLineWidget()->text() )
00686 mComposer->sujectLineWidget()->setText( tmpText );
00687 }
00688 else
00689 {
00690 setModified(true);
00691 }
00692 }
00693 mKSpell->cleanUp();
00694 KDictSpellingHighlighter::dictionaryChanged();
00695
00696 emit spellcheck_done( dlgResult );
00697 }
00698
00699 void KMEdit::slotSpellDone()
00700 {
00701 kdDebug(5006)<<" void KMEdit::slotSpellDone()\n";
00702 KSpell::spellStatus status = mKSpell->status();
00703 delete mKSpell;
00704 mKSpell = 0;
00705
00706 kdDebug(5006) << "spelling: delete SpellingFilter" << endl;
00707 delete mSpellingFilter;
00708 mSpellingFilter = 0;
00709 mComposer->sujectLineWidget()->deselect();
00710 if (status == KSpell::Error)
00711 {
00712 KMessageBox::sorry( topLevelWidget(),
00713 i18n("ISpell/Aspell could not be started. Please "
00714 "make sure you have ISpell or Aspell properly "
00715 "configured and in your PATH.") );
00716 emit spellcheck_done( KS_CANCEL );
00717 }
00718 else if (status == KSpell::Crashed)
00719 {
00720 spellcheck_stop();
00721 KMessageBox::sorry( topLevelWidget(),
00722 i18n("ISpell/Aspell seems to have crashed.") );
00723 emit spellcheck_done( KS_CANCEL );
00724 }
00725 else
00726 {
00727 if( mSpellLineEdit )
00728 spellcheck();
00729 else if( !mComposer->subjectTextWasSpellChecked() && status == KSpell::FinishedNoMisspellingsEncountered )
00730 KMessageBox::information( topLevelWidget(),
00731 i18n("No misspellings encountered.") );
00732 }
00733 }
00734
00735 void KMEdit::setCursorPositionFromStart( unsigned int pos ) {
00736 unsigned int l = 0;
00737 unsigned int c = 0;
00738 posToRowCol( pos, l, c );
00739
00740
00741 setCursorPosition( l, c );
00742 ensureCursorVisible();
00743 }
00744
00745 #include "kmedit.moc"