lib Library API Documentation

koAutoFormat.cc

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