/* This file is part of the KDE project Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> 2001 Sven Leiber <s.leiber@web.de> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoAutoFormat.h" #include "KoTextObject.h" #include "KoTextParag.h" #include "KoVariable.h" #include "KoParagCounter.h" #include <KoDocument.h> #include <KoSearchDia.h> #include <KoGlobal.h> #include <kdeversion.h> #include <kdebug.h> #include <klocale.h> #include <kinstance.h> #include <kconfig.h> #include <kstandarddirs.h> #include <kglobal.h> #include <kcommand.h> //#include <KoTextFormat.h> #include <kcompletion.h> #include <kcalendarsystem.h> #include <tqfile.h> #include <tqlabel.h> #include <tqtooltip.h> #include <tqwhatsthis.h> #include <tqdom.h> #include <tqregexp.h> KoCompletionBox::KoCompletionBox( TQWidget * tqparent, const char * name, WFlags f) : TQLabel(tqparent,name,f) { setBackgroundColor(TQColor("#FFFFE6")); setFocusPolicy(TQ_NoFocus); setFrameShape(TQFrame::Box); } KoCompletionBox::~KoCompletionBox() { } void KoCompletionBox::mousePressEvent( TQMouseEvent *) { hide(); } TQString& KoCompletionBox::lastWord() { return m_lastWord; } void KoCompletionBox::setLastWord( TQString const &lastword) { m_lastWord = lastword; } KoAutoFormatEntry::KoAutoFormatEntry(const TQString& tqreplace) : m_tqreplace( tqreplace ) { m_formatOptions= 0L; } KoAutoFormatEntry::~KoAutoFormatEntry() { delete m_formatOptions; m_formatOptions=0L; } KoSearchContext *KoAutoFormatEntry::formatEntryContext() const { return m_formatOptions; } void KoAutoFormatEntry::createNewEntryContext() { if ( !m_formatOptions ) { m_formatOptions = new KoSearchContext(); } } void KoAutoFormatEntry::setFormatEntryContext( KoSearchContext *_cont ) { delete m_formatOptions; m_formatOptions=_cont; } void KoAutoFormatEntry::clearFormatEntryContext( ) { delete m_formatOptions; m_formatOptions = 0L; } /******************************************************************/ /* Class: KoAutoFormat */ /******************************************************************/ KoAutoFormat::KoAutoFormat( KoDocument *_doc, KoVariableCollection *_varCollection, KoVariableFormatCollection *_varFormatCollection ) : m_doc( _doc ), m_varCollection(_varCollection), m_varFormatCollection(_varFormatCollection), m_autoFormatLanguage( TQString()), m_configRead( false ), m_convertUpperCase( false ), m_convertUpperUpper( false ), m_advancedAutoCorrect( true ), m_autoDetectUrl( false ), m_ignoreDoubleSpace( false ), m_removeSpaceBeginEndLine( false ), m_useBulletStyle(false), m_autoChangeFormat(false), m_autoReplaceNumber(false), m_useAutoNumberStyle(false), m_completion(false), m_toolTipCompletion(false), m_completionAppendSpace(false), m_addCompletionWord(true), m_includeTwoUpperLetterException(false), m_includeAbbreviation(false), m_ignoreUpperCase(false), m_bAutoFormatActive(true), m_bAutoSuperScript( false ), m_bAutoCorrectionWithFormat( false ), m_bCapitalizeNameOfDays( false ), m_wordInserted( false ), m_bulletStyle(), m_typographicSimpleQuotes(), m_typographicDoubleQuotes(), m_typographicDefaultDoubleQuotes(), m_typographicDefaultSimpleQuotes(), m_listCompletion( new KCompletion ), m_entries(17,false), m_allLanguages(17,false), m_superScriptEntries(), m_upperCaseExceptions(), m_twoUpperLetterException(), m_maxFindLength( 0 ), m_minCompletionWordLength( 5 ), m_nbMaxCompletionWord( 500 ), m_countMaxWords(0), m_completionBox(0), m_keyCompletionAction( Enter ) { //load once this list not each time that we "readConfig" loadListOfWordCompletion(); m_listCompletion->setIgnoreCase( true ); updateMaxWords(); KLocale klocale(m_doc->instance()->instanceName()); for (int i = 1; i <=7; i++) { m_cacheNameOfDays.append(klocale.calendar()->weekDayName( i ).lower()); } } KoAutoFormat::KoAutoFormat( const KoAutoFormat& format ) : m_doc( format.m_doc ), m_varCollection( format.m_varCollection ), m_varFormatCollection( format.m_varFormatCollection ), m_autoFormatLanguage( format.m_autoFormatLanguage), m_configRead( format.m_configRead ), m_convertUpperCase( format.m_convertUpperCase ), m_convertUpperUpper( format.m_convertUpperUpper ), m_advancedAutoCorrect( format.m_advancedAutoCorrect ), m_autoDetectUrl( format.m_autoDetectUrl ), m_ignoreDoubleSpace( format.m_ignoreDoubleSpace ), m_removeSpaceBeginEndLine( format.m_removeSpaceBeginEndLine ), m_useBulletStyle( format.m_useBulletStyle ), m_autoChangeFormat( format.m_autoChangeFormat ), m_autoReplaceNumber( format.m_autoReplaceNumber ), m_useAutoNumberStyle( format.m_useAutoNumberStyle ), m_completion( format.m_completion ), m_toolTipCompletion( format.m_toolTipCompletion), m_completionAppendSpace( format.m_completionAppendSpace ), m_addCompletionWord( format.m_addCompletionWord ), m_includeTwoUpperLetterException( format.m_includeTwoUpperLetterException ), m_includeAbbreviation( format.m_includeAbbreviation ), m_ignoreUpperCase( format.m_ignoreUpperCase ), m_bAutoFormatActive( format.m_bAutoFormatActive ), m_bAutoSuperScript( format.m_bAutoSuperScript ), m_bAutoCorrectionWithFormat( format.m_bAutoCorrectionWithFormat), m_bCapitalizeNameOfDays( format.m_bCapitalizeNameOfDays), m_bulletStyle( format.m_bulletStyle ), m_typographicSimpleQuotes( format.m_typographicSimpleQuotes ), m_typographicDoubleQuotes( format.m_typographicDoubleQuotes ), m_typographicDefaultDoubleQuotes( format.m_typographicDefaultDoubleQuotes), m_typographicDefaultSimpleQuotes( format.m_typographicDefaultSimpleQuotes), m_listCompletion( 0L ), // don't copy it! m_entries(17,false ),//don't copy it. m_allLanguages(17,false), //don't copy it m_superScriptEntries ( format.m_superScriptEntries ), m_upperCaseExceptions( format.m_upperCaseExceptions ), m_twoUpperLetterException( format.m_twoUpperLetterException ), m_maxFindLength( format.m_maxFindLength ), m_minCompletionWordLength( format.m_minCompletionWordLength ), m_nbMaxCompletionWord( format.m_nbMaxCompletionWord ), m_cacheNameOfDays( format.m_cacheNameOfDays), m_completionBox(0), m_keyCompletionAction( format.m_keyCompletionAction ) { //m_listCompletion=new KCompletion(); //m_listCompletion->setItems( autoFormat.listCompletion() ); //copyAutoFormatEntries( autoFormat ); } KoAutoFormat::~KoAutoFormat() { delete m_listCompletion; m_entries.setAutoDelete( true ); m_entries.clear(); m_allLanguages.setAutoDelete( true ); m_allLanguages.clear(); } void KoAutoFormat::updateMaxWords() { TQStringList list = m_listCompletion->items(); for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) { TQString tmp = *it; uint maxword = 1; for (uint i=0; i < (uint)tmp.length(); i++) if ( tmp.at(i).isSpace() || tmp.at(i).isPunct() ) maxword++; if (maxword > m_countMaxWords ) m_countMaxWords = maxword; } kdDebug() << "m_countMaxWords: " << m_countMaxWords << endl; } void KoAutoFormat::loadListOfWordCompletion() { KConfig* config = KoGlobal::kofficeConfig(); KConfigGroupSaver cgs( config, "Completion Word" ); m_listCompletion->insertItems(config->readListEntry( "list" )); } void KoAutoFormat::readConfig(bool force) { // Read the autoformat configuration // This is done on demand (when typing the first char, or when opening the config dialog) // so that loading is faster and to avoid doing it for readonly documents. if ( m_configRead && !force ) return; KConfig* config = KoGlobal::kofficeConfig(); KConfigGroupSaver cgs( config, "AutoFormat" ); //when we force don't load format language. if ( !force) m_autoFormatLanguage = config->readEntry("formatLanguage", TQString()); m_convertUpperCase = config->readBoolEntry( "ConvertUpperCase", false ); m_convertUpperUpper = config->readBoolEntry( "ConvertUpperUpper", false ); m_includeTwoUpperLetterException = config->readBoolEntry( "includeTwoLetterException", false ); m_includeAbbreviation = config->readBoolEntry( "includeAbbreviation", false ); m_advancedAutoCorrect = config->readBoolEntry( "AdvancedAutocorrect", true ); m_bAutoCorrectionWithFormat = config->readBoolEntry( "AutoCorrectionWithFormat",false ); m_bCapitalizeNameOfDays = config->readBoolEntry( "CapitalizeNameOfDays",false ); m_autoDetectUrl = config->readBoolEntry("AutoDetectUrl",false); m_ignoreDoubleSpace = config->readBoolEntry("IgnoreDoubleSpace", true); m_removeSpaceBeginEndLine = config->readBoolEntry("RemoveSpaceBeginEndLine", true); m_useBulletStyle = config->readBoolEntry("UseBulletStyle",false); TQString tmp = config->readEntry( "BulletStyle", "" ); m_bulletStyle = tmp.isEmpty() ? TQChar() : tmp[0]; m_autoChangeFormat = config->readBoolEntry( "AutoChangeFormat", false ); m_autoReplaceNumber = config->readBoolEntry( "AutoReplaceNumber", true ); m_useAutoNumberStyle = config->readBoolEntry( "AutoNumberStyle", false ); TQString beginDoubleQuote = config->readEntry( "TypographicQuotesBegin" ); TQString endDoubleQuote = config->readEntry( "TypographicQuotesEnd" ); m_typographicDoubleQuotes.tqreplace = config->readBoolEntry( "TypographicQuotesEnabled", false ); TQString begin = config->readEntry( "TypographicSimpleQuotesBegin" ); TQString end = config->readEntry( "TypographicSimpleQuotesEnd" ); m_typographicSimpleQuotes.tqreplace = config->readBoolEntry( "TypographicSimpleQuotesEnabled", false ); m_bAutoSuperScript = config->readBoolEntry( "AutoSuperScript", true ); config->setGroup( "completion" ); m_completion = config->readBoolEntry( "completion", false ); m_completionAppendSpace = config->readBoolEntry( "CompletionAppendSpace", false ); m_minCompletionWordLength = config->readUnsignedNumEntry( "CompletionMinWordLength", 5 ); m_nbMaxCompletionWord = config->readUnsignedNumEntry( "NbMaxCompletionWord", 100 ); m_addCompletionWord = config->readBoolEntry( "AddCompletionWord", true ); m_toolTipCompletion = config->readBoolEntry( "ToolTipCompletion", true ); m_keyCompletionAction = ( KoAutoFormat::KeyCompletionAction )config->readUnsignedNumEntry( "CompletionKeyAction", 0 ); if ( force ) { m_entries.setAutoDelete(true); m_entries.clear(); m_entries.setAutoDelete(false); m_allLanguages.setAutoDelete(true); m_allLanguages.clear(); m_allLanguages.setAutoDelete(false); m_upperCaseExceptions.clear(); m_superScriptEntries.clear(); m_twoUpperLetterException.clear(); } //config->setGroup( "AutoFormatEntries" ); readAutoCorrectConfig(); if( beginDoubleQuote.isEmpty()) { if( m_typographicDefaultDoubleQuotes.begin.isNull()) m_typographicDoubleQuotes.begin = TQChar('�'); else m_typographicDoubleQuotes.begin = m_typographicDefaultDoubleQuotes.begin; } else m_typographicDoubleQuotes.begin = beginDoubleQuote[0]; if( endDoubleQuote.isEmpty() ) { if( m_typographicDefaultDoubleQuotes.end.isNull()) m_typographicDoubleQuotes.end = TQChar('�'); else m_typographicDoubleQuotes.end = m_typographicDefaultDoubleQuotes.end; } else m_typographicDoubleQuotes.end = endDoubleQuote[0]; m_typographicDoubleQuotes.tqreplace = m_typographicDoubleQuotes.tqreplace && !m_typographicDoubleQuotes.begin.isNull() && !m_typographicDoubleQuotes.end.isNull(); if( begin.isEmpty()) { if( m_typographicDefaultSimpleQuotes.begin.isNull()) m_typographicSimpleQuotes.begin = TQChar('\''); else m_typographicSimpleQuotes.begin = m_typographicDefaultSimpleQuotes.begin; } else m_typographicSimpleQuotes.begin = begin[0]; if( end.isEmpty() ) { if( m_typographicDefaultSimpleQuotes.end.isNull()) m_typographicSimpleQuotes.end = TQChar('\''); else m_typographicSimpleQuotes.end = m_typographicDefaultSimpleQuotes.end; } else m_typographicSimpleQuotes.end = end[0]; m_typographicSimpleQuotes.tqreplace = m_typographicSimpleQuotes.tqreplace && !m_typographicSimpleQuotes.end.isNull() && !m_typographicSimpleQuotes.begin.isNull(); loadAllLanguagesAutoCorrection(); buildMaxLen(); autoFormatIsActive(); m_configRead = true; } void KoAutoFormat::readAutoCorrectConfig() { Q_ASSERT( m_entries.isEmpty() ); // readConfig is only called once... KLocale klocale(m_doc->instance()->instanceName()); TQString kdelang = klocale.languageList().front(); kdelang.remove( TQRegExp( "@.*" ) ); kdDebug(32500) << "KoAutoFormat: m_autoFormatLanguage=" << m_autoFormatLanguage << " kdelang=" << kdelang << endl; TQString fname; if ( !m_autoFormatLanguage.isEmpty() ) { fname = locate( "data", "koffice/autocorrect/" + m_autoFormatLanguage + ".xml", m_doc->instance() ); } if ( m_autoFormatLanguage != "all_languages" ) { if ( fname.isEmpty() && !kdelang.isEmpty() ) fname = locate( "data", "koffice/autocorrect/" + kdelang + ".xml", m_doc->instance() ); if ( fname.isEmpty() && kdelang.tqcontains("_") ) { kdelang.remove( TQRegExp( "_.*" ) ); fname = locate( "data", "koffice/autocorrect/" + kdelang + ".xml", m_doc->instance() ); } if ( fname.isEmpty() ) fname = locate( "data", "koffice/autocorrect/autocorrect.xml", m_doc->instance() ); } if ( fname.isEmpty() ) return; TQFile xmlFile(fname); if(!xmlFile.open(IO_ReadOnly)) return; TQDomDocument doc; if(!doc.setContent(&xmlFile)) return; if(doc.doctype().name() != "autocorrection") { //return; } TQDomElement de=doc.documentElement(); loadAutoCorrection( de ); TQDomElement upper = de.namedItem( "UpperCaseExceptions" ).toElement(); if(!upper.isNull()) { TQDomNodeList nl = upper.childNodes(); for(uint i = 0; i < nl.count(); i++) { m_upperCaseExceptions+= nl.item(i).toElement().attribute("exception"); } } TQDomElement twoUpper = de.namedItem( "TwoUpperLetterExceptions" ).toElement(); if(!twoUpper.isNull()) { TQDomNodeList nl = twoUpper.childNodes(); for(uint i = 0; i < nl.count(); i++) { m_twoUpperLetterException+= nl.item(i).toElement().attribute("exception"); } } TQDomElement superScript = de.namedItem( "SuperScript" ).toElement(); if(!superScript.isNull()) { TQDomNodeList nl = superScript.childNodes(); for(uint i = 0; i < nl.count() ; i++) { //bug in qmap we overwrite = false doesn't work //so we can't add multiple "othernb" m_superScriptEntries.insert( nl.item(i).toElement().attribute("tqfind"), KoAutoFormatEntry(nl.item(i).toElement().attribute("super")),FALSE ); } } TQDomElement doubleQuote = de.namedItem( "DoubleQuote" ).toElement(); if(!doubleQuote.isNull()) { TQDomElement childItem = doubleQuote.namedItem("doublequote").toElement(); if ( !childItem.isNull() ) { TQString attr = childItem.attribute( "begin" ); if ( !attr.isEmpty() && attr[0] != 0 ) m_typographicDefaultDoubleQuotes.begin = attr[0]; attr = childItem.attribute( "end" ); if ( !attr.isEmpty() && attr[0] != 0 ) m_typographicDefaultDoubleQuotes.end = attr[0]; } } TQDomElement simpleQuote = de.namedItem( "SimpleQuote" ).toElement(); if(!simpleQuote.isNull()) { TQDomElement childItem = simpleQuote.namedItem("simplequote").toElement(); if ( !childItem.isNull() ) { TQString attr = childItem.attribute( "begin" ); if ( !attr.isEmpty() && attr[0] != 0 ) m_typographicDefaultSimpleQuotes.begin = attr[0]; attr = childItem.attribute( "end" ); if ( !attr.isEmpty() && attr[0] != 0 ) m_typographicDefaultSimpleQuotes.end = attr[0]; } } } void KoAutoFormat::loadAllLanguagesAutoCorrection() { TQString fname = locate( "data", "koffice/autocorrect/all_languages.xml", m_doc->instance() ); if ( fname.isEmpty() ) return; TQFile xmlFile( fname ); if(xmlFile.open(IO_ReadOnly)) { TQDomDocument doc; if(!doc.setContent(&xmlFile)) { return; } if(doc.doctype().name() != "autocorrection") { //return; } TQDomElement de=doc.documentElement(); loadAutoCorrection( de, true ); xmlFile.close(); } } void KoAutoFormat::loadAutoCorrection( const TQDomElement & _de, bool _allLanguages ) { TQDomElement item = _de.namedItem( "items" ).toElement(); if(!item.isNull()) { TQDomNodeList nl = item.childNodes(); m_maxFindLength=nl.count(); for(uint i = 0; i < m_maxFindLength; i++) { loadEntry( nl.item(i).toElement(), _allLanguages); } } } void KoAutoFormat::loadEntry( const TQDomElement &nl, bool _allLanguages) { KoAutoFormatEntry *tmp =new KoAutoFormatEntry(nl.attribute("tqreplace")); if ( nl.hasAttribute("FONT")) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_family=nl.attribute("FONT"); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Family; } if ( nl.hasAttribute("SIZE" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_size = nl.attribute("SIZE" ).toInt(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Size; } if (nl.hasAttribute("BOLD" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Bold; TQString value = nl.attribute("BOLD"); if ( value.toInt() == 1 ) tmp->formatEntryContext()->m_options |= KoSearchContext::Bold; } if (nl.hasAttribute("ITALIC" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Italic; TQString value = nl.attribute("ITALIC"); if ( value.toInt() == 1 ) tmp->formatEntryContext()->m_options |= KoSearchContext::Italic; } if (nl.hasAttribute("UNDERLINE" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Underline; TQString value = nl.attribute("UNDERLINE"); if ( value =="single" ) tmp->formatEntryContext()->m_underline = KoTextFormat::U_SIMPLE; else if ( value =="double" ) tmp->formatEntryContext()->m_underline = KoTextFormat::U_DOUBLE; else if ( value =="single-bold" ) tmp->formatEntryContext()->m_underline = KoTextFormat::U_SIMPLE_BOLD; else tmp->formatEntryContext()->m_underline = KoTextFormat::U_NONE; } if (nl.hasAttribute("STRIKEOUT" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::StrikeOut; TQString value = nl.attribute("STRIKEOUT"); if ( value =="single" ) tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_SIMPLE; else if ( value =="double" ) tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_DOUBLE; else if ( value =="single-bold" ) tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_SIMPLE_BOLD; else tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_NONE; } if (nl.hasAttribute("VERTALIGN" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::VertAlign; TQString value = nl.attribute("VERTALIGN"); tmp->formatEntryContext()->m_vertAlign=static_cast<KoTextFormat::VerticalAlignment>( value.toInt() ); } if ( nl.hasAttribute("TEXTCOLOR" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Color; TQColor col( nl.attribute("TEXTCOLOR" )); tmp->formatEntryContext()->m_color = col; } if ( nl.hasAttribute("TEXTBGCOLOR" )) { tmp->createNewEntryContext(); tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::BgColor; TQColor col( nl.attribute("TEXTBGCOLOR" )); tmp->formatEntryContext()->m_backGroundColor = col; } if ( !_allLanguages ) m_entries.insert( nl.attribute("tqfind"), tmp ); else m_allLanguages.insert( nl.attribute("tqfind"), tmp ); } void KoAutoFormat::saveConfig() { KConfig* config = KoGlobal::kofficeConfig(); KLocale klocale(m_doc->instance()->instanceName()); KConfigGroupSaver cgs( config, "AutoFormat" ); config->writeEntry( "ConvertUpperCase", m_convertUpperCase ); config->writeEntry( "formatLanguage", m_autoFormatLanguage=="all_languages" ? klocale.languageList().front() : m_autoFormatLanguage); config->writeEntry( "ConvertUpperUpper", m_convertUpperUpper ); config->writeEntry( "includeTwoLetterException", m_includeTwoUpperLetterException ); config->writeEntry( "includeAbbreviation", m_includeAbbreviation ); config->writeEntry( "TypographicQuotesBegin", TQString( m_typographicDoubleQuotes.begin ) ); config->writeEntry( "TypographicQuotesEnd", TQString( m_typographicDoubleQuotes.end ) ); config->writeEntry( "TypographicQuotesEnabled", m_typographicDoubleQuotes.tqreplace ); config->writeEntry( "TypographicSimpleQuotesBegin", TQString( m_typographicSimpleQuotes.begin ) ); config->writeEntry( "TypographicSimpleQuotesEnd", TQString( m_typographicSimpleQuotes.end ) ); config->writeEntry( "TypographicSimpleQuotesEnabled", m_typographicSimpleQuotes.tqreplace ); config->writeEntry( "AdvancedAutocorrect", m_advancedAutoCorrect ); config->writeEntry( "AutoCorrectionWithFormat", m_bAutoCorrectionWithFormat ); config->writeEntry( "CapitalizeNameOfDays", m_bCapitalizeNameOfDays ); config->writeEntry( "AutoDetectUrl",m_autoDetectUrl); config->writeEntry( "IgnoreDoubleSpace",m_ignoreDoubleSpace ); config->writeEntry( "RemoveSpaceBeginEndLine",m_removeSpaceBeginEndLine ); config->writeEntry( "UseBulletStyle", m_useBulletStyle); config->writeEntry( "BulletStyle", TQString(m_bulletStyle)); config->writeEntry( "AutoChangeFormat", m_autoChangeFormat); config->writeEntry( "AutoReplaceNumber", m_autoReplaceNumber); config->writeEntry( "AutoNumberStyle", m_useAutoNumberStyle ); config->writeEntry( "AutoSuperScript", m_bAutoSuperScript ); config->setGroup( "completion" ); config->writeEntry( "completion", m_completion ); config->writeEntry( "CompletionAppendSpace", m_completionAppendSpace ); config->writeEntry( "CompletionMinWordLength", m_minCompletionWordLength); config->writeEntry( "NbMaxCompletionWord", m_nbMaxCompletionWord); config->writeEntry( "AddCompletionWord", m_addCompletionWord ); config->writeEntry( "ToolTipCompletion", m_toolTipCompletion ); config->writeEntry( "CompletionKeyAction", ( int )m_keyCompletionAction ); config->setGroup( "AutoFormatEntries" ); TQDictIterator<KoAutoFormatEntry> it( m_entries ); //refresh m_maxFindLength m_maxFindLength=0; TQDomDocument doc("autocorrection"); TQDomElement begin = doc.createElement( "Word" ); doc.appendChild( begin ); TQDomElement items; items = doc.createElement("items"); TQDomElement data; for ( ; it.current() ; ++it ) { items.appendChild(saveEntry( it, doc)); //m_maxFindLength=TQMAX(m_maxFindLength,it.currentKey().length()); } buildMaxLen(); begin.appendChild(items); TQDomElement upper; upper = doc.createElement("UpperCaseExceptions"); for ( TQStringList::Iterator it = m_upperCaseExceptions.begin(); it != m_upperCaseExceptions.end();++it ) { data = doc.createElement("word"); data.setAttribute("exception",(*it) ); upper.appendChild(data); } begin.appendChild(upper); TQDomElement twoUpper; twoUpper = doc.createElement("TwoUpperLetterExceptions"); for ( TQStringList::Iterator it = m_twoUpperLetterException.begin(); it != m_twoUpperLetterException.end();++it ) { data = doc.createElement("word"); data.setAttribute("exception",(*it) ); twoUpper.appendChild(data); } begin.appendChild(twoUpper); TQDomElement super; super = doc.createElement("SuperScript"); KoAutoFormatEntryMap::Iterator it2 = m_superScriptEntries.begin(); for ( ; it2 != m_superScriptEntries.end() ; ++it2 ) { data = doc.createElement("superscript"); data.setAttribute("tqfind", it2.key()); data.setAttribute("super", it2.data().tqreplace()); super.appendChild(data); } begin.appendChild(super); TQDomElement doubleQuote; doubleQuote = doc.createElement("DoubleQuote"); data = doc.createElement("doublequote"); data.setAttribute("begin", TQString(m_typographicDefaultDoubleQuotes.begin)); data.setAttribute("end", TQString(m_typographicDefaultDoubleQuotes.end)); doubleQuote.appendChild(data); begin.appendChild(doubleQuote); TQDomElement simpleQuote; simpleQuote = doc.createElement("SimpleQuote"); data = doc.createElement("simplequote"); data.setAttribute("begin", TQString(m_typographicDefaultSimpleQuotes.begin)); data.setAttribute("end", TQString(m_typographicDefaultSimpleQuotes.end)); simpleQuote.appendChild(data); begin.appendChild(simpleQuote); TQFile f; if ( m_autoFormatLanguage.isEmpty()) f.setName(locateLocal("data", "koffice/autocorrect/"+klocale.languageList().front() + ".xml",m_doc->instance())); else f.setName(locateLocal("data", "koffice/autocorrect/"+m_autoFormatLanguage + ".xml",m_doc->instance())); if(!f.open(IO_WriteOnly)) { kdWarning()<<"Error during saving autoformat to " << f.name() << endl; return; } TQTextStream ts(&f); doc.save(ts, 2); f.close(); autoFormatIsActive(); config->sync(); } TQDomElement KoAutoFormat::saveEntry( TQDictIterator<KoAutoFormatEntry> _entry, TQDomDocument doc) { TQDomElement data; data = doc.createElement("item"); data.setAttribute("tqfind", _entry.currentKey()); data.setAttribute("tqreplace", _entry.current()->tqreplace()); if ( _entry.current()->formatEntryContext() ) { KoSearchContext *tmp = _entry.current()->formatEntryContext(); if ( tmp->m_optionsMask & KoSearchContext::Family ) { data.setAttribute("FONT", tmp->m_family); } if ( tmp->m_optionsMask & KoSearchContext::Size ) { data.setAttribute("SIZE", tmp->m_size); } if ( tmp->m_optionsMask & KoSearchContext::Italic ) { data.setAttribute("ITALIC", static_cast<bool>(tmp->m_options & KoSearchContext::Italic)); } if ( tmp->m_optionsMask & KoSearchContext::Bold ) { data.setAttribute("BOLD", static_cast<bool>(tmp->m_options & KoSearchContext::Bold)); } if ( tmp->m_optionsMask & KoSearchContext::Shadow ) { data.setAttribute("SHADOWTEXT", static_cast<bool>(tmp->m_options & KoSearchContext::Shadow)); } if ( tmp->m_optionsMask & KoSearchContext::WordByWord ) { data.setAttribute("WORDBYWORD", static_cast<bool>(tmp->m_options & KoSearchContext::WordByWord)); } if ( tmp->m_optionsMask & KoSearchContext::Underline ) { switch( tmp->m_underline ) { case KoTextFormat::U_SIMPLE: data.setAttribute("UNDERLINE", "single"); break; case KoTextFormat::U_DOUBLE: data.setAttribute("UNDERLINE", "double"); break; case KoTextFormat::U_SIMPLE_BOLD: data.setAttribute("UNDERLINE", "single-bold"); break; case KoTextFormat::U_WAVE: data.setAttribute("UNDERLINE", "wave"); break; case KoTextFormat::U_NONE: data.setAttribute("UNDERLINE", "none"); break; } } if ( tmp->m_optionsMask & KoSearchContext::StrikeOut ) { switch( tmp->m_strikeOut ) { case KoTextFormat::S_SIMPLE: data.setAttribute("STRIKEOUT", "single"); break; case KoTextFormat::S_DOUBLE: data.setAttribute("STRIKEOUT", "double"); break; case KoTextFormat::S_NONE: data.setAttribute("STRIKEOUT", "none"); break; case KoTextFormat::S_SIMPLE_BOLD: data.setAttribute("STRIKEOUT", "single-bold"); break; } } if ( tmp->m_optionsMask & KoSearchContext::Attribute ) { data.setAttribute("FONTATTRIBUTE", KoTextFormat::attributeFontToString( tmp->m_attribute ) ); } if ( tmp->m_optionsMask & KoSearchContext::VertAlign) { data.setAttribute( "VERTALIGN", static_cast<int>(tmp->m_vertAlign) ); } if ( tmp->m_optionsMask & KoSearchContext::BgColor ) { data.setAttribute( "TEXTCOLOR", tmp->m_color.name()); } if ( tmp->m_optionsMask & KoSearchContext::Color ) { data.setAttribute( "TEXTCOLOR", tmp->m_color.name()); } if ( tmp->m_optionsMask & KoSearchContext::BgColor ) { data.setAttribute( "TEXTBGCOLOR", tmp->m_backGroundColor.name()); } if ( tmp->m_optionsMask & KoSearchContext::Language ) data.setAttribute( "LANGUAGE", tmp->m_language ); } return data; } void KoAutoFormat::addAutoFormatEntry( const TQString &key, const TQString &tqreplace ) { KoAutoFormatEntry *findEntry = m_entries.tqfind( key); if ( findEntry ) { if ( findEntry->tqreplace().lower() == tqreplace.lower() ) return; } KoAutoFormatEntry *tmp = new KoAutoFormatEntry( tqreplace ); m_entries.insert( key, tmp ); saveConfig(); buildMaxLen(); } TQString KoAutoFormat::getLastWord(KoTextParag *parag, int const index) { TQString lastWord; KoTextString *s = parag->string(); for ( int i = index - 1; i >= 0; --i ) { TQChar ch = s->at( i ).c; if ( ch.isSpace() || ch.isPunct() ) break; lastWord.prepend( ch ); } return lastWord; } TQString KoAutoFormat::getLastWord(const int max_words, KoTextParag *parag, int const index) { TQString lastWord; KoTextString const *s = parag->string(); int words = 0; for ( int i = index - 1; i >= 0; --i ) { TQChar ch = s->at( i ).c; if ( ch.isSpace() || ch.isPunct() ) { ++words; if (words >= max_words) break; } lastWord.prepend( ch ); } return lastWord; } TQString KoAutoFormat::getWordAfterSpace(KoTextParag *parag, int const index) { TQString word; KoTextString *s = parag->string(); for ( int i = index - 1; i >= 0; --i ) { TQChar ch = s->at( i ).c; if ( ch.isSpace() ) break; word.prepend( ch ); } return word; } bool KoAutoFormat::doCompletion( KoTextCursor* textEditCursor, KoTextParag *parag, int const index, KoTextObject *txtObj ) { if( m_completion ) { bool part=false; TQString lastWord, word; if (m_completionBox && m_completionBox->isShown() ) //word completion with the tool-tip box { word = m_completionBox->text(); lastWord = m_completionBox->lastWord(); } else { TQStringList wordlist, new_wordlist; for (uint i=1; i <= m_countMaxWords; i++ ) { lastWord = getLastWord(i, parag, index+1); wordlist += m_listCompletion->substringCompletion( lastWord ); //find all completion words that contains lastWord } uint maxlength = 0; for ( TQStringList::ConstIterator it = wordlist.begin(); it != wordlist.end(); ++it ) // several completion words were found { if ( (*it).tqstartsWith( lastWord, false ) && new_wordlist.tqfind(*it) == new_wordlist.end() ) //the completion words that begin with lastWord { if ( (*it).length() > maxlength ) maxlength = (*it).length(); new_wordlist.append(*it); //kdDebug() << "adding word completion:" << *it << endl; } } if ( new_wordlist.isEmpty() ) return false; if ( new_wordlist.count() == 1 ) // only one completion word was found word = new_wordlist.first(); else { //we must extract the common part of the completions for (uint i = lastWord.length(); i<maxlength && !part; i++) //iterate through all completion words { TQChar ch = new_wordlist.first().at(i); for (TQStringList::ConstIterator it = new_wordlist.begin(); it != new_wordlist.end(); ++it ) { if ( (*it).tqat(i).lower() != ch.lower() ) { word = (*it).left(i); //the completion word is truncated here //kdDebug() << "set the word completion to:" << word << endl; part=true; // completion of a part of a word; a space-character after the completion should not be inserted break; } } } } if (word == lastWord) return false; word=lastWord+word.right(word.length()-lastWord.length() ); } if( !word.isEmpty() ) { int const lastword_length = lastWord.length(); int const start = index+1 - lastword_length; int const length = word.length(); KMacroCommand *macro = new KMacroCommand( i18n("Completion Word")); KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); KoTextDocument * textdoc = parag->textDocument(); if( m_completionAppendSpace && !part) word+=" "; textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + lastword_length ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); macro->addCommand( txtObj->replaceSelectionCommand( textEditCursor, word, i18n("Completion Word"), KoTextDocument::HighlightSelection )); if ( m_completionAppendSpace && !m_ignoreUpperCase && (m_convertUpperUpper || m_convertUpperCase) && !part) { //find the first word for (uint i=1; i < word.length(); i++) if ( word.at(i).isSpace() || word.at(i).isPunct() ) { word.truncate(i); break; } int const newPos = start + word.length();// + index - 3; KCommand *cmd = doUpperCase( textEditCursor, parag, newPos, word, txtObj ); if( cmd ) macro->addCommand( cmd ); txtObj->emitHideCursor(); textEditCursor->setIndex(start+ length+1); } else { txtObj->emitHideCursor(); textEditCursor->setIndex(start+ length); } txtObj->emitNewCommand( macro ); // The space/tab/CR that we inserted is still there but delete/insert moved the cursor // -> go right txtObj->emitShowCursor(); removeToolTipCompletion(); return true; } } return false; } bool KoAutoFormat::doToolTipCompletion( KoTextCursor* textEditCursor, KoTextParag *parag, int index, KoTextObject *txtObj, int keyPressed ) { if( m_completion && m_toolTipCompletion && m_completionBox && m_completionBox->isShown() ) { if ( ( keyPressed == TQt::Key_Return && m_keyCompletionAction==Enter ) || ( keyPressed == TQt::Key_Enter && m_keyCompletionAction==Enter ) || ( keyPressed == TQt::Key_Tab && m_keyCompletionAction==Tab ) || ( keyPressed == TQt::Key_Space && m_keyCompletionAction==Space ) || ( keyPressed == TQt::Key_End && m_keyCompletionAction==End ) || ( keyPressed == TQt::Key_Right && m_keyCompletionAction==Right )) { return doCompletion(textEditCursor, parag, index, txtObj); } } return false; } void KoAutoFormat::showToolTipBox(KoTextParag *parag, int index, TQWidget *widget, const TQPoint &pos ) { if( m_completion && m_toolTipCompletion) { TQString lastWord, word; for (uint i=1; i <= m_countMaxWords; i++ ) { lastWord = getLastWord(i, parag, index+1); word=m_listCompletion->makeCompletion( lastWord ); if ( !word.isEmpty()) break; } if( !word.isEmpty() && word!=lastWord ) { uint const length = lastWord.length(); if (length<=3) return; word=lastWord+word.right(word.length()-length); if (!m_completionBox) m_completionBox = new KoCompletionBox(0,0,TQt::WType_Popup); TQPoint const show_pos = widget->mapToGlobal(pos); m_completionBox->setText(word); m_completionBox->setLastWord(lastWord); m_completionBox->adjustSize(); int const height = m_completionBox->tqsizeHint().height(); m_completionBox->move( show_pos.x(), show_pos.y() - height ); if (!m_completionBox->isShown() ) { m_completionBox->show(); widget->setFocus(); } } else removeToolTipCompletion(); } } void KoAutoFormat::removeToolTipCompletion() { if (m_completion && m_toolTipCompletion && m_completionBox && m_completionBox->isShown()) m_completionBox->hide(); } void KoAutoFormat::autoFormatIsActive() { m_bAutoFormatActive = m_useBulletStyle || m_removeSpaceBeginEndLine || m_autoDetectUrl || m_convertUpperUpper || m_convertUpperCase || m_autoReplaceNumber || m_autoChangeFormat || m_completion || m_typographicDoubleQuotes.tqreplace || m_typographicSimpleQuotes.tqreplace || m_entries.count()!=0 || m_allLanguages.count()!=0; } void KoAutoFormat::doAutoFormat( KoTextCursor* textEditCursor, KoTextParag *parag, int index, TQChar ch,KoTextObject *txtObj ) { m_ignoreUpperCase = false; if ( !m_configRead ) readConfig(); if ( !m_bAutoFormatActive ) return; if( ch.isSpace()) { //a link doesn't have a space //=>m_ignoreUpperCase = false //m_ignoreUpperCase=false; TQString word=getWordAfterSpace(parag,index); if ( m_autoChangeFormat && index > 3) { KCommand *cmd =doAutoChangeFormat( textEditCursor, parag, index, word, txtObj ); if ( cmd ) txtObj->emitNewCommand( cmd ); } if ( m_autoReplaceNumber ) { KCommand *cmd = doAutoReplaceNumber( textEditCursor, parag, index, word, txtObj ); if ( cmd ) txtObj->emitNewCommand( cmd ); } } if( ch =='\n' ) { if( m_removeSpaceBeginEndLine && index > 1) { KCommand *cmd = doRemoveSpaceBeginEndLine( textEditCursor, parag, txtObj, index ); if ( cmd ) txtObj->emitNewCommand( cmd ); } if( m_useBulletStyle && index > 3) { KCommand *cmd =doUseBulletStyle( textEditCursor, parag, txtObj, index ); if ( cmd ) txtObj->emitNewCommand( cmd ); } if( m_useAutoNumberStyle && index > 3 ) { KCommand *cmd =doUseNumberStyle( textEditCursor, parag, txtObj, index ); if ( cmd ) txtObj->emitNewCommand( cmd ); } if( m_convertUpperUpper && m_includeTwoUpperLetterException ) doAutoIncludeUpperUpper(textEditCursor, parag, txtObj ); if( m_convertUpperCase && m_includeAbbreviation ) doAutoIncludeAbbreviation(textEditCursor, parag, txtObj ); } //kdDebug(32500) << "KoAutoFormat::doAutoFormat ch=" << TQString(ch) << endl; //if ( !m_enabled ) // return; // Auto-correction happens when pressing space, tab, CR, punct etc. if ( (ch.isSpace() || ch==':' || ch=='?' || ch=='!' || ch==',' || (m_advancedAutoCorrect && ch=='.') ) && index > 0 ) { KCommand *cmd = 0L; KMacroCommand *macro = 0L; TQString lastWord = getWordAfterSpace(parag, index); //kdDebug(32500) << "KoAutoFormat::doAutoFormat lastWord=" << lastWord << endl; if ( ch == '.') detectStartOfLink( parag, index, true ); else detectStartOfLink( parag, index, false ); if ( !m_wordInserted && m_advancedAutoCorrect && !m_ignoreUpperCase) { int const completionBeginPos = index -lastWord.length(); int newPos = index; cmd = doAutoCorrect( textEditCursor, parag, newPos, txtObj ); if( cmd ) { if (!macro) macro = new KMacroCommand(i18n("Autocorrection")); macro->addCommand( cmd ); } int const endPos=textEditCursor->index(); bool was_a_replacement; if (index == newPos) was_a_replacement = false; else was_a_replacement = true; if( was_a_replacement) // a replacement took place { txtObj->emitHideCursor(); if(endPos==0) //new line, the user pressed enter { textEditCursor->gotoUp(); textEditCursor->gotoLineEnd(); newPos=textEditCursor->index(); } else newPos= endPos-1; m_wordInserted = true; //don't allow other replacements in this replacement for(int i=completionBeginPos; i<newPos;i++) { textEditCursor->setIndex(i); doAutoFormat( textEditCursor, parag, i, parag->toString().at(i),txtObj ); } textEditCursor->setIndex(newPos); doAutoFormat( textEditCursor, parag, newPos, ch,txtObj ); m_wordInserted = false; if (endPos==0) { textEditCursor->gotoLineStart(); textEditCursor->gotoDown(); } else textEditCursor->setIndex(newPos+1); txtObj->emitShowCursor(); return; } } if (!m_ignoreUpperCase && m_bCapitalizeNameOfDays) { KCommand *cmd = doCapitalizeNameOfDays( textEditCursor, parag, index, lastWord, txtObj ); if( cmd ) { if (!macro) macro = new KMacroCommand(i18n("Autocorrection")); macro->addCommand( cmd ); m_ignoreUpperCase = true; } } if (ch=='.') return; //kdDebug(32500)<<" m_listCompletion->items() :"<<m_listCompletion->items()<<endl; if( !m_ignoreUpperCase && m_completion && m_addCompletionWord && m_listCompletion->items().count() < m_nbMaxCompletionWord ) { TQString completionWord(""); TQChar ch; for (uint i=0;i<lastWord.length();i++) { ch = lastWord.at(i); if (ch.isPunct() && ch!='-' && ch!='=' ) { if (completionWord.at(0) == '-') completionWord.remove(0,1); if (completionWord.length()>= m_minCompletionWordLength && !completionWord.isEmpty() && m_listCompletion->makeCompletion(completionWord).isEmpty()) { kdDebug() << "Adding:" << completionWord << endl; m_listCompletion->addItem( completionWord ); if ( completionWord.length() > m_countMaxWords ) m_countMaxWords = completionWord.length(); } completionWord = ""; } else { completionWord.append(ch); if (i==lastWord.length()-1) { if (completionWord.at(0) == '-') completionWord.remove(0,1); if (completionWord.at(completionWord.length()-1) == '-') completionWord.truncate(completionWord.length()-1); completionWord.remove('='); if (completionWord.length()>= m_minCompletionWordLength && !completionWord.isEmpty() && m_listCompletion->makeCompletion(completionWord).isEmpty()) { kdDebug() << "Adding:" << completionWord << endl; m_listCompletion->addItem( completionWord ); if ( completionWord.length() > m_countMaxWords ) m_countMaxWords = completionWord.length(); } } } } } if( m_autoDetectUrl && m_ignoreUpperCase && (ch!='?' || lastWord.at(lastWord.length()-1)=='?') ) { doAutoDetectUrl( textEditCursor, parag, index, lastWord, txtObj ); //textEditCursor->gotoRight(); } if (!m_ignoreUpperCase && (m_convertUpperUpper || m_convertUpperCase) ) { cmd = doUpperCase( textEditCursor, parag, index, lastWord, txtObj ); if( cmd ) { if (!macro) macro = new KMacroCommand(i18n("Autocorrection")); macro->addCommand( cmd ); } } if ( macro ) txtObj->emitNewCommand( macro ); if(!m_ignoreUpperCase && m_bAutoSuperScript && m_superScriptEntries.count()>0) { if( lastWord.at(0).isPunct() ) lastWord.remove(0,1); KCommand * cmd = doAutoSuperScript( textEditCursor, parag, index, lastWord, txtObj ); if ( cmd ) txtObj->emitNewCommand( cmd ); } } else { if ( ch == '"' && m_typographicDoubleQuotes.tqreplace ) { KCommand *cmd = doTypographicQuotes( textEditCursor, parag, index, txtObj, true /*double quote*/ ); if ( cmd ) txtObj->emitNewCommand( cmd ); } else if ( ch == '\'' && m_typographicDoubleQuotes.tqreplace ) { KCommand *cmd = doTypographicQuotes( textEditCursor, parag, index, txtObj, false /* simple quote*/ ); if ( cmd ) txtObj->emitNewCommand( cmd ); } } } KCommand *KoAutoFormat::doAutoCorrect( KoTextCursor* textEditCursor, KoTextParag *parag, int &index, KoTextObject *txtObj ) { //if(!m_advancedAutoCorrect) // return 0L; // Prepare an array with words of different lengths, all terminating at "index". // Obviously only full words are put into the array // But this allows 'find strings' with spaces and punctuation in them. TQString * wordArray = new TQString[m_maxFindLength+1]; { TQString word; KoTextString *s = parag->string(); for ( int i = index - 1; i >= 0; --i ) { TQChar ch = s->at( i ).c; // It's necessary to stop at spaces - #99063 if ( ch.isSpace() /*|| ch.isPunct()*/ || i==0) { if(i==0 && word.length()<m_maxFindLength) word.prepend( ch ); wordArray[word.length()]=word; } word.prepend( ch ); if (((index - 1)-i) == (int)m_maxFindLength) break; } } KCommand *cmd = autoFormatWord( textEditCursor, parag, index, txtObj, wordArray, false ); if ( !cmd ) cmd = autoFormatWord( textEditCursor, parag, index, txtObj, wordArray, true ); delete [] wordArray; return cmd; } KCommand *KoAutoFormat::autoFormatWord( KoTextCursor* textEditCursor, KoTextParag *parag, int &index, KoTextObject *txtObj, TQString * _wordArray, bool _allLanguages ) { KoTextDocument * textdoc = parag->textDocument(); // Now for each entry in the autocorrect list, look if // the word of the same size in wordArray matches. // This allows an o(n) behaviour instead of an o(n^2). for(int i=m_maxFindLength;i>0;--i) { if ( !_wordArray[i].isEmpty()) { KoAutoFormatEntry* it = 0L; if ( _allLanguages ) it = m_allLanguages[ _wordArray[i] ]; else it = m_entries[ _wordArray[i] ]; if ( _wordArray[i]!=0 && it ) { unsigned int length = _wordArray[i].length(); int const start = index - length; KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + length ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KCommand *cmd = 0L; kdDebug()<<"it->tqreplace() :"<<it->tqreplace()<<endl; if (!it->formatEntryContext() || !m_bAutoCorrectionWithFormat) { cmd = txtObj->replaceSelectionCommand( textEditCursor, it->tqreplace(), i18n("Autocorrect Word"), KoTextDocument::HighlightSelection ); } else { int flags = 0; KoTextFormat * lastFormat = parag->at( start )->format(); KoTextFormat * newFormat = new KoTextFormat(*lastFormat); changeTextFormat(it->formatEntryContext(), newFormat, flags ); KMacroCommand *macro = new KMacroCommand( i18n("Autocorrect Word with Format")); KCommand *cmd2=txtObj->replaceSelectionCommand( textEditCursor, it->tqreplace(), i18n("Autocorrect Word"), KoTextDocument::HighlightSelection ); if ( cmd2 ) macro->addCommand(cmd2); KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + it->tqreplace().length()/*+ length + 1*/ ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); cmd2 =txtObj->setFormatCommand( textEditCursor, &lastFormat, newFormat, flags, false, KoTextDocument::HighlightSelection ); macro->addCommand( cmd2); index = index - length + it->tqreplace().length(); textEditCursor->setIndex(index+1); cmd2 =txtObj->setFormatCommand( textEditCursor, &newFormat, lastFormat, 0 ); macro->addCommand( cmd2); parag->at( index+1 )->setFormat(lastFormat); cmd = macro; txtObj->emitHideCursor(); textEditCursor->gotoRight(); txtObj->emitShowCursor(); return cmd; } // The space/tab/CR that we inserted is still there but delete/insert moved the cursor // -> go right txtObj->emitHideCursor(); textEditCursor->gotoRight(); txtObj->emitShowCursor(); index = index - length + it->tqreplace().length(); return cmd; } } } return 0L; } KCommand *KoAutoFormat::doTypographicQuotes( KoTextCursor* textEditCursor, KoTextParag *parag, int index, KoTextObject *txtObj, bool doubleQuotes ) { //kdDebug(32500) << "KoAutoFormat::doTypographicQuotes" << endl; KoTextDocument * textdoc = parag->textDocument(); KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( index ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( index + 1 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); // Need to determine if we want a starting or ending quote. // we use a starting quote in three cases: // 1. if the previous character is a space // 2. if the previous character is some kind of opening punctuation (e.g., "(", "[", or "{") // a. and the character before that is not an opening quote (so that we get quotations of single characters // right) // 3. if the previous character is an opening quote (so that we get nested quotations right) // a. and the character before that is not an opening quote (so that we get quotations of single characters // right) // b. and the previous quote of a different kind (so that we get empty quotations right) TQString replacement; bool ending = true; if( index > 0 ) { TQChar::Category c1 = parag->at( index - 1 )->c.category(); // case 1 and 2 if ( c1 == TQChar::Separator_Space || c1 == TQChar::Separator_Line || c1 == TQChar::Separator_Paragraph || c1 == TQChar::Punctuation_Open || c1 == TQChar::Other_Control ) ending = false; // case 3 if ( c1 == TQChar::Punctuation_InitialQuote ) { TQChar openingQuote; if( doubleQuotes ) openingQuote = m_typographicDoubleQuotes.begin; else openingQuote = m_typographicSimpleQuotes.begin; // case 3b if( parag->at( index - 1 )->c != openingQuote ) ending = false; } } // cases 2a and 3a if( index > 1 && !ending ) { TQChar::Category c2 = parag->at( index - 2 )->c.category(); ending = (c2 == TQChar::Punctuation_InitialQuote); } if( ending ) { if( doubleQuotes ) replacement = m_typographicDoubleQuotes.end; else replacement = m_typographicSimpleQuotes.end; } else { if( doubleQuotes ) replacement = m_typographicDoubleQuotes.begin; else replacement = m_typographicSimpleQuotes.begin; } return txtObj->replaceSelectionCommand( textEditCursor, replacement, i18n("Typographic Quote"), KoTextDocument::HighlightSelection ); } KCommand * KoAutoFormat::doUpperCase( KoTextCursor *textEditCursor, KoTextParag *parag, int index, const TQString & word, KoTextObject *txtObj ) { KoTextDocument * textdoc = parag->textDocument(); unsigned int length = word.length(); if (word.at(length-1) == '.' ) { --index; --length; } int const start = index - length; KoTextCursor backCursor( parag->document() ); backCursor.setParag( parag ); backCursor.setIndex( start ); // backCursor now points at the first char of the word TQChar const firstChar = backCursor.parag()->at( backCursor.index() )->c; bool bNeedMove = false; KCommand *cmd = 0L; if ( m_convertUpperCase && isLower( firstChar ) ) { bool beginningOfSentence = true; // true if beginning of text // Go back over any space/tab/CR while ( backCursor.index() > 0 || backCursor.parag()->prev() ) { beginningOfSentence = false; // we could go back -> false unless we'll tqfind '.' backCursor.gotoLeft(); if ( !backCursor.parag()->at( backCursor.index() )->c.isSpace() ) break; } // We are now at the first non-space char before the word if ( !beginningOfSentence ) beginningOfSentence = isMark( backCursor.parag()->at( backCursor.index() )->c); //beginningOfSentence = isMark( backCursor.parag()->at( backCursor.index() )->c ) && (backCursor.parag()->at( backCursor.index()+1 )->c.isSpace()); if ( !beginningOfSentence && start==0 ) if ( parag->counter() || backCursor.parag()->at( backCursor.index() )->c.isPunct() ) beginningOfSentence = true; // Now look for exceptions if ( beginningOfSentence ) { TQChar const punct = backCursor.parag()->at( backCursor.index() )->c; TQString const text = getLastWord( backCursor.parag(), backCursor.index() ) + punct; kdDebug() << "text: " << text << endl; // text has the word at the end of the 'sentence', including the termination. Example: "Mr." beginningOfSentence = (m_upperCaseExceptions.tqfindIndex(text)==-1); // Ok if we can't find it } if ( beginningOfSentence ) { KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + 1 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); cmd = txtObj->replaceSelectionCommand( textEditCursor, TQString( firstChar.upper() ), i18n("Autocorrect (capitalize first letter)"), KoTextDocument::HighlightSelection ); bNeedMove = true; } } else if ( m_convertUpperUpper && isUpper( firstChar ) && length > 2 ) { backCursor.setIndex( backCursor.index() + 1 ); TQChar secondChar = backCursor.parag()->at( backCursor.index() )->c; //kdDebug(32500)<<" secondChar :"<<secondChar<<endl; if ( isUpper( secondChar ) ) { // Check next letter - we still want to be able to write fully uppercase words... backCursor.setIndex( backCursor.index() + 1 ); TQChar thirdChar = backCursor.parag()->at( backCursor.index() )->c; if ( isLower( thirdChar ) && (m_twoUpperLetterException.tqfindIndex(word)==-1)) { // Ok, convert KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start + 1 ); // After all the first letter's fine, so only change the second letter textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + 2 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); TQString replacement = word[1].lower(); cmd = txtObj->replaceSelectionCommand( textEditCursor, replacement, i18n("Autocorrect"), KoTextDocument::HighlightSelection ); bNeedMove = true; } } } if ( bNeedMove ) { if (word.at(word.length()-1) == '.' ) ++index; txtObj->emitHideCursor(); textEditCursor->setParag( parag ); textEditCursor->setIndex( index ); textEditCursor->gotoRight(); // not the same thing as index+1, in case of CR txtObj->emitShowCursor(); } return cmd; } KCommand * KoAutoFormat::doAutoReplaceNumber( KoTextCursor* textEditCursor, KoTextParag *parag, int& index, const TQString & word , KoTextObject *txtObj ) { unsigned int length = word.length(); if ( length != 3 ) return 0L; KoTextDocument * textdoc = parag->textDocument(); int start = index - length; if( word == TQString("1/2") || word == TQString("1/4") || word == TQString("3/4") ) { KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + length ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); TQString replacement; if( word == TQString("1/2") ) replacement=TQString("�"); else if (word == TQString("1/4") ) replacement=TQString("�"); else if (word == TQString("3/4") ) replacement=TQString("�"); TQString cmdName = i18n("Autocorrect for Fraction"); KCommand *cmd =txtObj->replaceSelectionCommand( textEditCursor, replacement, cmdName, KoTextDocument::HighlightSelection ); txtObj->emitHideCursor(); textEditCursor->gotoRight(); txtObj->emitShowCursor(); index = index - length + replacement.length(); return cmd; } return 0L; } void KoAutoFormat::detectStartOfLink(KoTextParag * parag, int const index, bool const insertedDot) { TQString word; KoTextString *s = parag->string(); for ( int i = 0; i < index; ++i ) { word.append( s->at( i ).c ); } if (word.tqfind("http")!=-1 || word.tqfind("https")!=-1 || word.tqfind("mailto")!=-1 || word.tqfind("ftp")!=-1 || word.tqfind("file")!=-1 || word.tqfind("news")!=-1 || word.tqfind('@')!=-1) m_ignoreUpperCase=true; else { int const tmp_pos=word.tqfind("www."); if (tmp_pos!=-1 && (word.tqfind('.',tmp_pos+4)!=-1 || insertedDot) ) m_ignoreUpperCase=true; } } void KoAutoFormat::doAutoDetectUrl( KoTextCursor *textEditCursor, KoTextParag *parag, int &index, TQString & word, KoTextObject *txtObj ) { kdDebug() << "link:" << word << endl; char link_type = 0; int pos = word.tqfind("http://"); int tmp_pos = word.tqfind("https://"); if(tmp_pos<pos && tmp_pos!=-1) pos = tmp_pos; tmp_pos = word.tqfind("mailto:/"); if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1) pos = tmp_pos; tmp_pos = word.tqfind("ftp://"); if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1) pos = tmp_pos; tmp_pos = word.tqfind("ftp."); if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1) { pos = tmp_pos; link_type = 3; } tmp_pos = word.tqfind("file:/"); if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1) pos = tmp_pos; tmp_pos = word.tqfind("news:"); if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1) pos = tmp_pos; tmp_pos = word.tqfind("www."); if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1 && word.tqfind('.',tmp_pos+4)!=-1 ) { pos = tmp_pos; link_type = 2; } tmp_pos = word.tqfind('@'); if ( pos == -1 && tmp_pos != -1 ) { pos = tmp_pos-1; TQChar c; while( pos>=0 ) { c = word.at(pos); if ( c.isPunct() && c!='.'&& c!='_') break; else --pos; } if ( pos == tmp_pos-1 ) //it not a valid address { m_ignoreUpperCase = false; pos = -1; } else ++pos; link_type = 1; } if(pos!=-1) { // A URL inside e.g. quotes (like "http://www.koffice.org" with the quotes) shouldn't include the quote in the URL. while ( !word.at(word.length()-1).isLetter() && !word.at(word.length()-1).isDigit() && word.at(word.length()-1)!='/') { word.truncate(word.length()-1); --index; } word.remove(0,pos); unsigned int const length = word.length(); int const start = index - length; KoTextCursor cursor( parag->document() ); KoTextDocument * textdoc = parag->textDocument(); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + length ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); TQString newWord = word; if(link_type==1) newWord = TQString("mailto:") + word; else if(link_type==2) newWord = TQString("http://") + word; else if(link_type==3) newWord = TQString("ftp://") + word; KoVariable* var = new KoLinkVariable( textdoc, word, newWord, m_varFormatCollection->format( "STRING" ), m_varCollection ); CustomItemsMap customItemsMap; customItemsMap.insert( 0, var ); KoTextFormat * lastFormat = parag->at( start )->format(); int origCursorIndex = textEditCursor->index(); txtObj->insert( textEditCursor, lastFormat, KoTextObject::customItemChar(), i18n("Insert Variable"), KoTextDocument::HighlightSelection, KoTextObject::DefaultInsertFlags, customItemsMap ); var->recalc(); parag->tqinvalidate(0); parag->setChanged( true ); // adjust index index -= length-1; // we removed length chars and inserted one instead txtObj->emitHideCursor(); textEditCursor->setIndex( origCursorIndex - (length-1) ); txtObj->emitShowCursor(); // ###### TODO: Move to a common method, this code is duplicated... if ( m_completion && m_addCompletionWord && m_listCompletion->items().count() < m_nbMaxCompletionWord ) { if (word.length()>= m_minCompletionWordLength && !word.isEmpty() && m_listCompletion->makeCompletion(word).isEmpty()) { kdDebug() << "Adding:" << word << endl; m_listCompletion->addItem( word ); if ( word.length() > m_countMaxWords ) m_countMaxWords = word.length(); } } } } void KoAutoFormat::doAutoIncludeUpperUpper(KoTextCursor* /*textEditCursor*/, KoTextParag *parag, KoTextObject* /*txtObj*/ ) { KoTextString *s = parag->string(); if( s->length() < 2 ) return; for (int i=0; i<=(s->length() - 1);i++) { TQString word; for ( int j = i ; j < s->length() - 1; j++ ) { TQChar ch = s->at( j ).c; if ( ch.isSpace() ) break; word.append( ch ); } if( word.length() > 2 && word.left(2)==word.left(2).upper() && word.tqat(3)!=word.tqat(3).upper() ) { if ( m_twoUpperLetterException.tqfindIndex(word )==-1) m_twoUpperLetterException.append( word); } i+=word.length(); } } void KoAutoFormat::doAutoIncludeAbbreviation(KoTextCursor* /*textEditCursor*/, KoTextParag *parag, KoTextObject* /*txtObj*/ ) { KoTextString *s = parag->string(); if( s->length() < 2 ) return; for (int i=0; i<=(s->length() - 1);i++) { TQString wordAfter; TQString word; for ( int j = i ; j < s->length() - 1; j++ ) { TQChar ch = s->at( j ).c; if ( ch.isSpace() ) break; word.append( ch ); } if ( isMark( word.at(word.length()-1)) ) { for ( int j = i+word.length()+1 ; j < s->length() - 1; j++ ) { TQChar ch = s->at( j ).c; if ( ch.isSpace() ) break; wordAfter.append( ch ); } if( word.length()>1 && !wordAfter.isEmpty() && wordAfter.tqat(0)==wordAfter.tqat(0).lower()) { if ( m_upperCaseExceptions.tqfindIndex(word )==-1) m_upperCaseExceptions.append( word ); } } i+=word.length(); if( !wordAfter.isEmpty()) { i+=wordAfter.length()+1; } } } KCommand * KoAutoFormat::doAutoChangeFormat( KoTextCursor *textEditCursor, KoTextParag *parag,int index, const TQString & word, KoTextObject *txtObj ) { bool underline = (word.at(0)=='_' && word.at(word.length()-1)=='_'); bool bold = (word.at(0)=='*' && word.at(word.length()-1)=='*'); if( bold || underline) { TQString replacement=word.mid(1,word.length()-2); int start = index - word.length(); KoTextDocument * textdoc = parag->textDocument(); KMacroCommand *macro=new KMacroCommand(i18n("Autocorrection: Change Format")); KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + word.length() ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); macro->addCommand(txtObj->replaceSelectionCommand( textEditCursor, replacement, i18n("Autocorrect Word"), KoTextDocument::HighlightSelection)); KoTextFormat * lastFormat = parag->at( start )->format(); KoTextFormat * newFormat = new KoTextFormat(*lastFormat); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + word.length()-2 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); if( bold) { newFormat->setBold(true); macro->addCommand(txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::Bold , false,KoTextDocument::HighlightSelection )); } else if( underline ) { newFormat->setUnderline(true); macro->addCommand(txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::Underline , false,KoTextDocument::HighlightSelection )); } txtObj->emitHideCursor(); textEditCursor->gotoRight(); txtObj->emitShowCursor(); return macro; } return 0L; } KCommand *KoAutoFormat::doUseBulletStyle(KoTextCursor * /*textEditCursor*/, KoTextParag *parag, KoTextObject *txtObj, int& index ) { KoTextDocument * textdoc = parag->textDocument(); KoTextCursor cursor( parag->document() ); KoTextString *s = parag->string(); TQChar ch = s->at( 0 ).c; if( m_useBulletStyle && (ch =='*' || ch == '-' || ch =='+') && (s->at(1).c).isSpace()) { if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_FOOTNOTE ) return 0L; KMacroCommand *macroCmd = new KMacroCommand( i18n("Autocorrect (use bullet style)")); cursor.setParag( parag ); cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setParag( parag ); cursor.setIndex( 2 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KCommand *cmd=txtObj->removeSelectedTextCommand( &cursor, KoTextDocument::HighlightSelection ); // Adjust index index -= 2; if(cmd) macroCmd->addCommand(cmd); cursor.setParag( parag ); cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( 2 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KoParagCounter c; if( m_bulletStyle.isNull() && (ch == '*' || ch == '+' || ch == '-')) { if ( ch =='*') { c.setNumbering( KoParagCounter::NUM_LIST ); c.setStyle( KoParagCounter::STYLE_DISCBULLET ); } else if ( ch =='+' || ch=='-') { c.setNumbering( KoParagCounter::NUM_LIST ); c.setStyle( KoParagCounter::STYLE_CUSTOMBULLET ); if ( ch =='-' ) c.setCustomBulletCharacter( '-' ); else if ( ch=='+') c.setCustomBulletCharacter( '+' ); } } else { c.setNumbering( KoParagCounter::NUM_LIST ); c.setStyle( KoParagCounter::STYLE_CUSTOMBULLET ); c.setCustomBulletCharacter( m_bulletStyle ); } c.setSuffix(TQString()); cmd=txtObj->setCounterCommand( &cursor, c ,KoTextDocument::HighlightSelection ); if( cmd) macroCmd->addCommand(cmd); if (parag->next() ) cursor.setParag( parag->next() ); else return 0L; cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( 0 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); cmd=txtObj->setCounterCommand( &cursor, c ,KoTextDocument::HighlightSelection ); if(cmd) macroCmd->addCommand(cmd); return macroCmd; } return 0L; } KCommand *KoAutoFormat::doUseNumberStyle(KoTextCursor * /*textEditCursor*/, KoTextParag *parag, KoTextObject *txtObj, int& index ) { if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_FOOTNOTE ) return 0L; KoTextDocument * textdoc = parag->textDocument(); KoTextCursor cursor( parag->document() ); KoTextString *s = parag->string(); TQString word; for ( int i = 0 ; i < s->length() - 1; i++ ) { TQChar ch = s->at( i ).c; if ( ch.isSpace() ) break; word.append( ch ); } TQChar punct=word[word.length()-1]; if( punct.isPunct() ) { TQString number=word.mid(0,word.length()-1); bool ok; uint val=number.toUInt(&ok); if( ok ) { KMacroCommand *macroCmd = new KMacroCommand( i18n("Autocorrect (use number style)")); cursor.setParag( parag ); cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setParag( parag ); cursor.setIndex( word.length()+1 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KCommand *cmd=txtObj->removeSelectedTextCommand( &cursor, KoTextDocument::HighlightSelection ); // Adjust index index -= word.length()+1; if(cmd) macroCmd->addCommand(cmd); // Apply counter to this paragraph cursor.setParag( parag ); cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( 2 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KoParagCounter c; c.setNumbering( KoParagCounter::NUM_LIST ); c.setStyle( KoParagCounter::STYLE_NUM ); c.setSuffix(TQString( punct )); c.setStartNumber( (int)val); // Look at which number this parag will have without a restart counter flag, // to see if we need it. Thanks to Shaheed for number() taking a parag as param, // so that it works even if the parag doesn't have this counter yet! if ( c.number( parag ) != (int)val ) c.setRestartCounter( true ); cmd=txtObj->setCounterCommand( &cursor, c, KoTextDocument::HighlightSelection ); if( cmd) macroCmd->addCommand(cmd); // Apply counter to next paragraph too // but without restart c.setRestartCounter( false ); cursor.setParag( parag->next() ); cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( 0 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); cmd=txtObj->setCounterCommand( &cursor, c, KoTextDocument::HighlightSelection ); if(cmd) macroCmd->addCommand(cmd); return macroCmd; } } return 0L; } KCommand * KoAutoFormat::doRemoveSpaceBeginEndLine( KoTextCursor *textEditCursor, KoTextParag *parag, KoTextObject *txtObj, int &index ) { KoTextString *s = parag->string(); KoTextDocument * textdoc = parag->textDocument(); KoTextCursor cursor( parag->document() ); KMacroCommand *macroCmd = 0L; // Cut away spaces at end of paragraph for ( int i = parag->lastCharPos(); i >= 0; --i ) { TQChar ch = s->at( i ).c; if ( ch != ' ' ) // was: !ch.isSpace(), but this includes tabs, and this option is only about spaces { if( i == parag->lastCharPos() ) break; cursor.setParag( parag ); cursor.setIndex( i+1 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setParag( parag ); cursor.setIndex( parag->lastCharPos()+1 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KCommand *cmd=txtObj->replaceSelectionCommand( &cursor, "", TQString(), KoTextDocument::HighlightSelection ); if(cmd) { if ( index > i ) index = i; if ( !macroCmd ) macroCmd = new KMacroCommand( i18n("Autocorrect (remove start and end line space)")); macroCmd->addCommand(cmd); } break; } } // Cut away spaces at start of parag. for ( int i = 0 ; i <= parag->lastCharPos() ; i++ ) { TQChar ch = s->at( i ).c; if ( ch != ' ' ) // was: !ch.isSpace(), but this includes tabs, and this option is only about spaces { if( i == 0 ) break; cursor.setParag( parag ); cursor.setIndex( 0 ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setParag( parag ); cursor.setIndex( i ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); KCommand *cmd=txtObj->replaceSelectionCommand( &cursor, "", TQString(), KoTextDocument::HighlightSelection ); if(cmd) { index -= i; // adjust index if ( !macroCmd ) macroCmd = new KMacroCommand( i18n("Autocorrect (remove start and end line space)")); macroCmd->addCommand(cmd); } break; } } if( macroCmd ) { txtObj->emitHideCursor(); textEditCursor->setParag( parag->next() ); //textEditCursor->cursorgotoRight(); txtObj->emitShowCursor(); } return macroCmd; } KCommand *KoAutoFormat::doCapitalizeNameOfDays( KoTextCursor* textEditCursor, KoTextParag *parag, int index, const TQString & word , KoTextObject *txtObj ) { //m_cacheNameOfDays //todo int pos = m_cacheNameOfDays.tqfindIndex( word.lower() ); if ( pos == -1 ) return 0L; KoTextDocument * textdoc = parag->textDocument(); TQString replaceStr= m_cacheNameOfDays[pos]; int start = index - replaceStr.length(); int length = replaceStr.length(); if( word.tqat(0).isLetter() && word.tqat(0)==word.tqat(0).lower() ) { KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + length ); TQString replacement = replaceStr.tqat(0).upper() + replaceStr.right( length-1 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); TQString cmdName=i18n("Capitalize Name of Days"); KCommand *cmd =txtObj->replaceSelectionCommand( textEditCursor, replacement, cmdName, KoTextDocument::HighlightSelection ); txtObj->emitHideCursor(); textEditCursor->gotoRight(); txtObj->emitShowCursor(); return cmd; } return 0L; } KCommand *KoAutoFormat::doAutoSuperScript( KoTextCursor* textEditCursor, KoTextParag *parag, int index, const TQString & word , KoTextObject *txtObj ) { KoAutoFormatEntryMap::Iterator it = m_superScriptEntries.begin(); bool found = false; TQString tqreplace; for ( ; it != m_superScriptEntries.end() ; ++it ) { if( it.key()==word) { tqreplace = it.data().tqreplace(); found = true; break; } else if ( it.key()=="othernb") { TQString tmp = it.data().tqreplace(); int pos = word.tqfind( tmp ); if( pos != -1) { if( pos + tmp.length() == word.length()) { bool ok; word.left( pos ).toInt( &ok); if( ok ) { tqreplace = tmp; found = true; break; } } } } } if (found ) { KoTextDocument * textdoc = parag->textDocument(); int start = index - tqreplace.length(); KoTextFormat * lastFormat = parag->at( start )->format(); KoTextFormat * newFormat = new KoTextFormat(*lastFormat); KoTextCursor cursor( parag->document() ); cursor.setParag( parag ); cursor.setIndex( start ); textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor ); cursor.setIndex( start + word.length() -1 ); textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor ); newFormat->setVAlign(KoTextFormat::AlignSuperScript); KCommand *cmd =txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::VAlign , false,KoTextDocument::HighlightSelection ); textdoc->removeSelection( KoTextDocument::HighlightSelection ); return cmd; } return 0L; } bool KoAutoFormat::doIgnoreDoubleSpace( KoTextParag *parag, int index, TQChar ch ) { if( m_ignoreDoubleSpace && ch==' ' && index >= 0 && !parag->hasAnySelection() ) { KoTextString *s = parag->string(); TQChar ch = s->at( index ).c; if ( ch==' ' ) return true; } return false; } void KoAutoFormat::configTypographicSimpleQuotes( TypographicQuotes _tq ) { m_typographicSimpleQuotes = _tq; } void KoAutoFormat::configTypographicDoubleQuotes( TypographicQuotes _tq ) { m_typographicDoubleQuotes = _tq; } void KoAutoFormat::configUpperCase( bool _uc ) { m_convertUpperCase = _uc; } void KoAutoFormat::configUpperUpper( bool _uu ) { m_convertUpperUpper = _uu; } void KoAutoFormat::configAdvancedAutocorrect( bool _aa ) { m_advancedAutoCorrect = _aa; } void KoAutoFormat::configAutoDetectUrl(bool _au) { m_autoDetectUrl=_au; } void KoAutoFormat::configIgnoreDoubleSpace( bool _ids) { m_ignoreDoubleSpace=_ids; } void KoAutoFormat::configRemoveSpaceBeginEndLine( bool _space) { m_removeSpaceBeginEndLine=_space; } void KoAutoFormat::configUseBulletStyle( bool _ubs) { m_useBulletStyle=_ubs; } void KoAutoFormat::configBulletStyle( TQChar b ) { m_bulletStyle = b; } void KoAutoFormat::configAutoChangeFormat( bool b) { m_autoChangeFormat = b; } void KoAutoFormat::configAutoReplaceNumber( bool b ) { m_autoReplaceNumber = b; } void KoAutoFormat::configAutoNumberStyle( bool b ) { m_useAutoNumberStyle = b; } void KoAutoFormat::configCompletion( bool b ) { m_completion = b; } void KoAutoFormat::configToolTipCompletion( bool b ) { m_toolTipCompletion = b; if (!b && m_completionBox) { delete m_completionBox; m_completionBox = 0; } } void KoAutoFormat::configKeyCompletionAction( KeyCompletionAction action ) { m_keyCompletionAction = action; } void KoAutoFormat::configAppendSpace( bool b) { m_completionAppendSpace= b; } void KoAutoFormat::configMinWordLength( uint val ) { m_minCompletionWordLength = val; } void KoAutoFormat::configNbMaxCompletionWord( uint val ) { m_nbMaxCompletionWord = val; } void KoAutoFormat::configAddCompletionWord( bool b ) { m_addCompletionWord= b; } bool KoAutoFormat::isUpper( const TQChar &c ) { return c.lower() != c; } bool KoAutoFormat::isLower( const TQChar &c ) { // Note that this is not the same as !isUpper ! // For instance '1' is not lower nor upper, return c.upper() != c; } bool KoAutoFormat::isMark( const TQChar &c ) { return ( c == TQChar( '.' ) || c == TQChar( '?' ) || c == TQChar( '!' ) ); } bool KoAutoFormat::isSeparator( const TQChar &c ) { return ( !c.isLetter() && !c.isNumber() && !c.isDigit() ); } void KoAutoFormat::buildMaxLen() { m_maxFindLength = 0; TQDictIterator<KoAutoFormatEntry> it( m_entries ); for( ; it.current(); ++it ) { m_maxFindLength = TQMAX( m_maxFindLength, it.currentKey().length() ); } TQDictIterator<KoAutoFormatEntry> it2( m_allLanguages ); for( ; it2.current(); ++it2 ) { m_maxFindLength = TQMAX( m_maxFindLength, it2.currentKey().length() ); } } TQStringList KoAutoFormat::listCompletion() const { return m_listCompletion->items(); } void KoAutoFormat::configIncludeTwoUpperUpperLetterException( bool b) { m_includeTwoUpperLetterException = b; } void KoAutoFormat::configIncludeAbbreviation( bool b ) { m_includeAbbreviation = b; } void KoAutoFormat::configAutoSuperScript( bool b ) { m_bAutoSuperScript = b; } void KoAutoFormat::configCorrectionWithFormat( bool b) { m_bAutoCorrectionWithFormat = b; } void KoAutoFormat::configCapitalizeNameOfDays( bool b) { m_bCapitalizeNameOfDays = b; } void KoAutoFormat::configAutoFormatLanguage( const TQString &_lang) { m_autoFormatLanguage=_lang; } KCommand *KoAutoFormat::applyAutoFormat( KoTextObject * obj ) { KoTextParag * parag = obj->textDocument()->firstParag(); KoTextCursor *cursor = new KoTextCursor( obj->textDocument() ); KMacroCommand *macro = 0L; while ( parag ) { cursor->setIndex(0); for (int i=0;i<parag->length();i++) { cursor->gotoRight(); //kdDebug() << "ch:" << parag->string()->at(i).c << endl; if (i == parag->length()-1) doAutoFormat(cursor,parag,i,'\n',obj); else doAutoFormat(cursor,parag,i, parag->string()->at(i).c,obj); } parag = parag->next(); } delete cursor; return macro; } void KoAutoFormat::changeTextFormat(KoSearchContext *formatOptions, KoTextFormat * format, int & flags ) { if (formatOptions ) { if (formatOptions->m_optionsMask & KoSearchContext::Bold) { format->setBold( formatOptions->m_options & KoSearchContext::Bold); flags |=KoTextFormat::Bold; } if ( formatOptions->m_optionsMask & KoSearchContext::Size) { format->setPointSize( formatOptions->m_size ); flags |=KoTextFormat::Size; } if ( formatOptions->m_optionsMask & KoSearchContext::Family) { format->setFamily( formatOptions->m_family ); flags |=KoTextFormat::Family; } if ( formatOptions->m_optionsMask & KoSearchContext::Color) { format->setColor(formatOptions->m_color); flags |=KoTextFormat::Color; } if ( formatOptions->m_optionsMask & KoSearchContext::BgColor) { format->setTextBackgroundColor(formatOptions->m_backGroundColor); flags |=KoTextFormat::TextBackgroundColor; } if ( formatOptions->m_optionsMask & KoSearchContext::Italic) { format->setItalic( formatOptions->m_options & KoSearchContext::Italic); flags |=KoTextFormat::Italic; } if ( formatOptions->m_optionsMask & KoSearchContext::WordByWord) { format->setWordByWord( formatOptions->m_options & KoSearchContext::WordByWord ); flags |=KoTextFormat::WordByWord; } if ( formatOptions->m_optionsMask & KoSearchContext::Shadow) { if ( formatOptions->m_options & KoSearchContext::Shadow ) format->setShadow( 1, 1, TQt::gray ); else format->setShadow( 0, 0, TQColor() ); flags |=KoTextFormat::ShadowText; } if ( formatOptions->m_optionsMask & KoSearchContext::Underline) { format->setUnderlineType(formatOptions->m_underline); flags |=KoTextFormat::ExtendUnderLine; } if ( formatOptions->m_optionsMask & KoSearchContext::StrikeOut) { format->setStrikeOutType(formatOptions->m_strikeOut); flags |= KoTextFormat::StrikeOut; } if ( formatOptions->m_optionsMask & KoSearchContext::VertAlign) { format->setVAlign(formatOptions->m_vertAlign); flags |=KoTextFormat::VAlign; } if ( formatOptions->m_optionsMask & KoSearchContext::Attribute) { format->setAttributeFont(formatOptions->m_attribute); flags |= KoTextFormat::Attribute; } if (formatOptions->m_optionsMask & KoSearchContext::Language) { flags |= KoTextFormat::Language; format->setLanguage( formatOptions->m_language ); } } } #include "KoAutoFormat.moc"