F:/KPlato/koffice/libs/kotext/KoAutoFormat.cpp

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

Généré le Wed Nov 22 23:41:07 2006 pour KPlato par  doxygen 1.5.1-p1