lib Library API Documentation

koAutoFormat.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
00003                  2001       Sven Leiber         <s.leiber@web.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "koAutoFormat.h"
00022 
00023 #include "kotextobject.h"
00024 #include "kotextparag.h"
00025 #include "kovariable.h"
00026 #include "koparagcounter.h"
00027 #include <koDocument.h>
00028 #include <koSearchDia.h>
00029 #include <kozoomhandler.h>
00030 #include <koGlobal.h>
00031 
00032 #include <kdeversion.h>
00033 #include <kdebug.h>
00034 #include <klocale.h>
00035 #include <kinstance.h>
00036 #include <kconfig.h>
00037 #include <kstandarddirs.h>
00038 #include <kglobal.h>
00039 #include <kcommand.h>
00040 //#include <kotextformat.h>
00041 #include <kcompletion.h>
00042 #include <kcalendarsystem.h>
00043 
00044 #include <qfile.h>
00045 #include <qlabel.h>
00046 #include <qtooltip.h>
00047 #include <qwhatsthis.h>
00048 #include <qdom.h>
00049 #include <qregexp.h>
00050 
00051 
00052 KoCompletionBox::KoCompletionBox( QWidget * parent, const char * name, WFlags f)
00053   : QLabel(parent,name,f)
00054 {
00055   setBackgroundColor(QColor("#FFFFE6"));
00056   setFocusPolicy(QWidget::NoFocus);
00057   setFrameShape(QFrame::Box);
00058 }
00059 
00060 KoCompletionBox::~KoCompletionBox()
00061 {
00062 }
00063 
00064 void KoCompletionBox::mousePressEvent( QMouseEvent *)
00065 {
00066   hide();
00067 }
00068 
00069 QString& KoCompletionBox::lastWord()
00070 {
00071   return m_lastWord;
00072 }
00073 
00074 void KoCompletionBox::setLastWord( QString const &lastword)
00075 {
00076   m_lastWord = lastword;
00077 }
00078 
00079 KoAutoFormatEntry::KoAutoFormatEntry(const QString& replace)
00080     : m_replace( replace )
00081 {
00082     m_formatOptions= 0L;
00083 }
00084 
00085 KoAutoFormatEntry::~KoAutoFormatEntry()
00086 {
00087     delete m_formatOptions;
00088     m_formatOptions=0L;
00089 }
00090 
00091 KoSearchContext *KoAutoFormatEntry::formatEntryContext() const
00092 {
00093     return m_formatOptions;
00094 }
00095 
00096 void KoAutoFormatEntry::createNewEntryContext()
00097 {
00098     if ( !m_formatOptions )
00099     {
00100         m_formatOptions = new KoSearchContext();
00101     }
00102 }
00103 
00104 void KoAutoFormatEntry::setFormatEntryContext( KoSearchContext *_cont )
00105 {
00106     delete m_formatOptions;
00107     m_formatOptions=_cont;
00108 }
00109 
00110 void KoAutoFormatEntry::clearFormatEntryContext( )
00111 {
00112     delete m_formatOptions;
00113     m_formatOptions = 0L;
00114 }
00115 
00116 
00117 /******************************************************************/
00118 /* Class: KoAutoFormat                        */
00119 /******************************************************************/
00120 KoAutoFormat::KoAutoFormat( KoDocument *_doc, KoVariableCollection *_varCollection, KoVariableFormatCollection *_varFormatCollection )
00121     : m_doc( _doc ),
00122       m_varCollection(_varCollection),
00123       m_varFormatCollection(_varFormatCollection),
00124       m_autoFormatLanguage( QString::null),
00125       m_configRead( false ),
00126       m_convertUpperCase( false ), m_convertUpperUpper( false ),
00127       m_advancedAutoCorrect( true ),
00128       m_autoDetectUrl( false ),
00129       m_ignoreDoubleSpace( false ),
00130       m_removeSpaceBeginEndLine( false ),
00131       m_useBulletStyle(false),
00132       m_autoChangeFormat(false),
00133       m_autoReplaceNumber(false),
00134       m_useAutoNumberStyle(false),
00135       m_completion(false),
00136       m_toolTipCompletion(false),
00137       m_completionAppendSpace(false),
00138       m_addCompletionWord(true),
00139       m_includeTwoUpperLetterException(false),
00140       m_includeAbbreviation(false),
00141       m_ignoreUpperCase(false),
00142       m_bAutoFormatActive(true),
00143       m_bAutoSuperScript( false ),
00144       m_bAutoCorrectionWithFormat( false ),
00145       m_bCapitalizeNameOfDays( false ),
00146       m_wordInserted( false ),
00147       m_bulletStyle(),
00148       m_typographicSimpleQuotes(),
00149       m_typographicDoubleQuotes(),
00150       m_typographicDefaultDoubleQuotes(),
00151       m_typographicDefaultSimpleQuotes(),
00152       m_listCompletion( new KCompletion ),
00153       m_entries(17,false),
00154       m_allLanguages(17,false),
00155       m_superScriptEntries(),
00156       m_upperCaseExceptions(),
00157       m_twoUpperLetterException(),
00158       m_maxFindLength( 0 ),
00159       m_minCompletionWordLength( 5 ),
00160       m_nbMaxCompletionWord( 500 ),
00161       m_countMaxWords(0),
00162       m_completionBox(0),
00163       m_keyCompletionAction( Enter )
00164 
00165 {
00166     //load once this list not each time that we "readConfig"
00167     loadListOfWordCompletion();
00168     m_listCompletion->setIgnoreCase( true );
00169     updateMaxWords();
00170     KLocale klocale(m_doc->instance()->instanceName());
00171     for (int i = 1; i <=7; i++)
00172     {
00173         m_cacheNameOfDays.append(klocale.calendar()->weekDayName( i ).lower());
00174     }
00175 }
00176 
00177 KoAutoFormat::KoAutoFormat( const KoAutoFormat& format )
00178     : m_doc( format.m_doc ),
00179       m_varCollection( format.m_varCollection ),
00180       m_varFormatCollection( format.m_varFormatCollection ),
00181       m_autoFormatLanguage( format.m_autoFormatLanguage),
00182       m_configRead( format.m_configRead ),
00183       m_convertUpperCase( format.m_convertUpperCase ),
00184       m_convertUpperUpper( format.m_convertUpperUpper ),
00185       m_advancedAutoCorrect( format.m_advancedAutoCorrect ),
00186       m_autoDetectUrl( format.m_autoDetectUrl ),
00187       m_ignoreDoubleSpace( format.m_ignoreDoubleSpace ),
00188       m_removeSpaceBeginEndLine( format.m_removeSpaceBeginEndLine ),
00189       m_useBulletStyle( format.m_useBulletStyle ),
00190       m_autoChangeFormat( format.m_autoChangeFormat ),
00191       m_autoReplaceNumber( format.m_autoReplaceNumber ),
00192       m_useAutoNumberStyle( format.m_useAutoNumberStyle ),
00193       m_completion( format.m_completion ),
00194       m_toolTipCompletion( format.m_toolTipCompletion),
00195       m_completionAppendSpace( format.m_completionAppendSpace ),
00196       m_addCompletionWord( format.m_addCompletionWord ),
00197       m_includeTwoUpperLetterException( format.m_includeTwoUpperLetterException ),
00198       m_includeAbbreviation( format.m_includeAbbreviation ),
00199       m_ignoreUpperCase( format.m_ignoreUpperCase ),
00200       m_bAutoFormatActive( format.m_bAutoFormatActive ),
00201       m_bAutoSuperScript( format.m_bAutoSuperScript ),
00202       m_bAutoCorrectionWithFormat( format.m_bAutoCorrectionWithFormat),
00203       m_bCapitalizeNameOfDays( format.m_bCapitalizeNameOfDays),
00204       m_bulletStyle( format.m_bulletStyle ),
00205       m_typographicSimpleQuotes( format.m_typographicSimpleQuotes ),
00206       m_typographicDoubleQuotes( format.m_typographicDoubleQuotes ),
00207       m_typographicDefaultDoubleQuotes( format.m_typographicDefaultDoubleQuotes),
00208       m_typographicDefaultSimpleQuotes( format.m_typographicDefaultSimpleQuotes),
00209       m_listCompletion( 0L ), // don't copy it!
00210       m_entries(17,false ),//don't copy it.
00211       m_allLanguages(17,false), //don't copy it
00212       m_superScriptEntries ( format.m_superScriptEntries ),
00213       m_upperCaseExceptions( format.m_upperCaseExceptions ),
00214       m_twoUpperLetterException( format.m_twoUpperLetterException ),
00215       m_maxFindLength( format.m_maxFindLength ),
00216       m_minCompletionWordLength( format.m_minCompletionWordLength ),
00217       m_nbMaxCompletionWord( format.m_nbMaxCompletionWord ),
00218       m_cacheNameOfDays( format.m_cacheNameOfDays),
00219       m_completionBox(0),
00220       m_keyCompletionAction( format.m_keyCompletionAction )
00221 {
00222     //m_listCompletion=new KCompletion();
00223     //m_listCompletion->setItems( autoFormat.listCompletion() );
00224     //copyAutoFormatEntries( autoFormat );
00225 }
00226 
00227 KoAutoFormat::~KoAutoFormat()
00228 {
00229     delete m_listCompletion;
00230     m_entries.setAutoDelete( true );
00231     m_entries.clear();
00232     m_allLanguages.setAutoDelete( true );
00233     m_allLanguages.clear();
00234 }
00235 
00236 void KoAutoFormat::updateMaxWords()
00237 {
00238     QStringList list = m_listCompletion->items();
00239     for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
00240     {
00241         QString tmp = *it;
00242         uint maxword = 1;
00243 
00244         for (uint i=0; i < (uint)tmp.length(); i++)
00245                 if ( tmp.at(i).isSpace() || tmp.at(i).isPunct() )
00246                         maxword++;
00247         if (maxword >  m_countMaxWords )
00248                 m_countMaxWords = maxword;
00249     }
00250     kdDebug() << "m_countMaxWords: " << m_countMaxWords << endl;
00251 }
00252 
00253 void KoAutoFormat::loadListOfWordCompletion()
00254 {
00255     KConfig* config = KoGlobal::kofficeConfig();
00256     KConfigGroupSaver cgs( config, "Completion Word" );
00257     m_listCompletion->insertItems(config->readListEntry( "list" ));
00258 }
00259 
00260 void KoAutoFormat::readConfig(bool force)
00261 {
00262     // Read the autoformat configuration
00263     // This is done on demand (when typing the first char, or when opening the config dialog)
00264     // so that loading is faster and to avoid doing it for readonly documents.
00265     if ( m_configRead && !force )
00266         return;
00267     KConfig* config = KoGlobal::kofficeConfig();
00268     KConfigGroupSaver cgs( config, "AutoFormat" );
00269     //when we force don't load format language.
00270     if ( !force)
00271         m_autoFormatLanguage = config->readEntry("formatLanguage", QString::null);
00272 
00273     m_convertUpperCase = config->readBoolEntry( "ConvertUpperCase", false );
00274     m_convertUpperUpper = config->readBoolEntry( "ConvertUpperUpper", false );
00275     m_includeTwoUpperLetterException = config->readBoolEntry( "includeTwoLetterException", false );
00276     m_includeAbbreviation = config->readBoolEntry( "includeAbbreviation", false );
00277 
00278     m_advancedAutoCorrect = config->readBoolEntry( "AdvancedAutocorrect", true );
00279     m_bAutoCorrectionWithFormat = config->readBoolEntry( "AutoCorrectionWithFormat",false );
00280     m_bCapitalizeNameOfDays = config->readBoolEntry( "CapitalizeNameOfDays",false );
00281 
00282     m_autoDetectUrl = config->readBoolEntry("AutoDetectUrl",false);
00283     m_ignoreDoubleSpace = config->readBoolEntry("IgnoreDoubleSpace",false);
00284     m_removeSpaceBeginEndLine = config->readBoolEntry("RemoveSpaceBeginEndLine",false);
00285 
00286     m_useBulletStyle = config->readBoolEntry("UseBulletStyle",false);
00287     QString tmp = config->readEntry( "BulletStyle", "" );
00288     m_bulletStyle = tmp.isEmpty() ? QChar() : tmp[0];
00289 
00290     m_autoChangeFormat = config->readBoolEntry( "AutoChangeFormat", false );
00291 
00292     m_autoReplaceNumber = config->readBoolEntry( "AutoReplaceNumber", false );
00293 
00294     m_useAutoNumberStyle = config->readBoolEntry( "AutoNumberStyle", false );
00295 
00296 
00297     QString beginDoubleQuote = config->readEntry( "TypographicQuotesBegin" );
00298     QString endDoubleQuote = config->readEntry( "TypographicQuotesEnd" );
00299 
00300     m_typographicDoubleQuotes.replace = config->readBoolEntry( "TypographicQuotesEnabled", false );
00301 
00302     QString begin = config->readEntry( "TypographicSimpleQuotesBegin" );
00303     QString end = config->readEntry( "TypographicSimpleQuotesEnd" );
00304     m_typographicSimpleQuotes.replace = config->readBoolEntry( "TypographicSimpleQuotesEnabled", false );
00305 
00306     m_bAutoSuperScript = config->readBoolEntry( "AutoSuperScript", false );
00307 
00308     config->setGroup( "completion" );
00309     m_completion = config->readBoolEntry( "completion", false );
00310 
00311     m_completionAppendSpace = config->readBoolEntry( "CompletionAppendSpace", false );
00312     m_minCompletionWordLength = config->readUnsignedNumEntry( "CompletionMinWordLength", 5 );
00313     m_nbMaxCompletionWord = config->readUnsignedNumEntry( "NbMaxCompletionWord", 100 );
00314     m_addCompletionWord = config->readBoolEntry( "AddCompletionWord", true );
00315     m_toolTipCompletion = config->readBoolEntry( "ToolTipCompletion", true );
00316     m_keyCompletionAction = ( KoAutoFormat::KeyCompletionAction )config->readUnsignedNumEntry( "CompletionKeyAction", 0 );
00317 
00318     if ( force )
00319     {
00320         m_entries.setAutoDelete(true);
00321         m_entries.clear();
00322         m_entries.setAutoDelete(false);
00323         m_allLanguages.setAutoDelete(true);
00324         m_allLanguages.clear();
00325         m_allLanguages.setAutoDelete(false);
00326         m_upperCaseExceptions.clear();
00327         m_superScriptEntries.clear();
00328         m_twoUpperLetterException.clear();
00329 
00330     }
00331 
00332     //config->setGroup( "AutoFormatEntries" );
00333 
00334     readAutoCorrectConfig();
00335 
00336     if( beginDoubleQuote.isEmpty())
00337     {
00338         if( m_typographicDefaultDoubleQuotes.begin.isNull())
00339             m_typographicDoubleQuotes.begin = QChar('«');
00340         else
00341             m_typographicDoubleQuotes.begin = m_typographicDefaultDoubleQuotes.begin;
00342     }
00343     else
00344         m_typographicDoubleQuotes.begin = beginDoubleQuote[0];
00345 
00346     if( endDoubleQuote.isEmpty() )
00347     {
00348         if( m_typographicDefaultDoubleQuotes.end.isNull())
00349             m_typographicDoubleQuotes.end = QChar('»');
00350         else
00351             m_typographicDoubleQuotes.end = m_typographicDefaultDoubleQuotes.end;
00352     }
00353     else
00354         m_typographicDoubleQuotes.end = endDoubleQuote[0];
00355 
00356     m_typographicDoubleQuotes.replace = m_typographicDoubleQuotes.replace
00357                                         && !m_typographicDoubleQuotes.begin.isNull()
00358                                         && !m_typographicDoubleQuotes.end.isNull();
00359 
00360 
00361     if( begin.isEmpty())
00362     {
00363         if( m_typographicDefaultSimpleQuotes.begin.isNull())
00364             m_typographicSimpleQuotes.begin = QChar('\'');
00365         else
00366             m_typographicSimpleQuotes.begin = m_typographicDefaultSimpleQuotes.begin;
00367     }
00368     else
00369         m_typographicSimpleQuotes.begin = begin[0];
00370 
00371     if( end.isEmpty() )
00372     {
00373         if( m_typographicDefaultSimpleQuotes.end.isNull())
00374             m_typographicSimpleQuotes.end = QChar('\'');
00375         else
00376             m_typographicSimpleQuotes.end = m_typographicDefaultSimpleQuotes.end;
00377     }
00378     else
00379         m_typographicSimpleQuotes.end = end[0];
00380 
00381     m_typographicSimpleQuotes.replace = m_typographicSimpleQuotes.replace
00382                                         && !m_typographicSimpleQuotes.end.isNull()
00383                                         && !m_typographicSimpleQuotes.begin.isNull();
00384 
00385 
00386     loadAllLanguagesAutoCorrection();
00387     buildMaxLen();
00388     autoFormatIsActive();
00389     m_configRead = true;
00390 }
00391 
00392 void KoAutoFormat::readAutoCorrectConfig()
00393 {
00394     Q_ASSERT( m_entries.isEmpty() ); // readConfig is only called once...
00395     KLocale klocale(m_doc->instance()->instanceName());
00396     QString kdelang = klocale.languageList().front();
00397     kdelang.remove( QRegExp( "@.*" ) );
00398     kdDebug(32500) << "KoAutoFormat: m_autoFormatLanguage=" << m_autoFormatLanguage << " kdelang=" << kdelang << endl;
00399     QString fname;
00400     if ( !m_autoFormatLanguage.isEmpty() )
00401     {
00402         fname = locate( "data", "koffice/autocorrect/" + m_autoFormatLanguage + ".xml", m_doc->instance() );
00403     }
00404     if ( m_autoFormatLanguage != "all_languages" )
00405     {
00406         if ( fname.isEmpty() && !kdelang.isEmpty() )
00407             fname = locate( "data", "koffice/autocorrect/" + kdelang + ".xml", m_doc->instance() );
00408         if ( fname.isEmpty() && kdelang.contains("_") )
00409         {
00410             kdelang.remove( QRegExp( "_.*" ) );
00411             fname = locate( "data", "koffice/autocorrect/" + kdelang + ".xml", m_doc->instance() );
00412         }
00413         if ( fname.isEmpty() )
00414             fname = locate( "data", "koffice/autocorrect/autocorrect.xml", m_doc->instance() );
00415     }
00416     if ( fname.isEmpty() )
00417         return;
00418     QFile xmlFile(fname);
00419     if(!xmlFile.open(IO_ReadOnly))
00420         return;
00421 
00422     QDomDocument doc;
00423     if(!doc.setContent(&xmlFile))
00424         return;
00425 
00426     if(doc.doctype().name() != "autocorrection") {
00427         //return;
00428     }
00429     QDomElement de=doc.documentElement();
00430 
00431     loadAutoCorrection( de );
00432 
00433     QDomElement upper = de.namedItem( "UpperCaseExceptions" ).toElement();
00434     if(!upper.isNull())
00435     {
00436         QDomNodeList nl = upper.childNodes();
00437         for(uint i = 0; i < nl.count(); i++)
00438         {
00439             m_upperCaseExceptions+= nl.item(i).toElement().attribute("exception");
00440         }
00441     }
00442 
00443     QDomElement twoUpper = de.namedItem( "TwoUpperLetterExceptions" ).toElement();
00444     if(!twoUpper.isNull())
00445     {
00446         QDomNodeList nl = twoUpper.childNodes();
00447         for(uint i = 0; i < nl.count(); i++)
00448         {
00449             m_twoUpperLetterException+= nl.item(i).toElement().attribute("exception");
00450         }
00451     }
00452 
00453     QDomElement superScript = de.namedItem( "SuperScript" ).toElement();
00454     if(!superScript.isNull())
00455     {
00456         QDomNodeList nl = superScript.childNodes();
00457         for(uint i = 0; i < nl.count() ; i++) {
00458             //bug in qmap we overwrite = false doesn't work
00459             //so we can't add multiple "othernb"
00460             m_superScriptEntries.insert( nl.item(i).toElement().attribute("find"), KoAutoFormatEntry(nl.item(i).toElement().attribute("super")),FALSE );
00461         }
00462     }
00463 
00464     QDomElement doubleQuote = de.namedItem( "DoubleQuote" ).toElement();
00465     if(!doubleQuote.isNull())
00466     {
00467         QDomElement childItem = doubleQuote.namedItem("doublequote").toElement();
00468         if ( !childItem.isNull() )
00469         {
00470             QString attr = childItem.attribute( "begin" );
00471             if ( !attr.isEmpty() && attr[0] != 0 )
00472                 m_typographicDefaultDoubleQuotes.begin = attr[0];
00473             attr = childItem.attribute( "end" );
00474             if ( !attr.isEmpty() && attr[0] != 0 )
00475                 m_typographicDefaultDoubleQuotes.end = attr[0];
00476         }
00477     }
00478     QDomElement simpleQuote = de.namedItem( "SimpleQuote" ).toElement();
00479     if(!simpleQuote.isNull())
00480     {
00481         QDomElement childItem = simpleQuote.namedItem("simplequote").toElement();
00482         if ( !childItem.isNull() )
00483         {
00484             QString attr = childItem.attribute( "begin" );
00485             if ( !attr.isEmpty() && attr[0] != 0 )
00486                 m_typographicDefaultSimpleQuotes.begin = attr[0];
00487             attr = childItem.attribute( "end" );
00488             if ( !attr.isEmpty() && attr[0] != 0 )
00489                 m_typographicDefaultSimpleQuotes.end = attr[0];
00490         }
00491     }
00492 }
00493 
00494 void KoAutoFormat::loadAllLanguagesAutoCorrection()
00495 {
00496     QString fname = locate( "data", "koffice/autocorrect/all_languages.xml", m_doc->instance() );
00497     if ( fname.isEmpty() )
00498         return;
00499     QFile xmlFile( fname );
00500     if(xmlFile.open(IO_ReadOnly))
00501     {
00502         QDomDocument doc;
00503         if(!doc.setContent(&xmlFile)) {
00504             return;
00505         }
00506         if(doc.doctype().name() != "autocorrection") {
00507             //return;
00508         }
00509         QDomElement de=doc.documentElement();
00510 
00511         loadAutoCorrection( de, true );
00512         xmlFile.close();
00513     }
00514 }
00515 
00516 void KoAutoFormat::loadAutoCorrection( const QDomElement & _de, bool _allLanguages )
00517 {
00518     QDomElement item = _de.namedItem( "items" ).toElement();
00519     if(!item.isNull())
00520     {
00521         QDomNodeList nl = item.childNodes();
00522         m_maxFindLength=nl.count();
00523         for(uint i = 0; i < m_maxFindLength; i++) {
00524             loadEntry( nl.item(i).toElement(), _allLanguages);
00525         }
00526     }
00527 }
00528 
00529 void KoAutoFormat::loadEntry( const QDomElement &nl, bool _allLanguages)
00530 {
00531     KoAutoFormatEntry *tmp =new KoAutoFormatEntry(nl.attribute("replace"));
00532     if ( nl.hasAttribute("FONT"))
00533     {
00534         tmp->createNewEntryContext();
00535         tmp->formatEntryContext()->m_family=nl.attribute("FONT");
00536         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Family;
00537     }
00538     if ( nl.hasAttribute("SIZE" ))
00539     {
00540         tmp->createNewEntryContext();
00541         tmp->formatEntryContext()->m_size = nl.attribute("SIZE" ).toInt();
00542         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Size;
00543     }
00544     if (nl.hasAttribute("BOLD" ))
00545     {
00546         tmp->createNewEntryContext();
00547         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Bold;
00548         QString value = nl.attribute("BOLD");
00549         if ( value.toInt() == 1 )
00550             tmp->formatEntryContext()->m_options |= KoSearchContext::Bold;
00551     }
00552     if (nl.hasAttribute("ITALIC" ))
00553     {
00554         tmp->createNewEntryContext();
00555         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Italic;
00556         QString value = nl.attribute("ITALIC");
00557         if ( value.toInt() == 1 )
00558             tmp->formatEntryContext()->m_options |= KoSearchContext::Italic;
00559     }
00560     if (nl.hasAttribute("UNDERLINE" ))
00561     {
00562         tmp->createNewEntryContext();
00563         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Underline;
00564         QString value = nl.attribute("UNDERLINE");
00565         if ( value =="single" )
00566             tmp->formatEntryContext()->m_underline = KoTextFormat::U_SIMPLE;
00567         else if ( value =="double" )
00568             tmp->formatEntryContext()->m_underline = KoTextFormat::U_DOUBLE;
00569         else if ( value =="single-bold" )
00570             tmp->formatEntryContext()->m_underline = KoTextFormat::U_SIMPLE_BOLD;
00571         else
00572             tmp->formatEntryContext()->m_underline = KoTextFormat::U_NONE;
00573     }
00574     if (nl.hasAttribute("STRIKEOUT" ))
00575     {
00576         tmp->createNewEntryContext();
00577         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::StrikeOut;
00578         QString value = nl.attribute("STRIKEOUT");
00579         if ( value =="single" )
00580             tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_SIMPLE;
00581         else if ( value =="double" )
00582             tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_DOUBLE;
00583         else if ( value =="single-bold" )
00584             tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_SIMPLE_BOLD;
00585         else
00586             tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_NONE;
00587     }
00588     if (nl.hasAttribute("VERTALIGN" ))
00589     {
00590         tmp->createNewEntryContext();
00591         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::VertAlign;
00592         QString value = nl.attribute("VERTALIGN");
00593         tmp->formatEntryContext()->m_vertAlign=static_cast<KoTextFormat::VerticalAlignment>( value.toInt() );
00594 
00595     }
00596     if ( nl.hasAttribute("TEXTCOLOR" ))
00597     {
00598         tmp->createNewEntryContext();
00599         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Color;
00600         QColor col( nl.attribute("TEXTCOLOR" ));
00601         tmp->formatEntryContext()->m_color = col;
00602     }
00603     if ( nl.hasAttribute("TEXTBGCOLOR" ))
00604     {
00605         tmp->createNewEntryContext();
00606         tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::BgColor;
00607         QColor col( nl.attribute("TEXTBGCOLOR" ));
00608         tmp->formatEntryContext()->m_backGroundColor = col;
00609     }
00610     if ( !_allLanguages )
00611         m_entries.insert( nl.attribute("find"), tmp );
00612     else
00613         m_allLanguages.insert( nl.attribute("find"), tmp );
00614 
00615 }
00616 
00617 void KoAutoFormat::saveConfig()
00618 {
00619     KConfig* config = KoGlobal::kofficeConfig();
00620     KLocale klocale(m_doc->instance()->instanceName());
00621 
00622     KConfigGroupSaver cgs( config, "AutoFormat" );
00623     config->writeEntry( "ConvertUpperCase", m_convertUpperCase );
00624     config->writeEntry( "formatLanguage", m_autoFormatLanguage=="all_languages" ? klocale.languageList().front() : m_autoFormatLanguage);
00625 
00626     config->writeEntry( "ConvertUpperUpper", m_convertUpperUpper );
00627     config->writeEntry( "includeTwoLetterException", m_includeTwoUpperLetterException );
00628     config->writeEntry( "includeAbbreviation", m_includeAbbreviation );
00629 
00630     config->writeEntry( "TypographicQuotesBegin", QString( m_typographicDoubleQuotes.begin ) );
00631     config->writeEntry( "TypographicQuotesEnd", QString( m_typographicDoubleQuotes.end ) );
00632     config->writeEntry( "TypographicQuotesEnabled", m_typographicDoubleQuotes.replace );
00633     config->writeEntry( "TypographicSimpleQuotesBegin", QString( m_typographicSimpleQuotes.begin ) );
00634     config->writeEntry( "TypographicSimpleQuotesEnd", QString( m_typographicSimpleQuotes.end ) );
00635     config->writeEntry( "TypographicSimpleQuotesEnabled", m_typographicSimpleQuotes.replace );
00636 
00637     config->writeEntry( "AdvancedAutocorrect", m_advancedAutoCorrect );
00638     config->writeEntry( "AutoCorrectionWithFormat", m_bAutoCorrectionWithFormat );
00639     config->writeEntry( "CapitalizeNameOfDays", m_bCapitalizeNameOfDays );
00640 
00641     config->writeEntry( "AutoDetectUrl",m_autoDetectUrl);
00642 
00643     config->writeEntry( "IgnoreDoubleSpace",m_ignoreDoubleSpace );
00644     config->writeEntry( "RemoveSpaceBeginEndLine",m_removeSpaceBeginEndLine );
00645 
00646     config->writeEntry( "UseBulletStyle", m_useBulletStyle);
00647     config->writeEntry( "BulletStyle", QString(m_bulletStyle));
00648 
00649     config->writeEntry( "AutoChangeFormat", m_autoChangeFormat);
00650 
00651     config->writeEntry( "AutoReplaceNumber", m_autoReplaceNumber);
00652 
00653     config->writeEntry( "AutoNumberStyle", m_useAutoNumberStyle );
00654 
00655     config->writeEntry( "AutoSuperScript", m_bAutoSuperScript );
00656 
00657     config->setGroup( "completion" );
00658     config->writeEntry( "completion", m_completion );
00659     config->writeEntry( "CompletionAppendSpace", m_completionAppendSpace );
00660     config->writeEntry( "CompletionMinWordLength", m_minCompletionWordLength);
00661     config->writeEntry( "NbMaxCompletionWord", m_nbMaxCompletionWord);
00662     config->writeEntry( "AddCompletionWord", m_addCompletionWord );
00663     config->writeEntry( "ToolTipCompletion", m_toolTipCompletion );
00664     config->writeEntry( "CompletionKeyAction", ( int )m_keyCompletionAction );
00665 
00666     config->setGroup( "AutoFormatEntries" );
00667     QDictIterator<KoAutoFormatEntry> it( m_entries );
00668 
00669     //refresh m_maxFindLength
00670     m_maxFindLength=0;
00671     QDomDocument doc("autocorrection");
00672 
00673     QDomElement begin = doc.createElement( "Word" );
00674     doc.appendChild( begin );
00675     QDomElement items;
00676     items = doc.createElement("items");
00677     QDomElement data;
00678     for ( ; it.current() ; ++it )
00679     {
00680     items.appendChild(saveEntry( it, doc));
00681         //m_maxFindLength=QMAX(m_maxFindLength,it.currentKey().length());
00682     }
00683     buildMaxLen();
00684     begin.appendChild(items);
00685 
00686     QDomElement upper;
00687     upper = doc.createElement("UpperCaseExceptions");
00688     for ( QStringList::Iterator it = m_upperCaseExceptions.begin(); it != m_upperCaseExceptions.end();++it )
00689     {
00690     data = doc.createElement("word");
00691     data.setAttribute("exception",(*it) );
00692     upper.appendChild(data);
00693     }
00694     begin.appendChild(upper);
00695 
00696     QDomElement twoUpper;
00697     twoUpper = doc.createElement("TwoUpperLetterExceptions");
00698 
00699     for ( QStringList::Iterator it = m_twoUpperLetterException.begin(); it != m_twoUpperLetterException.end();++it )
00700     {
00701     data = doc.createElement("word");
00702     data.setAttribute("exception",(*it) );
00703     twoUpper.appendChild(data);
00704     }
00705     begin.appendChild(twoUpper);
00706 
00707     QDomElement super;
00708     super = doc.createElement("SuperScript");
00709     KoAutoFormatEntryMap::Iterator it2 = m_superScriptEntries.begin();
00710     for ( ; it2 != m_superScriptEntries.end() ; ++it2 )
00711     {
00712     data = doc.createElement("superscript");
00713     data.setAttribute("find", it2.key());
00714     data.setAttribute("super", it2.data().replace());
00715     super.appendChild(data);
00716     }
00717     begin.appendChild(super);
00718 
00719     QDomElement doubleQuote;
00720     doubleQuote = doc.createElement("DoubleQuote");
00721     data = doc.createElement("doublequote");
00722     data.setAttribute("begin", QString(m_typographicDefaultDoubleQuotes.begin));
00723     data.setAttribute("end", QString(m_typographicDefaultDoubleQuotes.end));
00724     doubleQuote.appendChild(data);
00725     begin.appendChild(doubleQuote);
00726 
00727 
00728     QDomElement simpleQuote;
00729     simpleQuote = doc.createElement("SimpleQuote");
00730     data = doc.createElement("simplequote");
00731     data.setAttribute("begin", QString(m_typographicDefaultSimpleQuotes.begin));
00732     data.setAttribute("end", QString(m_typographicDefaultSimpleQuotes.end));
00733     simpleQuote.appendChild(data);
00734     begin.appendChild(simpleQuote);
00735     QFile f;
00736     if ( m_autoFormatLanguage.isEmpty())
00737         f.setName(locateLocal("data", "koffice/autocorrect/"+klocale.languageList().front() + ".xml",m_doc->instance()));
00738     else
00739         f.setName(locateLocal("data", "koffice/autocorrect/"+m_autoFormatLanguage + ".xml",m_doc->instance()));
00740     if(!f.open(IO_WriteOnly)) {
00741         kdWarning()<<"Error during saving autoformat to " << f.name() << endl;
00742     return;
00743     }
00744     QTextStream ts(&f);
00745     doc.save(ts, 2);
00746     f.close();
00747     autoFormatIsActive();
00748     config->sync();
00749 }
00750 
00751 QDomElement KoAutoFormat::saveEntry( QDictIterator<KoAutoFormatEntry> _entry, QDomDocument doc)
00752 {
00753     QDomElement data;
00754     data = doc.createElement("item");
00755     data.setAttribute("find", _entry.currentKey());
00756     data.setAttribute("replace", _entry.current()->replace());
00757     if ( _entry.current()->formatEntryContext() )
00758     {
00759         KoSearchContext *tmp = _entry.current()->formatEntryContext();
00760         if ( tmp->m_optionsMask & KoSearchContext::Family )
00761         {
00762             data.setAttribute("FONT", tmp->m_family);
00763         }
00764         if ( tmp->m_optionsMask &  KoSearchContext::Size )
00765         {
00766             data.setAttribute("SIZE", tmp->m_size);
00767         }
00768         if ( tmp->m_optionsMask & KoSearchContext::Italic )
00769         {
00770             data.setAttribute("ITALIC", static_cast<bool>(tmp->m_options & KoSearchContext::Italic));
00771         }
00772         if ( tmp->m_optionsMask & KoSearchContext::Bold )
00773         {
00774             data.setAttribute("BOLD", static_cast<bool>(tmp->m_options & KoSearchContext::Bold));
00775         }
00776         if ( tmp->m_optionsMask & KoSearchContext::Shadow )
00777         {
00778             data.setAttribute("SHADOWTEXT", static_cast<bool>(tmp->m_options & KoSearchContext::Shadow));
00779         }
00780         if ( tmp->m_optionsMask & KoSearchContext::WordByWord )
00781         {
00782             data.setAttribute("WORDBYWORD", static_cast<bool>(tmp->m_options & KoSearchContext::WordByWord));
00783         }
00784 
00785         if ( tmp->m_optionsMask & KoSearchContext::Underline )
00786         {
00787             switch( tmp->m_underline )
00788             {
00789             case KoTextFormat::U_SIMPLE:
00790                 data.setAttribute("UNDERLINE", "single");
00791                 break;
00792             case KoTextFormat::U_DOUBLE:
00793                 data.setAttribute("UNDERLINE", "double");
00794                 break;
00795             case KoTextFormat::U_SIMPLE_BOLD:
00796                 data.setAttribute("UNDERLINE", "single-bold");
00797                 break;
00798             case KoTextFormat::U_WAVE:
00799                 data.setAttribute("UNDERLINE", "wave");
00800                 break;
00801             case KoTextFormat::U_NONE:
00802                 data.setAttribute("UNDERLINE", "none");
00803                 break;
00804             }
00805         }
00806         if ( tmp->m_optionsMask & KoSearchContext::StrikeOut )
00807         {
00808             switch( tmp->m_strikeOut )
00809             {
00810             case KoTextFormat::S_SIMPLE:
00811                 data.setAttribute("STRIKEOUT", "single");
00812                 break;
00813             case KoTextFormat::S_DOUBLE:
00814                 data.setAttribute("STRIKEOUT", "double");
00815                 break;
00816             case KoTextFormat::S_NONE:
00817                 data.setAttribute("STRIKEOUT", "none");
00818                 break;
00819             case KoTextFormat::S_SIMPLE_BOLD:
00820                 data.setAttribute("STRIKEOUT", "single-bold");
00821                 break;
00822             }
00823         }
00824         if ( tmp->m_optionsMask & KoSearchContext::Attribute )
00825         {
00826             data.setAttribute("FONTATTRIBUTE", KoTextFormat::attributeFontToString( tmp->m_attribute ) );
00827         }
00828 
00829         if ( tmp->m_optionsMask & KoSearchContext::VertAlign)
00830         {
00831             data.setAttribute( "VERTALIGN", static_cast<int>(tmp->m_vertAlign) );
00832         }
00833         if ( tmp->m_optionsMask & KoSearchContext::BgColor )
00834         {
00835             data.setAttribute( "TEXTCOLOR", tmp->m_color.name());
00836         }
00837         if ( tmp->m_optionsMask & KoSearchContext::Color )
00838         {
00839             data.setAttribute( "TEXTCOLOR", tmp->m_color.name());
00840         }
00841         if ( tmp->m_optionsMask & KoSearchContext::BgColor )
00842         {
00843             data.setAttribute( "TEXTBGCOLOR", tmp->m_backGroundColor.name());
00844         }
00845         if ( tmp->m_optionsMask & KoSearchContext::Language )
00846             data.setAttribute( "LANGUAGE", tmp->m_language );
00847     }
00848     return data;
00849 }
00850 
00851 void KoAutoFormat::addAutoFormatEntry( const QString &key, const QString &replace )
00852 {
00853     KoAutoFormatEntry *findEntry = m_entries.find( key);
00854     if ( findEntry )
00855     {
00856         if ( findEntry->replace().lower() == replace.lower() )
00857             return;
00858     }
00859 
00860     KoAutoFormatEntry *tmp = new KoAutoFormatEntry( replace );
00861     m_entries.insert( key, tmp );
00862     saveConfig();
00863     buildMaxLen();
00864 }
00865 
00866 QString KoAutoFormat::getLastWord(KoTextParag *parag, int const index)
00867 {
00868     QString lastWord;
00869     KoTextString *s = parag->string();
00870     for ( int i = index - 1; i >= 0; --i )
00871     {
00872         QChar ch = s->at( i ).c;
00873         if ( ch.isSpace() || ch.isPunct() )
00874             break;
00875         lastWord.prepend( ch );
00876     }
00877     return lastWord;
00878 }
00879 
00880 QString KoAutoFormat::getLastWord(const int max_words, KoTextParag *parag, int const index)
00881 {
00882     QString lastWord;
00883     KoTextString const *s = parag->string();
00884     int words = 0;
00885     for ( int i = index - 1; i >= 0; --i )
00886     {
00887         QChar ch = s->at( i ).c;
00888         if ( ch.isSpace() || ch.isPunct() )
00889         {
00890                 ++words;
00891                 if (words >= max_words)
00892                         break;
00893         }
00894         lastWord.prepend( ch );
00895     }
00896     return lastWord;
00897 }
00898 
00899 QString KoAutoFormat::getWordAfterSpace(KoTextParag *parag, int const index)
00900 {
00901     QString word;
00902     KoTextString *s = parag->string();
00903     for ( int i = index - 1; i >= 0; --i )
00904     {
00905         QChar ch = s->at( i ).c;
00906         if ( ch.isSpace() )
00907             break;
00908         word.prepend( ch );
00909     }
00910     return word;
00911 
00912 }
00913 
00914 bool KoAutoFormat::doCompletion( KoTextCursor* textEditCursor, KoTextParag *parag, int const index, KoTextObject *txtObj )
00915 {
00916     if( m_completion )
00917     {
00918         bool part=false;
00919         QString lastWord, word;
00920         if (m_completionBox && m_completionBox->isShown() ) //word completion with the tool-tip box
00921         {
00922                 word = m_completionBox->text();
00923                 lastWord = m_completionBox->lastWord();
00924         }
00925         else
00926         {
00927                 QStringList wordlist, new_wordlist;
00928                 for (uint i=1; i <= m_countMaxWords; i++ )
00929                 {
00930                         lastWord = getLastWord(i, parag, index+1);
00931                         wordlist += m_listCompletion->substringCompletion( lastWord ); //find all completion words that contains lastWord
00932                 }
00933                 uint maxlength = 0;
00934                 for ( QStringList::ConstIterator it = wordlist.begin(); it != wordlist.end(); ++it ) // several completion words were found
00935                 {
00936                   if ( (*it).startsWith( lastWord, false ) && new_wordlist.find(*it) == new_wordlist.end() ) //the completion words that begin with lastWord
00937                   {
00938                     if ( (*it).length() > maxlength )
00939                       maxlength = (*it).length();
00940                     new_wordlist.append(*it);
00941                     //kdDebug() << "adding word completion:" << *it << endl;
00942                   }
00943                 }
00944                 if ( new_wordlist.isEmpty() )
00945                     return false;
00946                 if ( new_wordlist.count() == 1 ) // only one completion word was found
00947                   word = new_wordlist.first();
00948                 else
00949                 {
00950                   //we must extract the common part of the completions
00951                   for (uint i = lastWord.length(); i<maxlength && !part; i++) //iterate through all completion words
00952                   {
00953                     QChar ch = new_wordlist.first().at(i);
00954                     for (QStringList::ConstIterator it = new_wordlist.begin(); it != new_wordlist.end(); ++it )
00955                     {
00956                       if ( (*it).at(i).lower() != ch.lower() )
00957                       {
00958                         word = (*it).left(i); //the completion word is truncated here
00959                         //kdDebug() << "set the word completion to:" << word << endl;
00960                         part=true; // completion of a part of a word; a space-character after the completion should not be inserted
00961                         break;
00962                       }
00963                     }
00964                   }
00965                 }
00966                 if (word == lastWord)
00967                         return false;
00968 
00969                 word=lastWord+word.right(word.length()-lastWord.length() );
00970         }
00971         if( !word.isEmpty() )
00972         {
00973             int const lastword_length = lastWord.length();
00974             int const start = index+1 - lastword_length;
00975             int const length = word.length();
00976 
00977             KMacroCommand *macro = new KMacroCommand( i18n("Completion Word"));
00978             KoTextCursor cursor( parag->document() );
00979             cursor.setParag( parag );
00980             cursor.setIndex( start );
00981             KoTextDocument * textdoc = parag->textDocument();
00982             if( m_completionAppendSpace && !part)
00983                 word+=" ";
00984             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
00985             cursor.setIndex( start + lastword_length );
00986             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
00987 
00988             macro->addCommand( txtObj->replaceSelectionCommand( textEditCursor, word,
00989                                                               KoTextObject::HighlightSelection,
00990                                                               i18n("Completion Word") ));
00991 
00992             if ( m_completionAppendSpace && !m_ignoreUpperCase && (m_convertUpperUpper || m_convertUpperCase) && !part)
00993             {
00994                 //find the first word
00995                 for (uint i=1; i < word.length(); i++)
00996                         if ( word.at(i).isSpace() || word.at(i).isPunct() )
00997                         {
00998                                word.truncate(i);
00999                                break;
01000                         }
01001                 int const newPos = start + word.length();// + index - 3;
01002                 KCommand *cmd = doUpperCase( textEditCursor, parag, newPos, word, txtObj );
01003                 if( cmd )
01004                     macro->addCommand( cmd );
01005                 txtObj->emitHideCursor();
01006                 textEditCursor->setIndex(start+ length+1);
01007             }
01008             else
01009             {
01010                 txtObj->emitHideCursor();
01011                 textEditCursor->setIndex(start+ length);
01012             }
01013             txtObj->emitNewCommand( macro );
01014 
01015             // The space/tab/CR that we inserted is still there but delete/insert moved the cursor
01016             // -> go right
01017 
01018             txtObj->emitShowCursor();
01019             return true;
01020         }
01021     }
01022     return false;
01023 }
01024 
01025 bool KoAutoFormat::doToolTipCompletion( KoTextCursor* textEditCursor, KoTextParag *parag, int index, KoTextObject *txtObj, int keyPressed )
01026 {
01027     if( m_completion && m_toolTipCompletion && m_completionBox && m_completionBox->isShown() )
01028     {
01029         if ( ( keyPressed == Qt::Key_Return && m_keyCompletionAction==Enter )
01030              || ( keyPressed == Qt::Key_Enter && m_keyCompletionAction==Enter )
01031              || ( keyPressed == Qt::Key_Tab && m_keyCompletionAction==Tab )
01032              || ( keyPressed == Qt::Key_Space && m_keyCompletionAction==Space )
01033              || ( keyPressed == Qt::Key_End && m_keyCompletionAction==End )
01034              || ( keyPressed == Qt::Key_Right && m_keyCompletionAction==Right ))
01035         {
01036             return doCompletion(textEditCursor, parag, index, txtObj);
01037         }
01038     }
01039     return false;
01040 }
01041 void KoAutoFormat::showToolTipBox(KoTextParag *parag,  int index, QWidget *widget, const QPoint &pos )
01042 {
01043 
01044     if( m_completion && m_toolTipCompletion)
01045     {
01046         QString lastWord, word;
01047         for (uint i=1; i <= m_countMaxWords; i++ )
01048         {
01049                 lastWord = getLastWord(i, parag, index+1);
01050                 word=m_listCompletion->makeCompletion( lastWord );
01051                 if ( !word.isEmpty())
01052                         break;
01053         }
01054         if( !word.isEmpty() && word!=lastWord )
01055         {
01056             uint const length = lastWord.length();
01057             if (length<=3)
01058                 return;
01059             word=lastWord+word.right(word.length()-length);
01060             if (!m_completionBox)
01061                 m_completionBox = new KoCompletionBox(0,0,Qt::WType_Popup);
01062             QPoint const show_pos = widget->mapToGlobal(pos);
01063             m_completionBox->setText(word);
01064             m_completionBox->setLastWord(lastWord);
01065             m_completionBox->adjustSize();
01066             int const height = m_completionBox->sizeHint().height();
01067             m_completionBox->move( show_pos.x(), show_pos.y() - height );
01068 
01069             if (!m_completionBox->isShown() )
01070             {
01071                 m_completionBox->show();
01072                 widget->setFocus();
01073             }
01074         }
01075         else
01076                 removeToolTipCompletion();
01077     }
01078 }
01079 void KoAutoFormat::removeToolTipCompletion()
01080 {
01081     if (m_completion && m_toolTipCompletion && m_completionBox && m_completionBox->isShown())
01082         m_completionBox->hide();
01083 }
01084 
01085 void KoAutoFormat::autoFormatIsActive()
01086 {
01087     m_bAutoFormatActive = m_useBulletStyle ||
01088                           m_removeSpaceBeginEndLine ||
01089                           m_autoDetectUrl ||
01090                           m_convertUpperUpper ||
01091                           m_convertUpperCase ||
01092                           m_autoReplaceNumber ||
01093                           m_autoChangeFormat ||
01094                           m_completion ||
01095                           m_typographicDoubleQuotes.replace ||
01096                           m_typographicSimpleQuotes.replace ||
01097                           m_entries.count()!=0 ||
01098                           m_allLanguages.count()!=0;
01099 }
01100 
01101 void KoAutoFormat::doAutoFormat( KoTextCursor* textEditCursor, KoTextParag *parag, int index, QChar ch,KoTextObject *txtObj )
01102 {
01103     m_ignoreUpperCase = false;
01104 
01105     if ( !m_configRead )
01106         readConfig();
01107 
01108     if ( !m_bAutoFormatActive )
01109         return;
01110 
01111     if( ch.isSpace())
01112     {
01113         //a link doesn't have a space
01114         //=>m_ignoreUpperCase = false
01115         //m_ignoreUpperCase=false;
01116 
01117         QString word=getWordAfterSpace(parag,index);
01118 
01119         if ( m_autoChangeFormat && index > 3)
01120         {
01121             KCommand *cmd =doAutoChangeFormat( textEditCursor, parag, index, word, txtObj );
01122             if ( cmd )
01123                 txtObj->emitNewCommand( cmd );
01124 
01125         }
01126         if ( m_autoReplaceNumber )
01127         {
01128             KCommand *cmd = doAutoReplaceNumber( textEditCursor, parag, index, word, txtObj );
01129             if ( cmd )
01130                 txtObj->emitNewCommand( cmd );
01131         }
01132     }
01133 
01134     if( ch =='\n' )
01135     {
01136 
01137         if( m_removeSpaceBeginEndLine && index > 1)
01138         {
01139             KCommand *cmd = doRemoveSpaceBeginEndLine( textEditCursor, parag, txtObj, index );
01140             if ( cmd )
01141                 txtObj->emitNewCommand( cmd );
01142         }
01143         if( m_useBulletStyle  && index > 3)
01144         {
01145             KCommand *cmd =doUseBulletStyle( textEditCursor, parag, txtObj, index );
01146             if ( cmd )
01147                 txtObj->emitNewCommand( cmd );
01148         }
01149         if( m_useAutoNumberStyle && index > 3 )
01150         {
01151             KCommand *cmd =doUseNumberStyle( textEditCursor, parag, txtObj, index );
01152             if ( cmd )
01153                 txtObj->emitNewCommand( cmd );
01154         }
01155         if( m_convertUpperUpper && m_includeTwoUpperLetterException )
01156             doAutoIncludeUpperUpper(textEditCursor, parag, txtObj );
01157         if( m_convertUpperCase && m_includeAbbreviation )
01158             doAutoIncludeAbbreviation(textEditCursor, parag, txtObj );
01159     }
01160 
01161     //kdDebug(32500) << "KoAutoFormat::doAutoFormat ch=" << QString(ch) << endl;
01162     //if ( !m_enabled )
01163     //    return;
01164     // Auto-correction happens when pressing space, tab, CR, punct etc.
01165     if ( (ch.isSpace() || ch==':' || ch=='?' || ch=='!' || ch==','  || ch=='<'  || ch=='>' || (m_advancedAutoCorrect && ch=='.') ) && index > 0 )
01166     {
01167         KCommand *cmd = 0L;
01168         KMacroCommand *macro = 0L;
01169         QString lastWord = getWordAfterSpace(parag, index);
01170         //kdDebug(32500) << "KoAutoFormat::doAutoFormat lastWord=" << lastWord << endl;
01171 
01172         if ( ch == '.')
01173                 detectStartOfLink( parag, index, true );
01174         else
01175                 detectStartOfLink( parag, index, false );
01176 
01177         if ( !m_wordInserted && m_advancedAutoCorrect && !m_ignoreUpperCase)
01178         {
01179                 int const completionBeginPos = index -lastWord.length();
01180                 int newPos = index;
01181                 cmd = doAutoCorrect( textEditCursor, parag, newPos, txtObj );
01182 
01183                 if( cmd )
01184                 {
01185                 if (!macro)
01186                         macro = new KMacroCommand(i18n("Autocorrection"));
01187                 macro->addCommand( cmd );
01188                 }
01189 
01190                 int const endPos=textEditCursor->index();
01191                 bool was_a_replacement;
01192                 if (index == newPos)
01193                         was_a_replacement = false;
01194                 else
01195                         was_a_replacement = true;
01196 
01197                 if( was_a_replacement) // a replacement took place
01198                 {
01199                         txtObj->emitHideCursor();
01200                         if(endPos==0) //new line, the user pressed enter
01201                         {
01202                                 textEditCursor->gotoUp();
01203                                 textEditCursor->gotoLineEnd();
01204                                 newPos=textEditCursor->index();
01205                         }
01206                         else
01207                                 newPos= endPos-1;
01208 
01209                         m_wordInserted = true; //don't allow other replacements in this replacement
01210                         for(int i=completionBeginPos; i<newPos;i++)
01211                         {
01212                                 textEditCursor->setIndex(i);
01213                                 doAutoFormat( textEditCursor, parag, i, parag->toString().at(i),txtObj );
01214 
01215                         }
01216                         textEditCursor->setIndex(newPos);
01217                         doAutoFormat( textEditCursor, parag, newPos, ch,txtObj );
01218                         m_wordInserted = false;
01219                         if (endPos==0)
01220                         {
01221                                 textEditCursor->gotoLineStart();
01222                                 textEditCursor->gotoDown();
01223                         }
01224                         else
01225                                 textEditCursor->setIndex(newPos+1);
01226                         txtObj->emitShowCursor();
01227                         return;
01228                 }
01229 
01230         }
01231 
01232         if (!m_ignoreUpperCase && m_bCapitalizeNameOfDays)
01233         {
01234             KCommand *cmd = doCapitalizeNameOfDays( textEditCursor, parag, index, lastWord, txtObj  );
01235 
01236             if( cmd )
01237             {
01238                 if (!macro)
01239                 macro = new KMacroCommand(i18n("Autocorrection"));
01240                 macro->addCommand( cmd );
01241                 m_ignoreUpperCase = true;
01242             }
01243         }
01244 
01245         if (ch=='.')
01246                 return;
01247 
01248         //kdDebug(32500)<<" m_listCompletion->items() :"<<m_listCompletion->items()<<endl;
01249         if( !m_ignoreUpperCase && m_completion && m_addCompletionWord && m_listCompletion->items().count() < m_nbMaxCompletionWord )
01250         {
01251                 QString completionWord("");
01252                 QChar ch;
01253                 for (uint i=0;i<lastWord.length();i++)
01254                 {
01255                         ch = lastWord.at(i);
01256                         if (ch.isPunct() && ch!='-' && ch!='=' )
01257                         {
01258                                 if (completionWord.at(0) == '-')
01259                                         completionWord.remove(0,1);
01260 
01261                                 if (completionWord.length()>= m_minCompletionWordLength  && !completionWord.isEmpty() && m_listCompletion->makeCompletion(completionWord).isEmpty())
01262                                 {
01263                                         kdDebug() << "Adding:" << completionWord << endl;
01264                                         m_listCompletion->addItem( completionWord );
01265                                         if ( completionWord.length() > m_countMaxWords )
01266                                             m_countMaxWords = completionWord.length();
01267 
01268                                 }
01269                                 completionWord = "";
01270                         }
01271                         else
01272                         {
01273                                 completionWord.append(ch);
01274                                 if (i==lastWord.length()-1)
01275                                 {
01276                                         if (completionWord.at(0) == '-')
01277                                                 completionWord.remove(0,1);
01278                                         if (completionWord.at(completionWord.length()-1) == '-')
01279                                                 completionWord.truncate(completionWord.length()-1);
01280                                         completionWord.remove('=');
01281                                         if (completionWord.length()>= m_minCompletionWordLength && !completionWord.isEmpty() && m_listCompletion->makeCompletion(completionWord).isEmpty())
01282                                         {
01283                                                 kdDebug() << "Adding:" << completionWord << endl;
01284                                                 m_listCompletion->addItem( completionWord );
01285                                                 if ( completionWord.length() > m_countMaxWords )
01286                                                     m_countMaxWords = completionWord.length();
01287                                         }
01288                                 }
01289                         }
01290                 }
01291         }
01292 
01293         if( m_autoDetectUrl && m_ignoreUpperCase && (ch!='?' || lastWord.at(lastWord.length()-1)=='?') )
01294         {
01295                 doAutoDetectUrl( textEditCursor, parag, index, lastWord, txtObj );
01296                 //textEditCursor->gotoRight();
01297         }
01298 
01299         if (!m_ignoreUpperCase && (m_convertUpperUpper || m_convertUpperCase) )
01300         {
01301             cmd = doUpperCase( textEditCursor, parag, index, lastWord, txtObj );
01302 
01303             if( cmd )
01304             {
01305                 if (!macro)
01306                     macro = new KMacroCommand(i18n("Autocorrection"));
01307                 macro->addCommand( cmd );
01308             }
01309         }
01310 
01311         if ( macro )
01312             txtObj->emitNewCommand( macro );
01313 
01314         if(!m_ignoreUpperCase &&  m_bAutoSuperScript && m_superScriptEntries.count()>0)
01315         {
01316             if( lastWord.at(0).isPunct() )
01317                 lastWord.remove(0,1);
01318             KCommand * cmd = doAutoSuperScript( textEditCursor, parag, index, lastWord, txtObj  );
01319             if ( cmd )
01320                 txtObj->emitNewCommand( cmd );
01321         }
01322 
01323     }
01324     else
01325     {
01326         if ( ch == '"' && m_typographicDoubleQuotes.replace )
01327         {
01328                 KCommand *cmd = doTypographicQuotes( textEditCursor, parag, index, txtObj, true /*double quote*/ );
01329                 if ( cmd )
01330                 txtObj->emitNewCommand( cmd );
01331         }
01332         else if ( ch == '\'' && m_typographicDoubleQuotes.replace )
01333         {
01334                 KCommand *cmd = doTypographicQuotes( textEditCursor, parag, index, txtObj, false /* simple quote*/ );
01335                 if ( cmd )
01336                 txtObj->emitNewCommand( cmd );
01337         }
01338     }
01339 }
01340 
01341 KCommand *KoAutoFormat::doAutoCorrect( KoTextCursor* textEditCursor, KoTextParag *parag, int &index, KoTextObject *txtObj )
01342 {
01343     //if(!m_advancedAutoCorrect)
01344       //  return 0L;
01345     // Prepare an array with words of different lengths, all terminating at "index".
01346     // Obviously only full words are put into the array
01347     // But this allows 'find strings' with spaces and punctuation in them.
01348     QString * wordArray = new QString[m_maxFindLength+1];
01349     {
01350         QString word;
01351         KoTextString *s = parag->string();
01352         for ( int i = index - 1; i >= 0; --i )
01353         {
01354             QChar ch = s->at( i ).c;
01355         // It's necessary to stop at spaces - #99063
01356             if ( ch.isSpace() /*|| ch.isPunct()*/ || i==0)
01357             {
01358                 if(i==0 && word.length()<m_maxFindLength)
01359                     word.prepend( ch );
01360                 wordArray[word.length()]=word;
01361             }
01362             word.prepend( ch );
01363             if (((index - 1)-i) == (int)m_maxFindLength)
01364                 break;
01365         }
01366 
01367     }
01368     KCommand *cmd = autoFormatWord( textEditCursor, parag, index, txtObj, wordArray, false );
01369     if ( !cmd )
01370         cmd = autoFormatWord( textEditCursor, parag, index, txtObj, wordArray, true );
01371     delete [] wordArray;
01372     return cmd;
01373 }
01374 
01375 
01376 KCommand *KoAutoFormat::autoFormatWord( KoTextCursor* textEditCursor, KoTextParag *parag, int &index, KoTextObject *txtObj, QString * _wordArray, bool _allLanguages )
01377 {
01378     KoTextDocument * textdoc = parag->textDocument();
01379 
01380     // Now for each entry in the autocorrect list, look if
01381     // the word of the same size in wordArray matches.
01382     // This allows an o(n) behaviour instead of an o(n^2).
01383     for(int i=m_maxFindLength;i>0;--i)
01384     {
01385         if ( !_wordArray[i].isEmpty())
01386         {
01387             KoAutoFormatEntry* it = 0L;
01388             if ( _allLanguages )
01389                 it = m_allLanguages[ _wordArray[i] ];
01390             else
01391                 it = m_entries[ _wordArray[i] ];
01392             if ( _wordArray[i]!=0  && it )
01393             {
01394                 unsigned int length = _wordArray[i].length();
01395                 int const start = index - length;
01396                 KoTextCursor cursor( parag->document() );
01397                 cursor.setParag( parag );
01398                 cursor.setIndex( start );
01399                 textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01400                 cursor.setIndex( start + length );
01401                 textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01402                 KCommand *cmd = 0L;
01403                 kdDebug()<<"it->replace() :"<<it->replace()<<endl;
01404                 if (!it->formatEntryContext() || !m_bAutoCorrectionWithFormat)
01405                 {
01406                     cmd = txtObj->replaceSelectionCommand( textEditCursor, it->replace(),
01407                                                            KoTextObject::HighlightSelection,
01408                                                            i18n("Autocorrect Word") );
01409                 }
01410                 else
01411                 {
01412                     int flags = 0;
01413                     KoTextFormat * lastFormat = parag->at( start )->format();
01414                     KoTextFormat * newFormat = new KoTextFormat(*lastFormat);
01415                     changeTextFormat(it->formatEntryContext(), newFormat, flags );
01416                     KMacroCommand *macro = new KMacroCommand( i18n("Autocorrect Word with Format"));
01417                     KCommand *cmd2=txtObj->replaceSelectionCommand( textEditCursor, it->replace(),
01418                                                                     KoTextObject::HighlightSelection,
01419                                                                     i18n("Autocorrect Word") );
01420                     if ( cmd2 )
01421                         macro->addCommand(cmd2);
01422                     KoTextCursor cursor( parag->document() );
01423                     cursor.setParag( parag );
01424                     cursor.setIndex( start );
01425                     textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01426                     cursor.setIndex( start + it->replace().length()/*+ length + 1*/ );
01427                     textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01428 
01429                     cmd2 =txtObj->setFormatCommand( textEditCursor, &lastFormat, newFormat, flags, false, KoTextObject::HighlightSelection );
01430                     macro->addCommand( cmd2);
01431 
01432                     index = index - length + it->replace().length();
01433                     textEditCursor->setIndex(index+1);
01434                     cmd2 =txtObj->setFormatCommand( textEditCursor, &newFormat, lastFormat, 0 );
01435                     macro->addCommand( cmd2);
01436                     parag->at( index+1 )->setFormat(lastFormat);
01437 
01438                     cmd = macro;
01439                     txtObj->emitHideCursor();
01440                     textEditCursor->gotoRight();
01441                     txtObj->emitShowCursor();
01442 
01443                     return cmd;
01444                 }
01445                 // The space/tab/CR that we inserted is still there but delete/insert moved the cursor
01446                 // -> go right
01447 
01448                 txtObj->emitHideCursor();
01449                 textEditCursor->gotoRight();
01450                 txtObj->emitShowCursor();
01451                 index = index - length + it->replace().length();
01452                 return cmd;
01453             }
01454         }
01455     }
01456     return 0L;
01457 }
01458 
01459 KCommand *KoAutoFormat::doTypographicQuotes( KoTextCursor* textEditCursor, KoTextParag *parag, int index, KoTextObject *txtObj, bool doubleQuotes )
01460 {
01461     //kdDebug(32500) << "KoAutoFormat::doTypographicQuotes" << endl;
01462     KoTextDocument * textdoc = parag->textDocument();
01463     KoTextCursor cursor( parag->document() );
01464     cursor.setParag( parag );
01465     cursor.setIndex( index );
01466     textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01467     cursor.setIndex( index + 1 );
01468     textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01469 
01470     // Need to determine if we want a starting or ending quote.
01471     // I see two solutions: either simply alternate, or depend on leading space.
01472     // MSWord does the latter afaics...
01473     QString replacement;
01474     if ( index > 0 && !parag->at( index - 1 )->c.isSpace() )
01475     {
01476         if( doubleQuotes )
01477             replacement = m_typographicDoubleQuotes.end;
01478         else
01479             replacement = m_typographicSimpleQuotes.end;
01480     }
01481     else
01482     {
01483         if( doubleQuotes )
01484             replacement = m_typographicDoubleQuotes.begin;
01485         else
01486             replacement = m_typographicSimpleQuotes.begin;
01487     }
01488     return txtObj->replaceSelectionCommand( textEditCursor, replacement,
01489                               KoTextObject::HighlightSelection,
01490                                             i18n("Typographic Quote") );
01491 }
01492 
01493 KCommand * KoAutoFormat::doUpperCase( KoTextCursor *textEditCursor, KoTextParag *parag,
01494                                 int index, const QString & word, KoTextObject *txtObj )
01495 {
01496     KoTextDocument * textdoc = parag->textDocument();
01497     unsigned int length = word.length();
01498     if (word.at(length-1) == '.' )
01499     {
01500         --index;
01501         --length;
01502     }
01503     int const start = index - length;
01504     KoTextCursor backCursor( parag->document() );
01505     backCursor.setParag( parag );
01506     backCursor.setIndex( start );
01507 
01508     // backCursor now points at the first char of the word
01509     QChar const firstChar = backCursor.parag()->at( backCursor.index() )->c;
01510 
01511     bool bNeedMove = false;
01512     KCommand *cmd = 0L;
01513     if ( m_convertUpperCase && isLower( firstChar ) )
01514     {
01515         bool beginningOfSentence = true; // true if beginning of text
01516         // Go back over any space/tab/CR
01517         while ( backCursor.index() > 0 || backCursor.parag()->prev() )
01518         {
01519             beginningOfSentence = false; // we could go back -> false unless we'll find '.'
01520             backCursor.gotoLeft();
01521             if ( !backCursor.parag()->at( backCursor.index() )->c.isSpace() )
01522                 break;
01523         }
01524         // We are now at the first non-space char before the word
01525         if ( !beginningOfSentence )
01526                 beginningOfSentence = isMark( backCursor.parag()->at( backCursor.index() )->c);
01527             //beginningOfSentence = isMark( backCursor.parag()->at( backCursor.index() )->c ) && (backCursor.parag()->at( backCursor.index()+1 )->c.isSpace());
01528         if ( !beginningOfSentence && start==0 )
01529             if ( parag->counter() || backCursor.parag()->at( backCursor.index() )->c.isPunct() )
01530                 beginningOfSentence = true;
01531 
01532         // Now look for exceptions
01533         if ( beginningOfSentence )
01534         {
01535             QChar const punct = backCursor.parag()->at( backCursor.index() )->c;
01536             QString const text = getLastWord( backCursor.parag(), backCursor.index() )
01537                            + punct;
01538                            kdDebug() << "text: " << text << endl;
01539             // text has the word at the end of the 'sentence', including the termination. Example: "Mr."
01540             beginningOfSentence = (m_upperCaseExceptions.findIndex(text)==-1); // Ok if we can't find it
01541         }
01542 
01543         if ( beginningOfSentence )
01544         {
01545             KoTextCursor cursor( parag->document() );
01546             cursor.setParag( parag );
01547             cursor.setIndex( start );
01548             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01549             cursor.setIndex( start + 1 );
01550             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01551             cmd = txtObj->replaceSelectionCommand( textEditCursor, QString( firstChar.upper() ),
01552                                       KoTextObject::HighlightSelection,
01553                                       i18n("Autocorrect (capitalize first letter)") );
01554             bNeedMove = true;
01555         }
01556     }
01557     else if ( m_convertUpperUpper && isUpper( firstChar ) && length > 2 )
01558     {
01559         backCursor.setIndex( backCursor.index() + 1 );
01560         QChar secondChar = backCursor.parag()->at( backCursor.index() )->c;
01561         //kdDebug(32500)<<" secondChar :"<<secondChar<<endl;
01562         if ( isUpper( secondChar ) )
01563         {
01564             // Check next letter - we still want to be able to write fully uppercase words...
01565             backCursor.setIndex( backCursor.index() + 1 );
01566             QChar thirdChar = backCursor.parag()->at( backCursor.index() )->c;
01567             if ( isLower( thirdChar ) && (m_twoUpperLetterException.findIndex(word)==-1))
01568             {
01569                 // Ok, convert
01570                 KoTextCursor cursor( parag->document() );
01571                 cursor.setParag( parag );
01572                 cursor.setIndex( start + 1 ); // After all the first letter's fine, so only change the second letter
01573                 textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01574                 cursor.setIndex( start + 2 );
01575                 textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01576 
01577                 QString replacement = word[1].lower();
01578                 cmd = txtObj->replaceSelectionCommand( textEditCursor, replacement,KoTextObject::HighlightSelection,i18n("Autocorrect (Convert two upper case letters to one upper case and one lower case letter.)") );
01579 
01580                 bNeedMove = true;
01581             }
01582         }
01583     }
01584     if ( bNeedMove )
01585     {
01586         if (word.at(word.length()-1) == '.' )
01587                 ++index;
01588         txtObj->emitHideCursor();
01589         textEditCursor->setParag( parag );
01590         textEditCursor->setIndex( index );
01591         textEditCursor->gotoRight(); // not the same thing as index+1, in case of CR
01592         txtObj->emitShowCursor();
01593     }
01594     return cmd;
01595 }
01596 
01597 KCommand * KoAutoFormat::doAutoReplaceNumber( KoTextCursor* textEditCursor, KoTextParag *parag, int& index, const QString & word , KoTextObject *txtObj )
01598 {
01599     unsigned int length = word.length();
01600     if ( length != 3 )
01601         return 0L;
01602     KoTextDocument * textdoc = parag->textDocument();
01603     int start = index - length;
01604     if( word == QString("1/2") || word == QString("1/4") || word == QString("3/4") )
01605     {
01606         KoTextCursor cursor( parag->document() );
01607         cursor.setParag( parag );
01608         cursor.setIndex( start );
01609         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01610         cursor.setIndex( start + length );
01611         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01612         QString replacement;
01613         if( word == QString("1/2") )
01614             replacement=QString("½");
01615         else if (word == QString("1/4") )
01616             replacement=QString("¼");
01617         else if (word == QString("3/4") )
01618             replacement=QString("¾");
01619         QString cmdName=i18n("Autocorrect (replace 1/2... with ")+QString("½...)");
01620         KCommand *cmd =txtObj->replaceSelectionCommand( textEditCursor, replacement,
01621                                                            KoTextObject::HighlightSelection,
01622                                                                 cmdName );
01623         txtObj->emitHideCursor();
01624         textEditCursor->gotoRight();
01625         txtObj->emitShowCursor();
01626         index = index - length + replacement.length();
01627         return cmd;
01628     }
01629     return 0L;
01630 }
01631 
01632 void KoAutoFormat::detectStartOfLink(KoTextParag * parag, int const index, bool const insertedDot)
01633 {
01634     QString word;
01635     KoTextString *s = parag->string();
01636     for ( int i = 0; i < index; ++i )
01637     {
01638         word.append( s->at( i ).c );
01639     }
01640 
01641     if (word.find("http")!=-1 || word.find("https")!=-1 || word.find("mailto")!=-1 || word.find("ftp")!=-1 || word.find("file")!=-1
01642         || word.find("news")!=-1 || word.find('@')!=-1)
01643                 m_ignoreUpperCase=true;
01644     else
01645     {
01646         int const tmp_pos=word.find("www.");
01647         if (tmp_pos!=-1 && (word.find('.',tmp_pos+4)!=-1 || insertedDot) )
01648                m_ignoreUpperCase=true;
01649     }
01650 }
01651 
01652 void KoAutoFormat::doAutoDetectUrl( KoTextCursor *textEditCursor, KoTextParag *parag, int &index, QString & word, KoTextObject *txtObj )
01653 {
01654     kdDebug() << "link:" << word << endl;
01655     char link_type = 0;
01656     int pos = word.find("http://");
01657     int tmp_pos = word.find("https://");
01658     if(tmp_pos<pos && tmp_pos!=-1)
01659           pos = tmp_pos;
01660     tmp_pos = word.find("mailto:/");
01661     if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
01662           pos = tmp_pos;
01663     tmp_pos = word.find("ftp://");
01664     if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
01665           pos = tmp_pos;
01666     tmp_pos = word.find("ftp.");
01667     if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
01668     {
01669           pos = tmp_pos;
01670           link_type = 3;
01671     }
01672     tmp_pos = word.find("file:/");
01673     if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
01674           pos = tmp_pos;
01675     tmp_pos = word.find("news:");
01676     if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
01677           pos = tmp_pos;
01678     tmp_pos = word.find("www.");
01679     if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1 && word.find('.',tmp_pos+4)!=-1 )
01680     {
01681           pos = tmp_pos;
01682           link_type = 2;
01683     }
01684     tmp_pos = word.find('@');
01685     if ( pos == -1 && tmp_pos != -1 )
01686     {
01687           pos = tmp_pos-1;
01688           QChar c;
01689           while( pos>=0 )
01690           {
01691                 c = word.at(pos);
01692                 if ( c.isPunct() && c!='.'&& c!='_' && c!='<' && c!='>' )    break;
01693                 else    --pos;
01694           }
01695           if ( pos == tmp_pos-1 ) //it not a valid address
01696           {
01697                 m_ignoreUpperCase = false;
01698                 pos = -1;
01699           }
01700           else
01701                 ++pos;
01702           link_type = 1;
01703     }
01704     if(pos!=-1)
01705     {
01706         // A URL inside e.g. quotes (like "http://www.koffice.org" with the quotes) shouldn't include the quote in the URL.
01707     while ( !word.at(word.length()-1).isLetter() &&  !word.at(word.length()-1).isDigit() && word.at(word.length()-1)!='/')
01708         {
01709                 word.truncate(word.length()-1);
01710                 --index;
01711         }
01712         word.remove(0,pos);
01713         unsigned int const length = word.length();
01714         int const start = index - length;
01715         KoTextCursor cursor( parag->document() );
01716         KoTextDocument * textdoc = parag->textDocument();
01717         cursor.setParag( parag );
01718         cursor.setIndex( start );
01719         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01720         cursor.setIndex( start + length );
01721         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01722         QString newWord = word;
01723         if(link_type==1)
01724             newWord = QString("mailto:") + word;
01725         else if(link_type==2)
01726             newWord = QString("http://") + word;
01727         else if(link_type==3)
01728             newWord = QString("ftp://") + word;
01729 
01730         KoVariable* var = new KoLinkVariable( textdoc, word, newWord, m_varFormatCollection->format( "STRING" ), m_varCollection );
01731         CustomItemsMap customItemsMap;
01732         customItemsMap.insert( 0, var );
01733         KoTextFormat * lastFormat = parag->at( start )->format();
01734         int origCursorIndex = textEditCursor->index();
01735         txtObj->insert( textEditCursor, lastFormat, KoTextObject::customItemChar(), false, true, i18n("Insert Variable"), customItemsMap,KoTextObject::HighlightSelection );
01736         var->recalc();
01737         parag->invalidate(0);
01738         parag->setChanged( true );
01739 
01740         // adjust index
01741         index -= length-1; // we removed length chars and inserted one instead
01742 
01743         txtObj->emitHideCursor();
01744         textEditCursor->setIndex( origCursorIndex - (length-1) );
01745         txtObj->emitShowCursor();
01746 
01747         // ###### TODO: Move to a common method, this code is duplicated...
01748         if ( m_completion && m_addCompletionWord && m_listCompletion->items().count() < m_nbMaxCompletionWord )
01749         {
01750             if (word.length()>= m_minCompletionWordLength  && !word.isEmpty() && m_listCompletion->makeCompletion(word).isEmpty())
01751             {
01752                 kdDebug() << "Adding:" << word << endl;
01753                 m_listCompletion->addItem( word );
01754                 if ( word.length() > m_countMaxWords )
01755                     m_countMaxWords = word.length();
01756             }
01757         }
01758     }
01759 }
01760 
01761 void KoAutoFormat::doAutoIncludeUpperUpper(KoTextCursor* /*textEditCursor*/, KoTextParag *parag, KoTextObject* /*txtObj*/ )
01762 {
01763     KoTextString *s = parag->string();
01764 
01765     if( s->length() < 2 )
01766         return;
01767 
01768     for (int i=0; i<=(s->length() - 1);i++)
01769     {
01770         QString word;
01771         for ( int j = i ; j < s->length() - 1; j++ )
01772         {
01773             QChar ch = s->at( j ).c;
01774             if ( ch.isSpace() )
01775                 break;
01776             word.append( ch );
01777         }
01778         if( word.length() > 2 && word.left(2)==word.left(2).upper() && word.at(3)!=word.at(3).upper() )
01779         {
01780             if ( m_twoUpperLetterException.findIndex(word )==-1)
01781                 m_twoUpperLetterException.append( word);
01782         }
01783         i+=word.length();
01784     }
01785 
01786 }
01787 
01788 
01789 void KoAutoFormat::doAutoIncludeAbbreviation(KoTextCursor* /*textEditCursor*/, KoTextParag *parag, KoTextObject* /*txtObj*/ )
01790 {
01791     KoTextString *s = parag->string();
01792     if( s->length() < 2 )
01793         return;
01794     for (int i=0; i<=(s->length() - 1);i++)
01795     {
01796         QString wordAfter;
01797         QString word;
01798 
01799         for ( int j = i ; j < s->length() - 1; j++ )
01800         {
01801             QChar ch = s->at( j ).c;
01802             if ( ch.isSpace() )
01803                 break;
01804             word.append( ch );
01805         }
01806         if ( isMark( word.at(word.length()-1)) )
01807         {
01808             for ( int j = i+word.length()+1 ; j < s->length() - 1; j++ )
01809             {
01810                 QChar ch = s->at( j ).c;
01811                 if ( ch.isSpace() )
01812                     break;
01813                 wordAfter.append( ch );
01814             }
01815             if( word.length()>1 && !wordAfter.isEmpty() && wordAfter.at(0)==wordAfter.at(0).lower())
01816             {
01817                 if ( m_upperCaseExceptions.findIndex(word )==-1)
01818                     m_upperCaseExceptions.append( word );
01819             }
01820         }
01821         i+=word.length();
01822         if( !wordAfter.isEmpty())
01823         {
01824             i+=wordAfter.length()+1;
01825         }
01826     }
01827 
01828 }
01829 
01830 
01831 KCommand * KoAutoFormat::doAutoChangeFormat( KoTextCursor *textEditCursor, KoTextParag *parag,int index, const QString & word, KoTextObject *txtObj )
01832 {
01833     bool underline = (word.at(0)=='_' && word.at(word.length()-1)=='_');
01834     bool bold = (word.at(0)=='*' && word.at(word.length()-1)=='*');
01835     if( bold || underline)
01836     {
01837         QString replacement=word.mid(1,word.length()-2);
01838         int start = index - word.length();
01839         KoTextDocument * textdoc = parag->textDocument();
01840         KMacroCommand *macro=new KMacroCommand(i18n("Autocorrection: Change Format"));
01841         KoTextCursor cursor( parag->document() );
01842 
01843         cursor.setParag( parag );
01844         cursor.setIndex( start );
01845         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01846         cursor.setIndex( start + word.length() );
01847         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01848         macro->addCommand(txtObj->replaceSelectionCommand( textEditCursor, replacement,
01849                                                            KoTextObject::HighlightSelection,
01850                                                            i18n("Autocorrect Word") ));
01851 
01852         KoTextFormat * lastFormat = parag->at( start )->format();
01853         KoTextFormat * newFormat = new KoTextFormat(*lastFormat);
01854         cursor.setIndex( start );
01855         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01856         cursor.setIndex( start + word.length()-2 );
01857         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01858 
01859         if( bold)
01860         {
01861             newFormat->setBold(true);
01862             macro->addCommand(txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::Bold , false,KoTextObject::HighlightSelection  ));
01863         }
01864         else if( underline )
01865         {
01866             newFormat->setUnderline(true);
01867             macro->addCommand(txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::Underline , false,KoTextObject::HighlightSelection  ));
01868         }
01869         txtObj->emitHideCursor();
01870         textEditCursor->gotoRight();
01871         txtObj->emitShowCursor();
01872         return macro;
01873     }
01874     return 0L;
01875 }
01876 
01877 KCommand *KoAutoFormat::doUseBulletStyle(KoTextCursor * /*textEditCursor*/, KoTextParag *parag, KoTextObject *txtObj, int& index )
01878 {
01879     KoTextDocument * textdoc = parag->textDocument();
01880     KoTextCursor cursor( parag->document() );
01881     KoTextString *s = parag->string();
01882     QChar ch = s->at( 0 ).c;
01883 
01884     if( m_useBulletStyle && (ch =='*' || ch == '-' || ch =='+') && (s->at(1).c).isSpace())
01885     {
01886         if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_FOOTNOTE )
01887             return 0L;
01888         KMacroCommand *macroCmd = new KMacroCommand( i18n("Autocorrect (use bullet style)"));
01889         cursor.setParag( parag );
01890         cursor.setIndex( 0 );
01891         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01892         cursor.setParag( parag );
01893         cursor.setIndex( 2 );
01894         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01895         KCommand *cmd=txtObj->removeSelectedTextCommand( &cursor, KoTextObject::HighlightSelection  );
01896         // Adjust index
01897         index -= 2;
01898         if(cmd)
01899             macroCmd->addCommand(cmd);
01900 
01901         cursor.setParag( parag );
01902         cursor.setIndex( 0 );
01903         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01904 
01905         cursor.setIndex( 2 );
01906         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01907 
01908 
01909         KoParagCounter c;
01910         if( m_bulletStyle.isNull() && (ch == '*' || ch == '+' || ch == '-'))
01911         {
01912             if ( ch =='*')
01913             {
01914                 c.setNumbering( KoParagCounter::NUM_LIST );
01915                 c.setStyle( KoParagCounter::STYLE_DISCBULLET );
01916             }
01917             else if ( ch =='+' || ch=='-')
01918             {
01919                 c.setNumbering( KoParagCounter::NUM_LIST );
01920                 c.setStyle( KoParagCounter::STYLE_CUSTOMBULLET );
01921                 if ( ch =='-' )
01922                     c.setCustomBulletCharacter( '-' );
01923                 else if ( ch=='+')
01924                     c.setCustomBulletCharacter( '+' );
01925             }
01926         }
01927         else
01928         {
01929             c.setNumbering( KoParagCounter::NUM_LIST );
01930             c.setStyle( KoParagCounter::STYLE_CUSTOMBULLET );
01931             c.setCustomBulletCharacter( m_bulletStyle );
01932         }
01933         c.setSuffix(QString::null);
01934         cmd=txtObj->setCounterCommand( &cursor, c ,KoTextObject::HighlightSelection );
01935         if( cmd)
01936             macroCmd->addCommand(cmd);
01937         if (parag->next() )
01938                 cursor.setParag( parag->next() );
01939         else
01940               return 0L;
01941 
01942         cursor.setIndex( 0 );
01943         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01944         cursor.setIndex( 0 );
01945         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01946         cmd=txtObj->setCounterCommand( &cursor, c ,KoTextObject::HighlightSelection );
01947         if(cmd)
01948             macroCmd->addCommand(cmd);
01949         return macroCmd;
01950     }
01951     return 0L;
01952 
01953 }
01954 
01955 KCommand *KoAutoFormat::doUseNumberStyle(KoTextCursor * /*textEditCursor*/, KoTextParag *parag, KoTextObject *txtObj, int& index )
01956 {
01957     if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_FOOTNOTE )
01958         return 0L;
01959     KoTextDocument * textdoc = parag->textDocument();
01960     KoTextCursor cursor( parag->document() );
01961     KoTextString *s = parag->string();
01962     QString word;
01963     for ( int i = 0 ; i < s->length() - 1; i++ )
01964     {
01965         QChar ch = s->at( i ).c;
01966         if ( ch.isSpace() )
01967             break;
01968         word.append( ch );
01969     }
01970     QChar punct=word[word.length()-1];
01971     if( punct.isPunct() )
01972     {
01973         QString number=word.mid(0,word.length()-1);
01974         bool ok;
01975         uint val=number.toUInt(&ok);
01976         if( ok )
01977         {
01978             KMacroCommand *macroCmd = new KMacroCommand( i18n("Autocorrect (use number style)"));
01979             cursor.setParag( parag );
01980             cursor.setIndex( 0 );
01981             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01982             cursor.setParag( parag );
01983             cursor.setIndex( word.length()+1 );
01984             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01985             KCommand *cmd=txtObj->removeSelectedTextCommand( &cursor, KoTextObject::HighlightSelection  );
01986             // Adjust index
01987             index -= word.length()+1;
01988             if(cmd)
01989                 macroCmd->addCommand(cmd);
01990 
01991             // Apply counter to this paragraph
01992             cursor.setParag( parag );
01993             cursor.setIndex( 0 );
01994             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
01995 
01996             cursor.setIndex( 2 );
01997             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
01998 
01999             KoParagCounter c;
02000             c.setNumbering( KoParagCounter::NUM_LIST );
02001             c.setStyle( KoParagCounter::STYLE_NUM );
02002             c.setSuffix(QString( punct ));
02003             c.setStartNumber( (int)val);
02004 
02005             // Look at which number this parag will have without a restart counter flag,
02006             // to see if we need it. Thanks to Shaheed for number() taking a parag as param,
02007             // so that it works even if the parag doesn't have this counter yet!
02008             if ( c.number( parag ) != (int)val )
02009                 c.setRestartCounter( true );
02010 
02011             cmd=txtObj->setCounterCommand( &cursor, c, KoTextObject::HighlightSelection );
02012             if( cmd)
02013                 macroCmd->addCommand(cmd);
02014             // Apply counter to next paragraph too
02015             // but without restart
02016             c.setRestartCounter( false );
02017             cursor.setParag( parag->next() );
02018             cursor.setIndex( 0 );
02019             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
02020             cursor.setIndex( 0 );
02021             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
02022             cmd=txtObj->setCounterCommand( &cursor, c, KoTextObject::HighlightSelection );
02023             if(cmd)
02024                 macroCmd->addCommand(cmd);
02025             return macroCmd;
02026         }
02027     }
02028     return 0L;
02029 }
02030 
02031 
02032 KCommand * KoAutoFormat::doRemoveSpaceBeginEndLine( KoTextCursor *textEditCursor, KoTextParag *parag, KoTextObject *txtObj, int &index )
02033 {
02034     KoTextString *s = parag->string();
02035     KoTextDocument * textdoc = parag->textDocument();
02036     KoTextCursor cursor( parag->document() );
02037 
02038     KMacroCommand *macroCmd = 0L;
02039     // Cut away spaces at end of paragraph
02040     for ( int i = parag->lastCharPos(); i >= 0; --i )
02041     {
02042         QChar ch = s->at( i ).c;
02043         if ( ch != ' ' )   // was: !ch.isSpace(), but this includes tabs, and this option is only about spaces
02044         {
02045             if( i == parag->lastCharPos() )
02046                 break;
02047             cursor.setParag( parag );
02048             cursor.setIndex( i+1 );
02049             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
02050             cursor.setParag( parag );
02051             cursor.setIndex( parag->lastCharPos()+1 );
02052             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
02053             KCommand *cmd=txtObj->replaceSelectionCommand( &cursor, "", KoTextObject::HighlightSelection, QString::null );
02054 
02055             if(cmd)
02056             {
02057                 if ( index > i )
02058                     index = i;
02059                 if ( !macroCmd )
02060                     macroCmd = new KMacroCommand( i18n("Autocorrect (remove start and end line space)"));
02061                 macroCmd->addCommand(cmd);
02062             }
02063             break;
02064         }
02065     }
02066 
02067     // Cut away spaces at start of parag.
02068 
02069     for ( int i = 0 ; i <= parag->lastCharPos() ; i++ )
02070     {
02071         QChar ch = s->at( i ).c;
02072         if ( ch != ' ' )   // was: !ch.isSpace(), but this includes tabs, and this option is only about spaces
02073         {
02074             if( i == 0 )
02075                 break;
02076 
02077             cursor.setParag( parag );
02078             cursor.setIndex( 0 );
02079             textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
02080             cursor.setParag( parag );
02081             cursor.setIndex( i );
02082             textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
02083             KCommand *cmd=txtObj->replaceSelectionCommand( &cursor, "", KoTextObject::HighlightSelection, QString::null );
02084 
02085             if(cmd)
02086             {
02087                 index -= i; // adjust index
02088                 if ( !macroCmd )
02089                     macroCmd = new KMacroCommand( i18n("Autocorrect (remove start and end line space)"));
02090                 macroCmd->addCommand(cmd);
02091             }
02092             break;
02093         }
02094     }
02095 
02096     if( macroCmd )
02097     {
02098         txtObj->emitHideCursor();
02099         textEditCursor->setParag( parag->next() );
02100         //textEditCursor->cursorgotoRight();
02101         txtObj->emitShowCursor();
02102     }
02103     return macroCmd;
02104 }
02105 
02106 KCommand *KoAutoFormat::doCapitalizeNameOfDays( KoTextCursor* textEditCursor, KoTextParag *parag, int index, const QString & word , KoTextObject *txtObj )
02107 {
02108     //m_cacheNameOfDays
02109     //todo
02110     int pos = m_cacheNameOfDays.findIndex( word.lower() );
02111     if ( pos == -1 )
02112         return 0L;
02113     KoTextDocument * textdoc = parag->textDocument();
02114     QString replaceStr= m_cacheNameOfDays[pos];
02115     int start = index - replaceStr.length();
02116     int length = replaceStr.length();
02117     if( word.at(0).isLetter() && word.at(0)==word.at(0).lower() )
02118     {
02119         KoTextCursor cursor( parag->document() );
02120         cursor.setParag( parag );
02121         cursor.setIndex( start );
02122         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
02123         cursor.setIndex( start + length );
02124         QString replacement = replaceStr.at(0).upper() + replaceStr.right( length-1 );
02125         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
02126         QString cmdName=i18n("Capitalize Name of Days");
02127         KCommand *cmd =txtObj->replaceSelectionCommand( textEditCursor, replacement,
02128                                                            KoTextObject::HighlightSelection,
02129                                                                 cmdName );
02130         txtObj->emitHideCursor();
02131         textEditCursor->gotoRight();
02132         txtObj->emitShowCursor();
02133         return cmd;
02134     }
02135     return 0L;
02136 }
02137 
02138 KCommand *KoAutoFormat::doAutoSuperScript( KoTextCursor* textEditCursor, KoTextParag *parag, int index, const QString & word , KoTextObject *txtObj )
02139 {
02140     KoAutoFormatEntryMap::Iterator it = m_superScriptEntries.begin();
02141     bool found = false;
02142     QString replace;
02143     for ( ; it != m_superScriptEntries.end() ; ++it )
02144     {
02145         if( it.key()==word)
02146         {
02147             replace = it.data().replace();
02148             found = true;
02149             break;
02150         }
02151         else if ( it.key()=="othernb")
02152         {
02153             QString tmp = it.data().replace();
02154             int pos = word.find( tmp );
02155             if( pos != -1)
02156             {
02157                 if( pos + tmp.length() == word.length())
02158                 {
02159                     bool ok;
02160                     word.left( pos ).toInt( &ok);
02161                     if( ok )
02162                     {
02163                         replace = tmp;
02164                         found = true;
02165                         break;
02166                     }
02167                 }
02168             }
02169         }
02170     }
02171     if (found )
02172     {
02173         KoTextDocument * textdoc = parag->textDocument();
02174 
02175         int start = index - replace.length();
02176         KoTextFormat * lastFormat = parag->at( start )->format();
02177         KoTextFormat * newFormat = new KoTextFormat(*lastFormat);
02178         KoTextCursor cursor( parag->document() );
02179 
02180         cursor.setParag( parag );
02181         cursor.setIndex( start );
02182         textdoc->setSelectionStart( KoTextObject::HighlightSelection, &cursor );
02183         cursor.setIndex( start + word.length() -1 );
02184         textdoc->setSelectionEnd( KoTextObject::HighlightSelection, &cursor );
02185         newFormat->setVAlign(KoTextFormat::AlignSuperScript);
02186         KCommand *cmd =txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::VAlign , false,KoTextObject::HighlightSelection  );
02187         textdoc->removeSelection( KoTextObject::HighlightSelection );
02188 
02189         return cmd;
02190     }
02191     return 0L;
02192 }
02193 
02194 bool KoAutoFormat::doIgnoreDoubleSpace( KoTextParag *parag, int index, QChar ch )
02195 {
02196     if( m_ignoreDoubleSpace && ch==' ' && index >=  0 )
02197     {
02198         KoTextString *s = parag->string();
02199         QChar ch = s->at( index ).c;
02200         if ( ch==' ' )
02201             return true;
02202     }
02203     return false;
02204 }
02205 
02206 void KoAutoFormat::configTypographicSimpleQuotes( TypographicQuotes _tq )
02207 {
02208     m_typographicSimpleQuotes = _tq;
02209 }
02210 
02211 void KoAutoFormat::configTypographicDoubleQuotes( TypographicQuotes _tq )
02212 {
02213     m_typographicDoubleQuotes = _tq;
02214 }
02215 
02216 void KoAutoFormat::configUpperCase( bool _uc )
02217 {
02218     m_convertUpperCase = _uc;
02219 }
02220 
02221 void KoAutoFormat::configUpperUpper( bool _uu )
02222 {
02223     m_convertUpperUpper = _uu;
02224 }
02225 
02226 void KoAutoFormat::configAdvancedAutocorrect( bool _aa )
02227 {
02228     m_advancedAutoCorrect = _aa;
02229 }
02230 
02231 void KoAutoFormat::configAutoDetectUrl(bool _au)
02232 {
02233     m_autoDetectUrl=_au;
02234 }
02235 
02236 void KoAutoFormat::configIgnoreDoubleSpace( bool _ids)
02237 {
02238     m_ignoreDoubleSpace=_ids;
02239 }
02240 
02241 void KoAutoFormat::configRemoveSpaceBeginEndLine( bool _space)
02242 {
02243     m_removeSpaceBeginEndLine=_space;
02244 }
02245 
02246 void KoAutoFormat::configUseBulletStyle( bool _ubs)
02247 {
02248     m_useBulletStyle=_ubs;
02249 }
02250 
02251 void KoAutoFormat::configBulletStyle( QChar b )
02252 {
02253     m_bulletStyle = b;
02254 }
02255 
02256 void KoAutoFormat::configAutoChangeFormat( bool b)
02257 {
02258     m_autoChangeFormat = b;
02259 }
02260 
02261 
02262 void KoAutoFormat::configAutoReplaceNumber( bool b )
02263 {
02264     m_autoReplaceNumber = b;
02265 }
02266 
02267 void KoAutoFormat::configAutoNumberStyle( bool b )
02268 {
02269     m_useAutoNumberStyle = b;
02270 }
02271 
02272 void KoAutoFormat::configCompletion( bool b )
02273 {
02274     m_completion = b;
02275 }
02276 
02277 void KoAutoFormat::configToolTipCompletion( bool b )
02278 {
02279     m_toolTipCompletion = b;
02280     if (!b && m_completionBox)
02281     {
02282         delete m_completionBox;
02283         m_completionBox = 0;
02284     }
02285 }
02286 
02287 void KoAutoFormat::configKeyCompletionAction( KeyCompletionAction action )
02288 {
02289     m_keyCompletionAction = action;
02290 }
02291 
02292 void KoAutoFormat::configAppendSpace( bool b)
02293 {
02294     m_completionAppendSpace= b;
02295 }
02296 
02297 void KoAutoFormat::configMinWordLength( uint val )
02298 {
02299    m_minCompletionWordLength = val;
02300 }
02301 
02302 void KoAutoFormat::configNbMaxCompletionWord( uint val )
02303 {
02304     m_nbMaxCompletionWord = val;
02305 }
02306 
02307 
02308 void KoAutoFormat::configAddCompletionWord( bool b )
02309 {
02310     m_addCompletionWord= b;
02311 }
02312 
02313 bool KoAutoFormat::isUpper( const QChar &c )
02314 {
02315     return c.lower() != c;
02316 }
02317 
02318 bool KoAutoFormat::isLower( const QChar &c )
02319 {
02320     // Note that this is not the same as !isUpper !
02321     // For instance '1' is not lower nor upper,
02322     return c.upper() != c;
02323 }
02324 
02325 bool KoAutoFormat::isMark( const QChar &c )
02326 {
02327     return ( c == QChar( '.' ) ||
02328          c == QChar( '?' ) ||
02329          c == QChar( '!' ) );
02330 }
02331 
02332 bool KoAutoFormat::isSeparator( const QChar &c )
02333 {
02334     return ( !c.isLetter() && !c.isNumber() && !c.isDigit() );
02335 }
02336 
02337 void KoAutoFormat::buildMaxLen()
02338 {
02339     m_maxFindLength = 0;
02340     QDictIterator<KoAutoFormatEntry> it( m_entries );
02341     for( ; it.current(); ++it )
02342     {
02343     m_maxFindLength = QMAX( m_maxFindLength, it.currentKey().length() );
02344     }
02345     QDictIterator<KoAutoFormatEntry> it2( m_allLanguages );
02346     for( ; it2.current(); ++it2 )
02347     {
02348     m_maxFindLength = QMAX( m_maxFindLength, it2.currentKey().length() );
02349     }
02350 }
02351 
02352 QStringList KoAutoFormat::listCompletion() const
02353 {
02354    return m_listCompletion->items();
02355 }
02356 
02357 
02358 void KoAutoFormat::configIncludeTwoUpperUpperLetterException( bool b)
02359 {
02360     m_includeTwoUpperLetterException = b;
02361 }
02362 
02363 void KoAutoFormat::configIncludeAbbreviation( bool b )
02364 {
02365     m_includeAbbreviation = b;
02366 }
02367 
02368 void KoAutoFormat::configAutoSuperScript( bool b )
02369 {
02370     m_bAutoSuperScript = b;
02371 }
02372 
02373 void KoAutoFormat::configCorrectionWithFormat( bool b)
02374 {
02375     m_bAutoCorrectionWithFormat = b;
02376 }
02377 
02378 void KoAutoFormat::configCapitalizeNameOfDays( bool b)
02379 {
02380     m_bCapitalizeNameOfDays = b;
02381 }
02382 
02383 void KoAutoFormat::configAutoFormatLanguage( const QString &_lang)
02384 {
02385     m_autoFormatLanguage=_lang;
02386 }
02387 
02388 KCommand *KoAutoFormat::applyAutoFormat( KoTextObject * obj )
02389 {
02390   KoTextParag * parag = obj->textDocument()->firstParag();
02391   KoTextCursor *cursor = new KoTextCursor( obj->textDocument() );
02392   KMacroCommand *macro = 0L;
02393   while ( parag )
02394   {
02395     cursor->setIndex(0);
02396     for (int i=0;i<parag->length();i++)
02397     {
02398       cursor->gotoRight();
02399       //kdDebug() << "ch:" << parag->string()->at(i).c << endl;
02400       if (i == parag->length()-1)
02401     doAutoFormat(cursor,parag,i,'\n',obj);
02402       else
02403     doAutoFormat(cursor,parag,i, parag->string()->at(i).c,obj);
02404     }
02405     parag = parag->next();
02406 
02407   }
02408   delete cursor;
02409   return macro;
02410 }
02411 
02412 void KoAutoFormat::changeTextFormat(KoSearchContext *formatOptions, KoTextFormat * format, int & flags )
02413 {
02414     if (formatOptions )
02415     {
02416         if (formatOptions->m_optionsMask & KoSearchContext::Bold)
02417         {
02418             format->setBold( formatOptions->m_options & KoSearchContext::Bold);
02419             flags |=KoTextFormat::Bold;
02420         }
02421         if ( formatOptions->m_optionsMask & KoSearchContext::Size)
02422         {
02423             format->setPointSize( formatOptions->m_size );
02424             flags |=KoTextFormat::Size;
02425         }
02426         if ( formatOptions->m_optionsMask & KoSearchContext::Family)
02427         {
02428             format->setFamily( formatOptions->m_family );
02429             flags |=KoTextFormat::Family;
02430         }
02431         if ( formatOptions->m_optionsMask & KoSearchContext::Color)
02432         {
02433             format->setColor(formatOptions->m_color);
02434             flags |=KoTextFormat::Color;
02435         }
02436         if ( formatOptions->m_optionsMask & KoSearchContext::BgColor)
02437         {
02438             format->setTextBackgroundColor(formatOptions->m_backGroundColor);
02439             flags |=KoTextFormat::TextBackgroundColor;
02440         }
02441 
02442         if ( formatOptions->m_optionsMask & KoSearchContext::Italic)
02443         {
02444             format->setItalic( formatOptions->m_options & KoSearchContext::Italic);
02445             flags |=KoTextFormat::Italic;
02446         }
02447         if ( formatOptions->m_optionsMask & KoSearchContext::WordByWord)
02448         {
02449             format->setWordByWord( formatOptions->m_options & KoSearchContext::WordByWord );
02450             flags |=KoTextFormat::WordByWord;
02451         }
02452         if ( formatOptions->m_optionsMask & KoSearchContext::Shadow)
02453         {
02454             if ( formatOptions->m_options & KoSearchContext::Shadow )
02455                 format->setShadow( 1, 1, Qt::gray );
02456             else
02457                 format->setShadow( 0, 0, QColor() );
02458             flags |=KoTextFormat::ShadowText;
02459         }
02460 
02461         if ( formatOptions->m_optionsMask & KoSearchContext::Underline)
02462         {
02463             format->setUnderlineType(formatOptions->m_underline);
02464             flags |=KoTextFormat::ExtendUnderLine;
02465         }
02466         if ( formatOptions->m_optionsMask & KoSearchContext::StrikeOut)
02467         {
02468             format->setStrikeOutType(formatOptions->m_strikeOut);
02469             flags |= KoTextFormat::StrikeOut;
02470         }
02471         if ( formatOptions->m_optionsMask & KoSearchContext::VertAlign)
02472         {
02473             format->setVAlign(formatOptions->m_vertAlign);
02474             flags |=KoTextFormat::VAlign;
02475         }
02476         if ( formatOptions->m_optionsMask & KoSearchContext::Attribute)
02477         {
02478             format->setAttributeFont(formatOptions->m_attribute);
02479             flags |= KoTextFormat::Attribute;
02480         }
02481         if (formatOptions->m_optionsMask & KoSearchContext::Language)
02482         {
02483             flags |= KoTextFormat::Language;
02484             format->setLanguage( formatOptions->m_language );
02485         }
02486     }
02487 }
02488 
02489 #include "koAutoFormat.moc"
KDE Logo
This file is part of the documentation for lib Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:39:58 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003