KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2534 lines
92KB

  1. /* This file is part of the KDE project
  2. Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
  3. 2001 Sven Leiber <s.leiber@web.de>
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. * Boston, MA 02110-1301, USA.
  16. */
  17. #include "KoAutoFormat.h"
  18. #include "KoTextObject.h"
  19. #include "KoTextParag.h"
  20. #include "KoVariable.h"
  21. #include "KoParagCounter.h"
  22. #include <KoDocument.h>
  23. #include <KoSearchDia.h>
  24. #include <KoGlobal.h>
  25. #include <tdeversion.h>
  26. #include <kdebug.h>
  27. #include <tdelocale.h>
  28. #include <kinstance.h>
  29. #include <tdeconfig.h>
  30. #include <kstandarddirs.h>
  31. #include <tdeglobal.h>
  32. #include <kcommand.h>
  33. //#include <KoTextFormat.h>
  34. #include <kcompletion.h>
  35. #include <kcalendarsystem.h>
  36. #include <tqfile.h>
  37. #include <tqlabel.h>
  38. #include <tqtooltip.h>
  39. #include <tqwhatsthis.h>
  40. #include <tqdom.h>
  41. #include <tqregexp.h>
  42. KoCompletionBox::KoCompletionBox( TQWidget * parent, const char * name, WFlags f)
  43. : TQLabel(parent,name,f)
  44. {
  45. setBackgroundColor(TQColor("#FFFFE6"));
  46. setFocusPolicy(TQ_NoFocus);
  47. setFrameShape(TQFrame::Box);
  48. }
  49. KoCompletionBox::~KoCompletionBox()
  50. {
  51. }
  52. void KoCompletionBox::mousePressEvent( TQMouseEvent *)
  53. {
  54. hide();
  55. }
  56. TQString& KoCompletionBox::lastWord()
  57. {
  58. return m_lastWord;
  59. }
  60. void KoCompletionBox::setLastWord( TQString const &lastword)
  61. {
  62. m_lastWord = lastword;
  63. }
  64. KoAutoFormatEntry::KoAutoFormatEntry(const TQString& replace)
  65. : m_replace( replace )
  66. {
  67. m_formatOptions= 0L;
  68. }
  69. KoAutoFormatEntry::~KoAutoFormatEntry()
  70. {
  71. delete m_formatOptions;
  72. m_formatOptions=0L;
  73. }
  74. KoSearchContext *KoAutoFormatEntry::formatEntryContext() const
  75. {
  76. return m_formatOptions;
  77. }
  78. void KoAutoFormatEntry::createNewEntryContext()
  79. {
  80. if ( !m_formatOptions )
  81. {
  82. m_formatOptions = new KoSearchContext();
  83. }
  84. }
  85. void KoAutoFormatEntry::setFormatEntryContext( KoSearchContext *_cont )
  86. {
  87. delete m_formatOptions;
  88. m_formatOptions=_cont;
  89. }
  90. void KoAutoFormatEntry::clearFormatEntryContext( )
  91. {
  92. delete m_formatOptions;
  93. m_formatOptions = 0L;
  94. }
  95. /******************************************************************/
  96. /* Class: KoAutoFormat */
  97. /******************************************************************/
  98. KoAutoFormat::KoAutoFormat( KoDocument *_doc, KoVariableCollection *_varCollection, KoVariableFormatCollection *_varFormatCollection )
  99. : m_doc( _doc ),
  100. m_varCollection(_varCollection),
  101. m_varFormatCollection(_varFormatCollection),
  102. m_autoFormatLanguage( TQString()),
  103. m_configRead( false ),
  104. m_convertUpperCase( false ), m_convertUpperUpper( false ),
  105. m_advancedAutoCorrect( true ),
  106. m_autoDetectUrl( false ),
  107. m_ignoreDoubleSpace( false ),
  108. m_removeSpaceBeginEndLine( false ),
  109. m_useBulletStyle(false),
  110. m_autoChangeFormat(false),
  111. m_autoReplaceNumber(false),
  112. m_useAutoNumberStyle(false),
  113. m_completion(false),
  114. m_toolTipCompletion(false),
  115. m_completionAppendSpace(false),
  116. m_addCompletionWord(true),
  117. m_includeTwoUpperLetterException(false),
  118. m_includeAbbreviation(false),
  119. m_ignoreUpperCase(false),
  120. m_bAutoFormatActive(true),
  121. m_bAutoSuperScript( false ),
  122. m_bAutoCorrectionWithFormat( false ),
  123. m_bCapitalizeNameOfDays( false ),
  124. m_wordInserted( false ),
  125. m_bulletStyle(),
  126. m_typographicSimpleQuotes(),
  127. m_typographicDoubleQuotes(),
  128. m_typographicDefaultDoubleQuotes(),
  129. m_typographicDefaultSimpleQuotes(),
  130. m_listCompletion( new TDECompletion ),
  131. m_entries(17,false),
  132. m_allLanguages(17,false),
  133. m_superScriptEntries(),
  134. m_upperCaseExceptions(),
  135. m_twoUpperLetterException(),
  136. m_maxFindLength( 0 ),
  137. m_minCompletionWordLength( 5 ),
  138. m_nbMaxCompletionWord( 500 ),
  139. m_countMaxWords(0),
  140. m_completionBox(0),
  141. m_keyCompletionAction( Enter )
  142. {
  143. //load once this list not each time that we "readConfig"
  144. loadListOfWordCompletion();
  145. m_listCompletion->setIgnoreCase( true );
  146. updateMaxWords();
  147. TDELocale tdelocale(m_doc->instance()->instanceName());
  148. for (int i = 1; i <=7; i++)
  149. {
  150. m_cacheNameOfDays.append(tdelocale.calendar()->weekDayName( i ).lower());
  151. }
  152. }
  153. KoAutoFormat::KoAutoFormat( const KoAutoFormat& format )
  154. : m_doc( format.m_doc ),
  155. m_varCollection( format.m_varCollection ),
  156. m_varFormatCollection( format.m_varFormatCollection ),
  157. m_autoFormatLanguage( format.m_autoFormatLanguage),
  158. m_configRead( format.m_configRead ),
  159. m_convertUpperCase( format.m_convertUpperCase ),
  160. m_convertUpperUpper( format.m_convertUpperUpper ),
  161. m_advancedAutoCorrect( format.m_advancedAutoCorrect ),
  162. m_autoDetectUrl( format.m_autoDetectUrl ),
  163. m_ignoreDoubleSpace( format.m_ignoreDoubleSpace ),
  164. m_removeSpaceBeginEndLine( format.m_removeSpaceBeginEndLine ),
  165. m_useBulletStyle( format.m_useBulletStyle ),
  166. m_autoChangeFormat( format.m_autoChangeFormat ),
  167. m_autoReplaceNumber( format.m_autoReplaceNumber ),
  168. m_useAutoNumberStyle( format.m_useAutoNumberStyle ),
  169. m_completion( format.m_completion ),
  170. m_toolTipCompletion( format.m_toolTipCompletion),
  171. m_completionAppendSpace( format.m_completionAppendSpace ),
  172. m_addCompletionWord( format.m_addCompletionWord ),
  173. m_includeTwoUpperLetterException( format.m_includeTwoUpperLetterException ),
  174. m_includeAbbreviation( format.m_includeAbbreviation ),
  175. m_ignoreUpperCase( format.m_ignoreUpperCase ),
  176. m_bAutoFormatActive( format.m_bAutoFormatActive ),
  177. m_bAutoSuperScript( format.m_bAutoSuperScript ),
  178. m_bAutoCorrectionWithFormat( format.m_bAutoCorrectionWithFormat),
  179. m_bCapitalizeNameOfDays( format.m_bCapitalizeNameOfDays),
  180. m_bulletStyle( format.m_bulletStyle ),
  181. m_typographicSimpleQuotes( format.m_typographicSimpleQuotes ),
  182. m_typographicDoubleQuotes( format.m_typographicDoubleQuotes ),
  183. m_typographicDefaultDoubleQuotes( format.m_typographicDefaultDoubleQuotes),
  184. m_typographicDefaultSimpleQuotes( format.m_typographicDefaultSimpleQuotes),
  185. m_listCompletion( 0L ), // don't copy it!
  186. m_entries(17,false ),//don't copy it.
  187. m_allLanguages(17,false), //don't copy it
  188. m_superScriptEntries ( format.m_superScriptEntries ),
  189. m_upperCaseExceptions( format.m_upperCaseExceptions ),
  190. m_twoUpperLetterException( format.m_twoUpperLetterException ),
  191. m_maxFindLength( format.m_maxFindLength ),
  192. m_minCompletionWordLength( format.m_minCompletionWordLength ),
  193. m_nbMaxCompletionWord( format.m_nbMaxCompletionWord ),
  194. m_cacheNameOfDays( format.m_cacheNameOfDays),
  195. m_completionBox(0),
  196. m_keyCompletionAction( format.m_keyCompletionAction )
  197. {
  198. //m_listCompletion=new TDECompletion();
  199. //m_listCompletion->setItems( autoFormat.listCompletion() );
  200. //copyAutoFormatEntries( autoFormat );
  201. }
  202. KoAutoFormat::~KoAutoFormat()
  203. {
  204. delete m_listCompletion;
  205. m_entries.setAutoDelete( true );
  206. m_entries.clear();
  207. m_allLanguages.setAutoDelete( true );
  208. m_allLanguages.clear();
  209. }
  210. void KoAutoFormat::updateMaxWords()
  211. {
  212. TQStringList list = m_listCompletion->items();
  213. for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
  214. {
  215. TQString tmp = *it;
  216. uint maxword = 1;
  217. for (uint i=0; i < (uint)tmp.length(); i++)
  218. if ( tmp.at(i).isSpace() || tmp.at(i).isPunct() )
  219. maxword++;
  220. if (maxword > m_countMaxWords )
  221. m_countMaxWords = maxword;
  222. }
  223. kdDebug() << "m_countMaxWords: " << m_countMaxWords << endl;
  224. }
  225. void KoAutoFormat::loadListOfWordCompletion()
  226. {
  227. TDEConfig* config = KoGlobal::kofficeConfig();
  228. TDEConfigGroupSaver cgs( config, "Completion Word" );
  229. m_listCompletion->insertItems(config->readListEntry( "list" ));
  230. }
  231. void KoAutoFormat::readConfig(bool force)
  232. {
  233. // Read the autoformat configuration
  234. // This is done on demand (when typing the first char, or when opening the config dialog)
  235. // so that loading is faster and to avoid doing it for readonly documents.
  236. if ( m_configRead && !force )
  237. return;
  238. TDEConfig* config = KoGlobal::kofficeConfig();
  239. TDEConfigGroupSaver cgs( config, "AutoFormat" );
  240. //when we force don't load format language.
  241. if ( !force)
  242. m_autoFormatLanguage = config->readEntry("formatLanguage", TQString());
  243. m_convertUpperCase = config->readBoolEntry( "ConvertUpperCase", false );
  244. m_convertUpperUpper = config->readBoolEntry( "ConvertUpperUpper", false );
  245. m_includeTwoUpperLetterException = config->readBoolEntry( "includeTwoLetterException", false );
  246. m_includeAbbreviation = config->readBoolEntry( "includeAbbreviation", false );
  247. m_advancedAutoCorrect = config->readBoolEntry( "AdvancedAutocorrect", true );
  248. m_bAutoCorrectionWithFormat = config->readBoolEntry( "AutoCorrectionWithFormat",false );
  249. m_bCapitalizeNameOfDays = config->readBoolEntry( "CapitalizeNameOfDays",false );
  250. m_autoDetectUrl = config->readBoolEntry("AutoDetectUrl",false);
  251. m_ignoreDoubleSpace = config->readBoolEntry("IgnoreDoubleSpace", true);
  252. m_removeSpaceBeginEndLine = config->readBoolEntry("RemoveSpaceBeginEndLine", true);
  253. m_useBulletStyle = config->readBoolEntry("UseBulletStyle",false);
  254. TQString tmp = config->readEntry( "BulletStyle", "" );
  255. m_bulletStyle = tmp.isEmpty() ? TQChar() : tmp[0];
  256. m_autoChangeFormat = config->readBoolEntry( "AutoChangeFormat", false );
  257. m_autoReplaceNumber = config->readBoolEntry( "AutoReplaceNumber", true );
  258. m_useAutoNumberStyle = config->readBoolEntry( "AutoNumberStyle", false );
  259. TQString beginDoubleQuote = config->readEntry( "TypographicQuotesBegin" );
  260. TQString endDoubleQuote = config->readEntry( "TypographicQuotesEnd" );
  261. m_typographicDoubleQuotes.replace = config->readBoolEntry( "TypographicQuotesEnabled", false );
  262. TQString begin = config->readEntry( "TypographicSimpleQuotesBegin" );
  263. TQString end = config->readEntry( "TypographicSimpleQuotesEnd" );
  264. m_typographicSimpleQuotes.replace = config->readBoolEntry( "TypographicSimpleQuotesEnabled", false );
  265. m_bAutoSuperScript = config->readBoolEntry( "AutoSuperScript", true );
  266. config->setGroup( "completion" );
  267. m_completion = config->readBoolEntry( "completion", false );
  268. m_completionAppendSpace = config->readBoolEntry( "CompletionAppendSpace", false );
  269. m_minCompletionWordLength = config->readUnsignedNumEntry( "CompletionMinWordLength", 5 );
  270. m_nbMaxCompletionWord = config->readUnsignedNumEntry( "NbMaxCompletionWord", 100 );
  271. m_addCompletionWord = config->readBoolEntry( "AddCompletionWord", true );
  272. m_toolTipCompletion = config->readBoolEntry( "ToolTipCompletion", true );
  273. m_keyCompletionAction = ( KoAutoFormat::KeyCompletionAction )config->readUnsignedNumEntry( "CompletionKeyAction", 0 );
  274. if ( force )
  275. {
  276. m_entries.setAutoDelete(true);
  277. m_entries.clear();
  278. m_entries.setAutoDelete(false);
  279. m_allLanguages.setAutoDelete(true);
  280. m_allLanguages.clear();
  281. m_allLanguages.setAutoDelete(false);
  282. m_upperCaseExceptions.clear();
  283. m_superScriptEntries.clear();
  284. m_twoUpperLetterException.clear();
  285. }
  286. //config->setGroup( "AutoFormatEntries" );
  287. readAutoCorrectConfig();
  288. if( beginDoubleQuote.isEmpty())
  289. {
  290. if( m_typographicDefaultDoubleQuotes.begin.isNull())
  291. m_typographicDoubleQuotes.begin = TQChar('«');
  292. else
  293. m_typographicDoubleQuotes.begin = m_typographicDefaultDoubleQuotes.begin;
  294. }
  295. else
  296. m_typographicDoubleQuotes.begin = beginDoubleQuote[0];
  297. if( endDoubleQuote.isEmpty() )
  298. {
  299. if( m_typographicDefaultDoubleQuotes.end.isNull())
  300. m_typographicDoubleQuotes.end = TQChar('»');
  301. else
  302. m_typographicDoubleQuotes.end = m_typographicDefaultDoubleQuotes.end;
  303. }
  304. else
  305. m_typographicDoubleQuotes.end = endDoubleQuote[0];
  306. m_typographicDoubleQuotes.replace = m_typographicDoubleQuotes.replace
  307. && !m_typographicDoubleQuotes.begin.isNull()
  308. && !m_typographicDoubleQuotes.end.isNull();
  309. if( begin.isEmpty())
  310. {
  311. if( m_typographicDefaultSimpleQuotes.begin.isNull())
  312. m_typographicSimpleQuotes.begin = TQChar('\'');
  313. else
  314. m_typographicSimpleQuotes.begin = m_typographicDefaultSimpleQuotes.begin;
  315. }
  316. else
  317. m_typographicSimpleQuotes.begin = begin[0];
  318. if( end.isEmpty() )
  319. {
  320. if( m_typographicDefaultSimpleQuotes.end.isNull())
  321. m_typographicSimpleQuotes.end = TQChar('\'');
  322. else
  323. m_typographicSimpleQuotes.end = m_typographicDefaultSimpleQuotes.end;
  324. }
  325. else
  326. m_typographicSimpleQuotes.end = end[0];
  327. m_typographicSimpleQuotes.replace = m_typographicSimpleQuotes.replace
  328. && !m_typographicSimpleQuotes.end.isNull()
  329. && !m_typographicSimpleQuotes.begin.isNull();
  330. loadAllLanguagesAutoCorrection();
  331. buildMaxLen();
  332. autoFormatIsActive();
  333. m_configRead = true;
  334. }
  335. void KoAutoFormat::readAutoCorrectConfig()
  336. {
  337. Q_ASSERT( m_entries.isEmpty() ); // readConfig is only called once...
  338. TDELocale tdelocale(m_doc->instance()->instanceName());
  339. TQString kdelang = tdelocale.languageList().front();
  340. kdelang.remove( TQRegExp( "@.*" ) );
  341. kdDebug(32500) << "KoAutoFormat: m_autoFormatLanguage=" << m_autoFormatLanguage << " kdelang=" << kdelang << endl;
  342. TQString fname;
  343. if ( !m_autoFormatLanguage.isEmpty() )
  344. {
  345. fname = locate( "data", "koffice/autocorrect/" + m_autoFormatLanguage + ".xml", m_doc->instance() );
  346. }
  347. if ( m_autoFormatLanguage != "all_languages" )
  348. {
  349. if ( fname.isEmpty() && !kdelang.isEmpty() )
  350. fname = locate( "data", "koffice/autocorrect/" + kdelang + ".xml", m_doc->instance() );
  351. if ( fname.isEmpty() && kdelang.contains("_") )
  352. {
  353. kdelang.remove( TQRegExp( "_.*" ) );
  354. fname = locate( "data", "koffice/autocorrect/" + kdelang + ".xml", m_doc->instance() );
  355. }
  356. if ( fname.isEmpty() )
  357. fname = locate( "data", "koffice/autocorrect/autocorrect.xml", m_doc->instance() );
  358. }
  359. if ( fname.isEmpty() )
  360. return;
  361. TQFile xmlFile(fname);
  362. if(!xmlFile.open(IO_ReadOnly))
  363. return;
  364. TQDomDocument doc;
  365. if(!doc.setContent(&xmlFile))
  366. return;
  367. if(doc.doctype().name() != "autocorrection") {
  368. //return;
  369. }
  370. TQDomElement de=doc.documentElement();
  371. loadAutoCorrection( de );
  372. TQDomElement upper = de.namedItem( "UpperCaseExceptions" ).toElement();
  373. if(!upper.isNull())
  374. {
  375. TQDomNodeList nl = upper.childNodes();
  376. for(uint i = 0; i < nl.count(); i++)
  377. {
  378. m_upperCaseExceptions+= nl.item(i).toElement().attribute("exception");
  379. }
  380. }
  381. TQDomElement twoUpper = de.namedItem( "TwoUpperLetterExceptions" ).toElement();
  382. if(!twoUpper.isNull())
  383. {
  384. TQDomNodeList nl = twoUpper.childNodes();
  385. for(uint i = 0; i < nl.count(); i++)
  386. {
  387. m_twoUpperLetterException+= nl.item(i).toElement().attribute("exception");
  388. }
  389. }
  390. TQDomElement superScript = de.namedItem( "SuperScript" ).toElement();
  391. if(!superScript.isNull())
  392. {
  393. TQDomNodeList nl = superScript.childNodes();
  394. for(uint i = 0; i < nl.count() ; i++) {
  395. //bug in qmap we overwrite = false doesn't work
  396. //so we can't add multiple "othernb"
  397. m_superScriptEntries.insert( nl.item(i).toElement().attribute("find"), KoAutoFormatEntry(nl.item(i).toElement().attribute("super")),FALSE );
  398. }
  399. }
  400. TQDomElement doubleQuote = de.namedItem( "DoubleQuote" ).toElement();
  401. if(!doubleQuote.isNull())
  402. {
  403. TQDomElement childItem = doubleQuote.namedItem("doublequote").toElement();
  404. if ( !childItem.isNull() )
  405. {
  406. TQString attr = childItem.attribute( "begin" );
  407. if ( !attr.isEmpty() && attr[0] != 0 )
  408. m_typographicDefaultDoubleQuotes.begin = attr[0];
  409. attr = childItem.attribute( "end" );
  410. if ( !attr.isEmpty() && attr[0] != 0 )
  411. m_typographicDefaultDoubleQuotes.end = attr[0];
  412. }
  413. }
  414. TQDomElement simpleQuote = de.namedItem( "SimpleQuote" ).toElement();
  415. if(!simpleQuote.isNull())
  416. {
  417. TQDomElement childItem = simpleQuote.namedItem("simplequote").toElement();
  418. if ( !childItem.isNull() )
  419. {
  420. TQString attr = childItem.attribute( "begin" );
  421. if ( !attr.isEmpty() && attr[0] != 0 )
  422. m_typographicDefaultSimpleQuotes.begin = attr[0];
  423. attr = childItem.attribute( "end" );
  424. if ( !attr.isEmpty() && attr[0] != 0 )
  425. m_typographicDefaultSimpleQuotes.end = attr[0];
  426. }
  427. }
  428. }
  429. void KoAutoFormat::loadAllLanguagesAutoCorrection()
  430. {
  431. TQString fname = locate( "data", "koffice/autocorrect/all_languages.xml", m_doc->instance() );
  432. if ( fname.isEmpty() )
  433. return;
  434. TQFile xmlFile( fname );
  435. if(xmlFile.open(IO_ReadOnly))
  436. {
  437. TQDomDocument doc;
  438. if(!doc.setContent(&xmlFile)) {
  439. return;
  440. }
  441. if(doc.doctype().name() != "autocorrection") {
  442. //return;
  443. }
  444. TQDomElement de=doc.documentElement();
  445. loadAutoCorrection( de, true );
  446. xmlFile.close();
  447. }
  448. }
  449. void KoAutoFormat::loadAutoCorrection( const TQDomElement & _de, bool _allLanguages )
  450. {
  451. TQDomElement item = _de.namedItem( "items" ).toElement();
  452. if(!item.isNull())
  453. {
  454. TQDomNodeList nl = item.childNodes();
  455. m_maxFindLength=nl.count();
  456. for(uint i = 0; i < m_maxFindLength; i++) {
  457. loadEntry( nl.item(i).toElement(), _allLanguages);
  458. }
  459. }
  460. }
  461. void KoAutoFormat::loadEntry( const TQDomElement &nl, bool _allLanguages)
  462. {
  463. KoAutoFormatEntry *tmp =new KoAutoFormatEntry(nl.attribute("replace"));
  464. if ( nl.hasAttribute("FONT"))
  465. {
  466. tmp->createNewEntryContext();
  467. tmp->formatEntryContext()->m_family=nl.attribute("FONT");
  468. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Family;
  469. }
  470. if ( nl.hasAttribute("SIZE" ))
  471. {
  472. tmp->createNewEntryContext();
  473. tmp->formatEntryContext()->m_size = nl.attribute("SIZE" ).toInt();
  474. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Size;
  475. }
  476. if (nl.hasAttribute("BOLD" ))
  477. {
  478. tmp->createNewEntryContext();
  479. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Bold;
  480. TQString value = nl.attribute("BOLD");
  481. if ( value.toInt() == 1 )
  482. tmp->formatEntryContext()->m_options |= KoSearchContext::Bold;
  483. }
  484. if (nl.hasAttribute("ITALIC" ))
  485. {
  486. tmp->createNewEntryContext();
  487. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Italic;
  488. TQString value = nl.attribute("ITALIC");
  489. if ( value.toInt() == 1 )
  490. tmp->formatEntryContext()->m_options |= KoSearchContext::Italic;
  491. }
  492. if (nl.hasAttribute("UNDERLINE" ))
  493. {
  494. tmp->createNewEntryContext();
  495. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Underline;
  496. TQString value = nl.attribute("UNDERLINE");
  497. if ( value =="single" )
  498. tmp->formatEntryContext()->m_underline = KoTextFormat::U_SIMPLE;
  499. else if ( value =="double" )
  500. tmp->formatEntryContext()->m_underline = KoTextFormat::U_DOUBLE;
  501. else if ( value =="single-bold" )
  502. tmp->formatEntryContext()->m_underline = KoTextFormat::U_SIMPLE_BOLD;
  503. else
  504. tmp->formatEntryContext()->m_underline = KoTextFormat::U_NONE;
  505. }
  506. if (nl.hasAttribute("STRIKEOUT" ))
  507. {
  508. tmp->createNewEntryContext();
  509. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::StrikeOut;
  510. TQString value = nl.attribute("STRIKEOUT");
  511. if ( value =="single" )
  512. tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_SIMPLE;
  513. else if ( value =="double" )
  514. tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_DOUBLE;
  515. else if ( value =="single-bold" )
  516. tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_SIMPLE_BOLD;
  517. else
  518. tmp->formatEntryContext()->m_strikeOut = KoTextFormat::S_NONE;
  519. }
  520. if (nl.hasAttribute("VERTALIGN" ))
  521. {
  522. tmp->createNewEntryContext();
  523. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::VertAlign;
  524. TQString value = nl.attribute("VERTALIGN");
  525. tmp->formatEntryContext()->m_vertAlign=static_cast<KoTextFormat::VerticalAlignment>( value.toInt() );
  526. }
  527. if ( nl.hasAttribute("TEXTCOLOR" ))
  528. {
  529. tmp->createNewEntryContext();
  530. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::Color;
  531. TQColor col( nl.attribute("TEXTCOLOR" ));
  532. tmp->formatEntryContext()->m_color = col;
  533. }
  534. if ( nl.hasAttribute("TEXTBGCOLOR" ))
  535. {
  536. tmp->createNewEntryContext();
  537. tmp->formatEntryContext()->m_optionsMask |= KoSearchContext::BgColor;
  538. TQColor col( nl.attribute("TEXTBGCOLOR" ));
  539. tmp->formatEntryContext()->m_backGroundColor = col;
  540. }
  541. if ( !_allLanguages )
  542. m_entries.insert( nl.attribute("find"), tmp );
  543. else
  544. m_allLanguages.insert( nl.attribute("find"), tmp );
  545. }
  546. void KoAutoFormat::saveConfig()
  547. {
  548. TDEConfig* config = KoGlobal::kofficeConfig();
  549. TDELocale tdelocale(m_doc->instance()->instanceName());
  550. TDEConfigGroupSaver cgs( config, "AutoFormat" );
  551. config->writeEntry( "ConvertUpperCase", m_convertUpperCase );
  552. config->writeEntry( "formatLanguage", m_autoFormatLanguage=="all_languages" ? tdelocale.languageList().front() : m_autoFormatLanguage);
  553. config->writeEntry( "ConvertUpperUpper", m_convertUpperUpper );
  554. config->writeEntry( "includeTwoLetterException", m_includeTwoUpperLetterException );
  555. config->writeEntry( "includeAbbreviation", m_includeAbbreviation );
  556. config->writeEntry( "TypographicQuotesBegin", TQString( m_typographicDoubleQuotes.begin ) );
  557. config->writeEntry( "TypographicQuotesEnd", TQString( m_typographicDoubleQuotes.end ) );
  558. config->writeEntry( "TypographicQuotesEnabled", m_typographicDoubleQuotes.replace );
  559. config->writeEntry( "TypographicSimpleQuotesBegin", TQString( m_typographicSimpleQuotes.begin ) );
  560. config->writeEntry( "TypographicSimpleQuotesEnd", TQString( m_typographicSimpleQuotes.end ) );
  561. config->writeEntry( "TypographicSimpleQuotesEnabled", m_typographicSimpleQuotes.replace );
  562. config->writeEntry( "AdvancedAutocorrect", m_advancedAutoCorrect );
  563. config->writeEntry( "AutoCorrectionWithFormat", m_bAutoCorrectionWithFormat );
  564. config->writeEntry( "CapitalizeNameOfDays", m_bCapitalizeNameOfDays );
  565. config->writeEntry( "AutoDetectUrl",m_autoDetectUrl);
  566. config->writeEntry( "IgnoreDoubleSpace",m_ignoreDoubleSpace );
  567. config->writeEntry( "RemoveSpaceBeginEndLine",m_removeSpaceBeginEndLine );
  568. config->writeEntry( "UseBulletStyle", m_useBulletStyle);
  569. config->writeEntry( "BulletStyle", TQString(m_bulletStyle));
  570. config->writeEntry( "AutoChangeFormat", m_autoChangeFormat);
  571. config->writeEntry( "AutoReplaceNumber", m_autoReplaceNumber);
  572. config->writeEntry( "AutoNumberStyle", m_useAutoNumberStyle );
  573. config->writeEntry( "AutoSuperScript", m_bAutoSuperScript );
  574. config->setGroup( "completion" );
  575. config->writeEntry( "completion", m_completion );
  576. config->writeEntry( "CompletionAppendSpace", m_completionAppendSpace );
  577. config->writeEntry( "CompletionMinWordLength", m_minCompletionWordLength);
  578. config->writeEntry( "NbMaxCompletionWord", m_nbMaxCompletionWord);
  579. config->writeEntry( "AddCompletionWord", m_addCompletionWord );
  580. config->writeEntry( "ToolTipCompletion", m_toolTipCompletion );
  581. config->writeEntry( "CompletionKeyAction", ( int )m_keyCompletionAction );
  582. config->setGroup( "AutoFormatEntries" );
  583. TQDictIterator<KoAutoFormatEntry> it( m_entries );
  584. //refresh m_maxFindLength
  585. m_maxFindLength=0;
  586. TQDomDocument doc("autocorrection");
  587. TQDomElement begin = doc.createElement( "Word" );
  588. doc.appendChild( begin );
  589. TQDomElement items;
  590. items = doc.createElement("items");
  591. TQDomElement data;
  592. for ( ; it.current() ; ++it )
  593. {
  594. items.appendChild(saveEntry( it, doc));
  595. //m_maxFindLength=TQMAX(m_maxFindLength,it.currentKey().length());
  596. }
  597. buildMaxLen();
  598. begin.appendChild(items);
  599. TQDomElement upper;
  600. upper = doc.createElement("UpperCaseExceptions");
  601. for ( TQStringList::Iterator it = m_upperCaseExceptions.begin(); it != m_upperCaseExceptions.end();++it )
  602. {
  603. data = doc.createElement("word");
  604. data.setAttribute("exception",(*it) );
  605. upper.appendChild(data);
  606. }
  607. begin.appendChild(upper);
  608. TQDomElement twoUpper;
  609. twoUpper = doc.createElement("TwoUpperLetterExceptions");
  610. for ( TQStringList::Iterator it = m_twoUpperLetterException.begin(); it != m_twoUpperLetterException.end();++it )
  611. {
  612. data = doc.createElement("word");
  613. data.setAttribute("exception",(*it) );
  614. twoUpper.appendChild(data);
  615. }
  616. begin.appendChild(twoUpper);
  617. TQDomElement super;
  618. super = doc.createElement("SuperScript");
  619. KoAutoFormatEntryMap::Iterator it2 = m_superScriptEntries.begin();
  620. for ( ; it2 != m_superScriptEntries.end() ; ++it2 )
  621. {
  622. data = doc.createElement("superscript");
  623. data.setAttribute("find", it2.key());
  624. data.setAttribute("super", it2.data().replace());
  625. super.appendChild(data);
  626. }
  627. begin.appendChild(super);
  628. TQDomElement doubleQuote;
  629. doubleQuote = doc.createElement("DoubleQuote");
  630. data = doc.createElement("doublequote");
  631. data.setAttribute("begin", TQString(m_typographicDefaultDoubleQuotes.begin));
  632. data.setAttribute("end", TQString(m_typographicDefaultDoubleQuotes.end));
  633. doubleQuote.appendChild(data);
  634. begin.appendChild(doubleQuote);
  635. TQDomElement simpleQuote;
  636. simpleQuote = doc.createElement("SimpleQuote");
  637. data = doc.createElement("simplequote");
  638. data.setAttribute("begin", TQString(m_typographicDefaultSimpleQuotes.begin));
  639. data.setAttribute("end", TQString(m_typographicDefaultSimpleQuotes.end));
  640. simpleQuote.appendChild(data);
  641. begin.appendChild(simpleQuote);
  642. TQFile f;
  643. if ( m_autoFormatLanguage.isEmpty())
  644. f.setName(locateLocal("data", "koffice/autocorrect/"+tdelocale.languageList().front() + ".xml",m_doc->instance()));
  645. else
  646. f.setName(locateLocal("data", "koffice/autocorrect/"+m_autoFormatLanguage + ".xml",m_doc->instance()));
  647. if(!f.open(IO_WriteOnly)) {
  648. kdWarning()<<"Error during saving autoformat to " << f.name() << endl;
  649. return;
  650. }
  651. TQTextStream ts(&f);
  652. doc.save(ts, 2);
  653. f.close();
  654. autoFormatIsActive();
  655. config->sync();
  656. }
  657. TQDomElement KoAutoFormat::saveEntry( TQDictIterator<KoAutoFormatEntry> _entry, TQDomDocument doc)
  658. {
  659. TQDomElement data;
  660. data = doc.createElement("item");
  661. data.setAttribute("find", _entry.currentKey());
  662. data.setAttribute("replace", _entry.current()->replace());
  663. if ( _entry.current()->formatEntryContext() )
  664. {
  665. KoSearchContext *tmp = _entry.current()->formatEntryContext();
  666. if ( tmp->m_optionsMask & KoSearchContext::Family )
  667. {
  668. data.setAttribute("FONT", tmp->m_family);
  669. }
  670. if ( tmp->m_optionsMask & KoSearchContext::Size )
  671. {
  672. data.setAttribute("SIZE", tmp->m_size);
  673. }
  674. if ( tmp->m_optionsMask & KoSearchContext::Italic )
  675. {
  676. data.setAttribute("ITALIC", static_cast<bool>(tmp->m_options & KoSearchContext::Italic));
  677. }
  678. if ( tmp->m_optionsMask & KoSearchContext::Bold )
  679. {
  680. data.setAttribute("BOLD", static_cast<bool>(tmp->m_options & KoSearchContext::Bold));
  681. }
  682. if ( tmp->m_optionsMask & KoSearchContext::Shadow )
  683. {
  684. data.setAttribute("SHADOWTEXT", static_cast<bool>(tmp->m_options & KoSearchContext::Shadow));
  685. }
  686. if ( tmp->m_optionsMask & KoSearchContext::WordByWord )
  687. {
  688. data.setAttribute("WORDBYWORD", static_cast<bool>(tmp->m_options & KoSearchContext::WordByWord));
  689. }
  690. if ( tmp->m_optionsMask & KoSearchContext::Underline )
  691. {
  692. switch( tmp->m_underline )
  693. {
  694. case KoTextFormat::U_SIMPLE:
  695. data.setAttribute("UNDERLINE", "single");
  696. break;
  697. case KoTextFormat::U_DOUBLE:
  698. data.setAttribute("UNDERLINE", "double");
  699. break;
  700. case KoTextFormat::U_SIMPLE_BOLD:
  701. data.setAttribute("UNDERLINE", "single-bold");
  702. break;
  703. case KoTextFormat::U_WAVE:
  704. data.setAttribute("UNDERLINE", "wave");
  705. break;
  706. case KoTextFormat::U_NONE:
  707. data.setAttribute("UNDERLINE", "none");
  708. break;
  709. }
  710. }
  711. if ( tmp->m_optionsMask & KoSearchContext::StrikeOut )
  712. {
  713. switch( tmp->m_strikeOut )
  714. {
  715. case KoTextFormat::S_SIMPLE:
  716. data.setAttribute("STRIKEOUT", "single");
  717. break;
  718. case KoTextFormat::S_DOUBLE:
  719. data.setAttribute("STRIKEOUT", "double");
  720. break;
  721. case KoTextFormat::S_NONE:
  722. data.setAttribute("STRIKEOUT", "none");
  723. break;
  724. case KoTextFormat::S_SIMPLE_BOLD:
  725. data.setAttribute("STRIKEOUT", "single-bold");
  726. break;
  727. }
  728. }
  729. if ( tmp->m_optionsMask & KoSearchContext::Attribute )
  730. {
  731. data.setAttribute("FONTATTRIBUTE", KoTextFormat::attributeFontToString( tmp->m_attribute ) );
  732. }
  733. if ( tmp->m_optionsMask & KoSearchContext::VertAlign)
  734. {
  735. data.setAttribute( "VERTALIGN", static_cast<int>(tmp->m_vertAlign) );
  736. }
  737. if ( tmp->m_optionsMask & KoSearchContext::BgColor )
  738. {
  739. data.setAttribute( "TEXTCOLOR", tmp->m_color.name());
  740. }
  741. if ( tmp->m_optionsMask & KoSearchContext::Color )
  742. {
  743. data.setAttribute( "TEXTCOLOR", tmp->m_color.name());
  744. }
  745. if ( tmp->m_optionsMask & KoSearchContext::BgColor )
  746. {
  747. data.setAttribute( "TEXTBGCOLOR", tmp->m_backGroundColor.name());
  748. }
  749. if ( tmp->m_optionsMask & KoSearchContext::Language )
  750. data.setAttribute( "LANGUAGE", tmp->m_language );
  751. }
  752. return data;
  753. }
  754. void KoAutoFormat::addAutoFormatEntry( const TQString &key, const TQString &replace )
  755. {
  756. KoAutoFormatEntry *findEntry = m_entries.find( key);
  757. if ( findEntry )
  758. {
  759. if ( findEntry->replace().lower() == replace.lower() )
  760. return;
  761. }
  762. KoAutoFormatEntry *tmp = new KoAutoFormatEntry( replace );
  763. m_entries.insert( key, tmp );
  764. saveConfig();
  765. buildMaxLen();
  766. }
  767. TQString KoAutoFormat::getLastWord(KoTextParag *parag, int const index)
  768. {
  769. TQString lastWord;
  770. KoTextString *s = parag->string();
  771. for ( int i = index - 1; i >= 0; --i )
  772. {
  773. TQChar ch = s->at( i ).c;
  774. if ( ch.isSpace() || ch.isPunct() )
  775. break;
  776. lastWord.prepend( ch );
  777. }
  778. return lastWord;
  779. }
  780. TQString KoAutoFormat::getLastWord(const int max_words, KoTextParag *parag, int const index)
  781. {
  782. TQString lastWord;
  783. KoTextString const *s = parag->string();
  784. int words = 0;
  785. for ( int i = index - 1; i >= 0; --i )
  786. {
  787. TQChar ch = s->at( i ).c;
  788. if ( ch.isSpace() || ch.isPunct() )
  789. {
  790. ++words;
  791. if (words >= max_words)
  792. break;
  793. }
  794. lastWord.prepend( ch );
  795. }
  796. return lastWord;
  797. }
  798. TQString KoAutoFormat::getWordAfterSpace(KoTextParag *parag, int const index)
  799. {
  800. TQString word;
  801. KoTextString *s = parag->string();
  802. for ( int i = index - 1; i >= 0; --i )
  803. {
  804. TQChar ch = s->at( i ).c;
  805. if ( ch.isSpace() )
  806. break;
  807. word.prepend( ch );
  808. }
  809. return word;
  810. }
  811. bool KoAutoFormat::doCompletion( KoTextCursor* textEditCursor, KoTextParag *parag, int const index, KoTextObject *txtObj )
  812. {
  813. if( m_completion )
  814. {
  815. bool part=false;
  816. TQString lastWord, word;
  817. if (m_completionBox && m_completionBox->isShown() ) //word completion with the tool-tip box
  818. {
  819. word = m_completionBox->text();
  820. lastWord = m_completionBox->lastWord();
  821. }
  822. else
  823. {
  824. TQStringList wordlist, new_wordlist;
  825. for (uint i=1; i <= m_countMaxWords; i++ )
  826. {
  827. lastWord = getLastWord(i, parag, index+1);
  828. wordlist += m_listCompletion->substringCompletion( lastWord ); //find all completion words that contains lastWord
  829. }
  830. uint maxlength = 0;
  831. for ( TQStringList::ConstIterator it = wordlist.begin(); it != wordlist.end(); ++it ) // several completion words were found
  832. {
  833. if ( (*it).startsWith( lastWord, false ) && new_wordlist.find(*it) == new_wordlist.end() ) //the completion words that begin with lastWord
  834. {
  835. if ( (*it).length() > maxlength )
  836. maxlength = (*it).length();
  837. new_wordlist.append(*it);
  838. //kdDebug() << "adding word completion:" << *it << endl;
  839. }
  840. }
  841. if ( new_wordlist.isEmpty() )
  842. return false;
  843. if ( new_wordlist.count() == 1 ) // only one completion word was found
  844. word = new_wordlist.first();
  845. else
  846. {
  847. //we must extract the common part of the completions
  848. for (uint i = lastWord.length(); i<maxlength && !part; i++) //iterate through all completion words
  849. {
  850. TQChar ch = new_wordlist.first().at(i);
  851. for (TQStringList::ConstIterator it = new_wordlist.begin(); it != new_wordlist.end(); ++it )
  852. {
  853. if ( (*it).at(i).lower() != ch.lower() )
  854. {
  855. word = (*it).left(i); //the completion word is truncated here
  856. //kdDebug() << "set the word completion to:" << word << endl;
  857. part=true; // completion of a part of a word; a space-character after the completion should not be inserted
  858. break;
  859. }
  860. }
  861. }
  862. }
  863. if (word == lastWord)
  864. return false;
  865. word=lastWord+word.right(word.length()-lastWord.length() );
  866. }
  867. if( !word.isEmpty() )
  868. {
  869. int const lastword_length = lastWord.length();
  870. int const start = index+1 - lastword_length;
  871. int const length = word.length();
  872. KMacroCommand *macro = new KMacroCommand( i18n("Completion Word"));
  873. KoTextCursor cursor( parag->document() );
  874. cursor.setParag( parag );
  875. cursor.setIndex( start );
  876. KoTextDocument * textdoc = parag->textDocument();
  877. if( m_completionAppendSpace && !part)
  878. word+=" ";
  879. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  880. cursor.setIndex( start + lastword_length );
  881. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  882. macro->addCommand( txtObj->replaceSelectionCommand( textEditCursor, word,
  883. i18n("Completion Word"),
  884. KoTextDocument::HighlightSelection ));
  885. if ( m_completionAppendSpace && !m_ignoreUpperCase && (m_convertUpperUpper || m_convertUpperCase) && !part)
  886. {
  887. //find the first word
  888. for (uint i=1; i < word.length(); i++)
  889. if ( word.at(i).isSpace() || word.at(i).isPunct() )
  890. {
  891. word.truncate(i);
  892. break;
  893. }
  894. int const newPos = start + word.length();// + index - 3;
  895. KCommand *cmd = doUpperCase( textEditCursor, parag, newPos, word, txtObj );
  896. if( cmd )
  897. macro->addCommand( cmd );
  898. txtObj->emitHideCursor();
  899. textEditCursor->setIndex(start+ length+1);
  900. }
  901. else
  902. {
  903. txtObj->emitHideCursor();
  904. textEditCursor->setIndex(start+ length);
  905. }
  906. txtObj->emitNewCommand( macro );
  907. // The space/tab/CR that we inserted is still there but delete/insert moved the cursor
  908. // -> go right
  909. txtObj->emitShowCursor();
  910. removeToolTipCompletion();
  911. return true;
  912. }
  913. }
  914. return false;
  915. }
  916. bool KoAutoFormat::doToolTipCompletion( KoTextCursor* textEditCursor, KoTextParag *parag, int index, KoTextObject *txtObj, int keyPressed )
  917. {
  918. if( m_completion && m_toolTipCompletion && m_completionBox && m_completionBox->isShown() )
  919. {
  920. if ( ( keyPressed == TQt::Key_Return && m_keyCompletionAction==Enter )
  921. || ( keyPressed == TQt::Key_Enter && m_keyCompletionAction==Enter )
  922. || ( keyPressed == TQt::Key_Tab && m_keyCompletionAction==Tab )
  923. || ( keyPressed == TQt::Key_Space && m_keyCompletionAction==Space )
  924. || ( keyPressed == TQt::Key_End && m_keyCompletionAction==End )
  925. || ( keyPressed == TQt::Key_Right && m_keyCompletionAction==Right ))
  926. {
  927. return doCompletion(textEditCursor, parag, index, txtObj);
  928. }
  929. }
  930. return false;
  931. }
  932. void KoAutoFormat::showToolTipBox(KoTextParag *parag, int index, TQWidget *widget, const TQPoint &pos )
  933. {
  934. if( m_completion && m_toolTipCompletion)
  935. {
  936. TQString lastWord, word;
  937. for (uint i=1; i <= m_countMaxWords; i++ )
  938. {
  939. lastWord = getLastWord(i, parag, index+1);
  940. word=m_listCompletion->makeCompletion( lastWord );
  941. if ( !word.isEmpty())
  942. break;
  943. }
  944. if( !word.isEmpty() && word!=lastWord )
  945. {
  946. uint const length = lastWord.length();
  947. if (length<=3)
  948. return;
  949. word=lastWord+word.right(word.length()-length);
  950. if (!m_completionBox)
  951. m_completionBox = new KoCompletionBox(0,0,TQt::WType_Popup);
  952. TQPoint const show_pos = widget->mapToGlobal(pos);
  953. m_completionBox->setText(word);
  954. m_completionBox->setLastWord(lastWord);
  955. m_completionBox->adjustSize();
  956. int const height = m_completionBox->sizeHint().height();
  957. m_completionBox->move( show_pos.x(), show_pos.y() - height );
  958. if (!m_completionBox->isShown() )
  959. {
  960. m_completionBox->show();
  961. widget->setFocus();
  962. }
  963. }
  964. else
  965. removeToolTipCompletion();
  966. }
  967. }
  968. void KoAutoFormat::removeToolTipCompletion()
  969. {
  970. if (m_completion && m_toolTipCompletion && m_completionBox && m_completionBox->isShown())
  971. m_completionBox->hide();
  972. }
  973. void KoAutoFormat::autoFormatIsActive()
  974. {
  975. m_bAutoFormatActive = m_useBulletStyle ||
  976. m_removeSpaceBeginEndLine ||
  977. m_autoDetectUrl ||
  978. m_convertUpperUpper ||
  979. m_convertUpperCase ||
  980. m_autoReplaceNumber ||
  981. m_autoChangeFormat ||
  982. m_completion ||
  983. m_typographicDoubleQuotes.replace ||
  984. m_typographicSimpleQuotes.replace ||
  985. m_entries.count()!=0 ||
  986. m_allLanguages.count()!=0;
  987. }
  988. void KoAutoFormat::doAutoFormat( KoTextCursor* textEditCursor, KoTextParag *parag, int index, TQChar ch,KoTextObject *txtObj )
  989. {
  990. m_ignoreUpperCase = false;
  991. if ( !m_configRead )
  992. readConfig();
  993. if ( !m_bAutoFormatActive )
  994. return;
  995. if( ch.isSpace())
  996. {
  997. //a link doesn't have a space
  998. //=>m_ignoreUpperCase = false
  999. //m_ignoreUpperCase=false;
  1000. TQString word=getWordAfterSpace(parag,index);
  1001. if ( m_autoChangeFormat && index > 3)
  1002. {
  1003. KCommand *cmd =doAutoChangeFormat( textEditCursor, parag, index, word, txtObj );
  1004. if ( cmd )
  1005. txtObj->emitNewCommand( cmd );
  1006. }
  1007. if ( m_autoReplaceNumber )
  1008. {
  1009. KCommand *cmd = doAutoReplaceNumber( textEditCursor, parag, index, word, txtObj );
  1010. if ( cmd )
  1011. txtObj->emitNewCommand( cmd );
  1012. }
  1013. }
  1014. if( ch =='\n' )
  1015. {
  1016. if( m_removeSpaceBeginEndLine && index > 1)
  1017. {
  1018. KCommand *cmd = doRemoveSpaceBeginEndLine( textEditCursor, parag, txtObj, index );
  1019. if ( cmd )
  1020. txtObj->emitNewCommand( cmd );
  1021. }
  1022. if( m_useBulletStyle && index > 3)
  1023. {
  1024. KCommand *cmd =doUseBulletStyle( textEditCursor, parag, txtObj, index );
  1025. if ( cmd )
  1026. txtObj->emitNewCommand( cmd );
  1027. }
  1028. if( m_useAutoNumberStyle && index > 3 )
  1029. {
  1030. KCommand *cmd =doUseNumberStyle( textEditCursor, parag, txtObj, index );
  1031. if ( cmd )
  1032. txtObj->emitNewCommand( cmd );
  1033. }
  1034. if( m_convertUpperUpper && m_includeTwoUpperLetterException )
  1035. doAutoIncludeUpperUpper(textEditCursor, parag, txtObj );
  1036. if( m_convertUpperCase && m_includeAbbreviation )
  1037. doAutoIncludeAbbreviation(textEditCursor, parag, txtObj );
  1038. }
  1039. //kdDebug(32500) << "KoAutoFormat::doAutoFormat ch=" << TQString(ch) << endl;
  1040. //if ( !m_enabled )
  1041. // return;
  1042. // Auto-correction happens when pressing space, tab, CR, punct etc.
  1043. if ( (ch.isSpace() || ch==':' || ch=='?' || ch=='!' || ch==',' || (m_advancedAutoCorrect && ch=='.') ) && index > 0 )
  1044. {
  1045. KCommand *cmd = 0L;
  1046. KMacroCommand *macro = 0L;
  1047. TQString lastWord = getWordAfterSpace(parag, index);
  1048. //kdDebug(32500) << "KoAutoFormat::doAutoFormat lastWord=" << lastWord << endl;
  1049. if ( ch == '.')
  1050. detectStartOfLink( parag, index, true );
  1051. else
  1052. detectStartOfLink( parag, index, false );
  1053. if ( !m_wordInserted && m_advancedAutoCorrect && !m_ignoreUpperCase)
  1054. {
  1055. int const completionBeginPos = index -lastWord.length();
  1056. int newPos = index;
  1057. cmd = doAutoCorrect( textEditCursor, parag, newPos, txtObj );
  1058. if( cmd )
  1059. {
  1060. if (!macro)
  1061. macro = new KMacroCommand(i18n("Autocorrection"));
  1062. macro->addCommand( cmd );
  1063. }
  1064. int const endPos=textEditCursor->index();
  1065. bool was_a_replacement;
  1066. if (index == newPos)
  1067. was_a_replacement = false;
  1068. else
  1069. was_a_replacement = true;
  1070. if( was_a_replacement) // a replacement took place
  1071. {
  1072. txtObj->emitHideCursor();
  1073. if(endPos==0) //new line, the user pressed enter
  1074. {
  1075. textEditCursor->gotoUp();
  1076. textEditCursor->gotoLineEnd();
  1077. newPos=textEditCursor->index();
  1078. }
  1079. else
  1080. newPos= endPos-1;
  1081. m_wordInserted = true; //don't allow other replacements in this replacement
  1082. for(int i=completionBeginPos; i<newPos;i++)
  1083. {
  1084. textEditCursor->setIndex(i);
  1085. doAutoFormat( textEditCursor, parag, i, parag->toString().at(i),txtObj );
  1086. }
  1087. textEditCursor->setIndex(newPos);
  1088. doAutoFormat( textEditCursor, parag, newPos, ch,txtObj );
  1089. m_wordInserted = false;
  1090. if (endPos==0)
  1091. {
  1092. textEditCursor->gotoLineStart();
  1093. textEditCursor->gotoDown();
  1094. }
  1095. else
  1096. textEditCursor->setIndex(newPos+1);
  1097. txtObj->emitShowCursor();
  1098. return;
  1099. }
  1100. }
  1101. if (!m_ignoreUpperCase && m_bCapitalizeNameOfDays)
  1102. {
  1103. KCommand *cmd = doCapitalizeNameOfDays( textEditCursor, parag, index, lastWord, txtObj );
  1104. if( cmd )
  1105. {
  1106. if (!macro)
  1107. macro = new KMacroCommand(i18n("Autocorrection"));
  1108. macro->addCommand( cmd );
  1109. m_ignoreUpperCase = true;
  1110. }
  1111. }
  1112. if (ch=='.')
  1113. return;
  1114. //kdDebug(32500)<<" m_listCompletion->items() :"<<m_listCompletion->items()<<endl;
  1115. if( !m_ignoreUpperCase && m_completion && m_addCompletionWord && m_listCompletion->items().count() < m_nbMaxCompletionWord )
  1116. {
  1117. TQString completionWord("");
  1118. TQChar ch;
  1119. for (uint i=0;i<lastWord.length();i++)
  1120. {
  1121. ch = lastWord.at(i);
  1122. if (ch.isPunct() && ch!='-' && ch!='=' )
  1123. {
  1124. if (completionWord.at(0) == '-')
  1125. completionWord.remove(0,1);
  1126. if (completionWord.length()>= m_minCompletionWordLength && !completionWord.isEmpty() && m_listCompletion->makeCompletion(completionWord).isEmpty())
  1127. {
  1128. kdDebug() << "Adding:" << completionWord << endl;
  1129. m_listCompletion->addItem( completionWord );
  1130. if ( completionWord.length() > m_countMaxWords )
  1131. m_countMaxWords = completionWord.length();
  1132. }
  1133. completionWord = "";
  1134. }
  1135. else
  1136. {
  1137. completionWord.append(ch);
  1138. if (i==lastWord.length()-1)
  1139. {
  1140. if (completionWord.at(0) == '-')
  1141. completionWord.remove(0,1);
  1142. if (completionWord.at(completionWord.length()-1) == '-')
  1143. completionWord.truncate(completionWord.length()-1);
  1144. completionWord.remove('=');
  1145. if (completionWord.length()>= m_minCompletionWordLength && !completionWord.isEmpty() && m_listCompletion->makeCompletion(completionWord).isEmpty())
  1146. {
  1147. kdDebug() << "Adding:" << completionWord << endl;
  1148. m_listCompletion->addItem( completionWord );
  1149. if ( completionWord.length() > m_countMaxWords )
  1150. m_countMaxWords = completionWord.length();
  1151. }
  1152. }
  1153. }
  1154. }
  1155. }
  1156. if( m_autoDetectUrl && m_ignoreUpperCase && (ch!='?' || lastWord.at(lastWord.length()-1)=='?') )
  1157. {
  1158. doAutoDetectUrl( textEditCursor, parag, index, lastWord, txtObj );
  1159. //textEditCursor->gotoRight();
  1160. }
  1161. if (!m_ignoreUpperCase && (m_convertUpperUpper || m_convertUpperCase) )
  1162. {
  1163. cmd = doUpperCase( textEditCursor, parag, index, lastWord, txtObj );
  1164. if( cmd )
  1165. {
  1166. if (!macro)
  1167. macro = new KMacroCommand(i18n("Autocorrection"));
  1168. macro->addCommand( cmd );
  1169. }
  1170. }
  1171. if ( macro )
  1172. txtObj->emitNewCommand( macro );
  1173. if(!m_ignoreUpperCase && m_bAutoSuperScript && m_superScriptEntries.count()>0)
  1174. {
  1175. if( lastWord.at(0).isPunct() )
  1176. lastWord.remove(0,1);
  1177. KCommand * cmd = doAutoSuperScript( textEditCursor, parag, index, lastWord, txtObj );
  1178. if ( cmd )
  1179. txtObj->emitNewCommand( cmd );
  1180. }
  1181. }
  1182. else
  1183. {
  1184. if ( ch == '"' && m_typographicDoubleQuotes.replace )
  1185. {
  1186. KCommand *cmd = doTypographicQuotes( textEditCursor, parag, index, txtObj, true /*double quote*/ );
  1187. if ( cmd )
  1188. txtObj->emitNewCommand( cmd );
  1189. }
  1190. else if ( ch == '\'' && m_typographicDoubleQuotes.replace )
  1191. {
  1192. KCommand *cmd = doTypographicQuotes( textEditCursor, parag, index, txtObj, false /* simple quote*/ );
  1193. if ( cmd )
  1194. txtObj->emitNewCommand( cmd );
  1195. }
  1196. }
  1197. }
  1198. KCommand *KoAutoFormat::doAutoCorrect( KoTextCursor* textEditCursor, KoTextParag *parag, int &index, KoTextObject *txtObj )
  1199. {
  1200. //if(!m_advancedAutoCorrect)
  1201. // return 0L;
  1202. // Prepare an array with words of different lengths, all terminating at "index".
  1203. // Obviously only full words are put into the array
  1204. // But this allows 'find strings' with spaces and punctuation in them.
  1205. TQString * wordArray = new TQString[m_maxFindLength+1];
  1206. {
  1207. TQString word;
  1208. KoTextString *s = parag->string();
  1209. for ( int i = index - 1; i >= 0; --i )
  1210. {
  1211. TQChar ch = s->at( i ).c;
  1212. // It's necessary to stop at spaces - #99063
  1213. if ( ch.isSpace() /*|| ch.isPunct()*/ || i==0)
  1214. {
  1215. if(i==0 && word.length()<m_maxFindLength)
  1216. word.prepend( ch );
  1217. wordArray[word.length()]=word;
  1218. }
  1219. word.prepend( ch );
  1220. if (((index - 1)-i) == (int)m_maxFindLength)
  1221. break;
  1222. }
  1223. }
  1224. KCommand *cmd = autoFormatWord( textEditCursor, parag, index, txtObj, wordArray, false );
  1225. if ( !cmd )
  1226. cmd = autoFormatWord( textEditCursor, parag, index, txtObj, wordArray, true );
  1227. delete [] wordArray;
  1228. return cmd;
  1229. }
  1230. KCommand *KoAutoFormat::autoFormatWord( KoTextCursor* textEditCursor, KoTextParag *parag, int &index, KoTextObject *txtObj, TQString * _wordArray, bool _allLanguages )
  1231. {
  1232. KoTextDocument * textdoc = parag->textDocument();
  1233. // Now for each entry in the autocorrect list, look if
  1234. // the word of the same size in wordArray matches.
  1235. // This allows an o(n) behaviour instead of an o(n^2).
  1236. for(int i=m_maxFindLength;i>0;--i)
  1237. {
  1238. if ( !_wordArray[i].isEmpty())
  1239. {
  1240. KoAutoFormatEntry* it = 0L;
  1241. if ( _allLanguages )
  1242. it = m_allLanguages[ _wordArray[i] ];
  1243. else
  1244. it = m_entries[ _wordArray[i] ];
  1245. if ( _wordArray[i]!=0 && it )
  1246. {
  1247. unsigned int length = _wordArray[i].length();
  1248. int const start = index - length;
  1249. KoTextCursor cursor( parag->document() );
  1250. cursor.setParag( parag );
  1251. cursor.setIndex( start );
  1252. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1253. cursor.setIndex( start + length );
  1254. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1255. KCommand *cmd = 0L;
  1256. kdDebug()<<"it->replace() :"<<it->replace()<<endl;
  1257. if (!it->formatEntryContext() || !m_bAutoCorrectionWithFormat)
  1258. {
  1259. cmd = txtObj->replaceSelectionCommand( textEditCursor, it->replace(),
  1260. i18n("Autocorrect Word"),
  1261. KoTextDocument::HighlightSelection );
  1262. }
  1263. else
  1264. {
  1265. int flags = 0;
  1266. KoTextFormat * lastFormat = parag->at( start )->format();
  1267. KoTextFormat * newFormat = new KoTextFormat(*lastFormat);
  1268. changeTextFormat(it->formatEntryContext(), newFormat, flags );
  1269. KMacroCommand *macro = new KMacroCommand( i18n("Autocorrect Word with Format"));
  1270. KCommand *cmd2=txtObj->replaceSelectionCommand( textEditCursor, it->replace(),
  1271. i18n("Autocorrect Word"),
  1272. KoTextDocument::HighlightSelection );
  1273. if ( cmd2 )
  1274. macro->addCommand(cmd2);
  1275. KoTextCursor cursor( parag->document() );
  1276. cursor.setParag( parag );
  1277. cursor.setIndex( start );
  1278. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1279. cursor.setIndex( start + it->replace().length()/*+ length + 1*/ );
  1280. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1281. cmd2 =txtObj->setFormatCommand( textEditCursor, &lastFormat, newFormat, flags, false, KoTextDocument::HighlightSelection );
  1282. macro->addCommand( cmd2);
  1283. index = index - length + it->replace().length();
  1284. textEditCursor->setIndex(index+1);
  1285. cmd2 =txtObj->setFormatCommand( textEditCursor, &newFormat, lastFormat, 0 );
  1286. macro->addCommand( cmd2);
  1287. parag->at( index+1 )->setFormat(lastFormat);
  1288. cmd = macro;
  1289. txtObj->emitHideCursor();
  1290. textEditCursor->gotoRight();
  1291. txtObj->emitShowCursor();
  1292. return cmd;
  1293. }
  1294. // The space/tab/CR that we inserted is still there but delete/insert moved the cursor
  1295. // -> go right
  1296. txtObj->emitHideCursor();
  1297. textEditCursor->gotoRight();
  1298. txtObj->emitShowCursor();
  1299. index = index - length + it->replace().length();
  1300. return cmd;
  1301. }
  1302. }
  1303. }
  1304. return 0L;
  1305. }
  1306. KCommand *KoAutoFormat::doTypographicQuotes( KoTextCursor* textEditCursor, KoTextParag *parag, int index, KoTextObject *txtObj, bool doubleQuotes )
  1307. {
  1308. //kdDebug(32500) << "KoAutoFormat::doTypographicQuotes" << endl;
  1309. KoTextDocument * textdoc = parag->textDocument();
  1310. KoTextCursor cursor( parag->document() );
  1311. cursor.setParag( parag );
  1312. cursor.setIndex( index );
  1313. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1314. cursor.setIndex( index + 1 );
  1315. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1316. // Need to determine if we want a starting or ending quote.
  1317. // we use a starting quote in three cases:
  1318. // 1. if the previous character is a space
  1319. // 2. if the previous character is some kind of opening punctuation (e.g., "(", "[", or "{")
  1320. // a. and the character before that is not an opening quote (so that we get quotations of single characters
  1321. // right)
  1322. // 3. if the previous character is an opening quote (so that we get nested quotations right)
  1323. // a. and the character before that is not an opening quote (so that we get quotations of single characters
  1324. // right)
  1325. // b. and the previous quote of a different kind (so that we get empty quotations right)
  1326. TQString replacement;
  1327. bool ending = true;
  1328. if( index > 0 )
  1329. {
  1330. TQChar::Category c1 = parag->at( index - 1 )->c.category();
  1331. // case 1 and 2
  1332. if ( c1 == TQChar::Separator_Space || c1 == TQChar::Separator_Line || c1 == TQChar::Separator_Paragraph ||
  1333. c1 == TQChar::Punctuation_Open || c1 == TQChar::Other_Control )
  1334. ending = false;
  1335. // case 3
  1336. if ( c1 == TQChar::Punctuation_InitialQuote )
  1337. {
  1338. TQChar openingQuote;
  1339. if( doubleQuotes )
  1340. openingQuote = m_typographicDoubleQuotes.begin;
  1341. else
  1342. openingQuote = m_typographicSimpleQuotes.begin;
  1343. // case 3b
  1344. if( parag->at( index - 1 )->c != openingQuote )
  1345. ending = false;
  1346. }
  1347. }
  1348. // cases 2a and 3a
  1349. if( index > 1 && !ending )
  1350. {
  1351. TQChar::Category c2 = parag->at( index - 2 )->c.category();
  1352. ending = (c2 == TQChar::Punctuation_InitialQuote);
  1353. }
  1354. if( ending )
  1355. {
  1356. if( doubleQuotes )
  1357. replacement = m_typographicDoubleQuotes.end;
  1358. else
  1359. replacement = m_typographicSimpleQuotes.end;
  1360. }
  1361. else
  1362. {
  1363. if( doubleQuotes )
  1364. replacement = m_typographicDoubleQuotes.begin;
  1365. else
  1366. replacement = m_typographicSimpleQuotes.begin;
  1367. }
  1368. return txtObj->replaceSelectionCommand( textEditCursor, replacement,
  1369. i18n("Typographic Quote"),
  1370. KoTextDocument::HighlightSelection );
  1371. }
  1372. KCommand * KoAutoFormat::doUpperCase( KoTextCursor *textEditCursor, KoTextParag *parag,
  1373. int index, const TQString & word, KoTextObject *txtObj )
  1374. {
  1375. KoTextDocument * textdoc = parag->textDocument();
  1376. unsigned int length = word.length();
  1377. if (word.at(length-1) == '.' )
  1378. {
  1379. --index;
  1380. --length;
  1381. }
  1382. int const start = index - length;
  1383. KoTextCursor backCursor( parag->document() );
  1384. backCursor.setParag( parag );
  1385. backCursor.setIndex( start );
  1386. // backCursor now points at the first char of the word
  1387. TQChar const firstChar = backCursor.parag()->at( backCursor.index() )->c;
  1388. bool bNeedMove = false;
  1389. KCommand *cmd = 0L;
  1390. if ( m_convertUpperCase && isLower( firstChar ) )
  1391. {
  1392. bool beginningOfSentence = true; // true if beginning of text
  1393. // Go back over any space/tab/CR
  1394. while ( backCursor.index() > 0 || backCursor.parag()->prev() )
  1395. {
  1396. beginningOfSentence = false; // we could go back -> false unless we'll find '.'
  1397. backCursor.gotoLeft();
  1398. if ( !backCursor.parag()->at( backCursor.index() )->c.isSpace() )
  1399. break;
  1400. }
  1401. // We are now at the first non-space char before the word
  1402. if ( !beginningOfSentence )
  1403. beginningOfSentence = isMark( backCursor.parag()->at( backCursor.index() )->c);
  1404. //beginningOfSentence = isMark( backCursor.parag()->at( backCursor.index() )->c ) && (backCursor.parag()->at( backCursor.index()+1 )->c.isSpace());
  1405. if ( !beginningOfSentence && start==0 )
  1406. if ( parag->counter() || backCursor.parag()->at( backCursor.index() )->c.isPunct() )
  1407. beginningOfSentence = true;
  1408. // Now look for exceptions
  1409. if ( beginningOfSentence )
  1410. {
  1411. TQChar const punct = backCursor.parag()->at( backCursor.index() )->c;
  1412. TQString const text = getLastWord( backCursor.parag(), backCursor.index() )
  1413. + punct;
  1414. kdDebug() << "text: " << text << endl;
  1415. // text has the word at the end of the 'sentence', including the termination. Example: "Mr."
  1416. beginningOfSentence = (m_upperCaseExceptions.findIndex(text)==-1); // Ok if we can't find it
  1417. }
  1418. if ( beginningOfSentence )
  1419. {
  1420. KoTextCursor cursor( parag->document() );
  1421. cursor.setParag( parag );
  1422. cursor.setIndex( start );
  1423. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1424. cursor.setIndex( start + 1 );
  1425. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1426. cmd = txtObj->replaceSelectionCommand( textEditCursor, TQString( firstChar.upper() ),
  1427. i18n("Autocorrect (capitalize first letter)"),
  1428. KoTextDocument::HighlightSelection );
  1429. bNeedMove = true;
  1430. }
  1431. }
  1432. else if ( m_convertUpperUpper && isUpper( firstChar ) && length > 2 )
  1433. {
  1434. backCursor.setIndex( backCursor.index() + 1 );
  1435. TQChar secondChar = backCursor.parag()->at( backCursor.index() )->c;
  1436. //kdDebug(32500)<<" secondChar :"<<secondChar<<endl;
  1437. if ( isUpper( secondChar ) )
  1438. {
  1439. // Check next letter - we still want to be able to write fully uppercase words...
  1440. backCursor.setIndex( backCursor.index() + 1 );
  1441. TQChar thirdChar = backCursor.parag()->at( backCursor.index() )->c;
  1442. if ( isLower( thirdChar ) && (m_twoUpperLetterException.findIndex(word)==-1))
  1443. {
  1444. // Ok, convert
  1445. KoTextCursor cursor( parag->document() );
  1446. cursor.setParag( parag );
  1447. cursor.setIndex( start + 1 ); // After all the first letter's fine, so only change the second letter
  1448. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1449. cursor.setIndex( start + 2 );
  1450. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1451. TQString replacement = word[1].lower();
  1452. cmd = txtObj->replaceSelectionCommand( textEditCursor, replacement,
  1453. i18n("Autocorrect"),
  1454. KoTextDocument::HighlightSelection );
  1455. bNeedMove = true;
  1456. }
  1457. }
  1458. }
  1459. if ( bNeedMove )
  1460. {
  1461. if (word.at(word.length()-1) == '.' )
  1462. ++index;
  1463. txtObj->emitHideCursor();
  1464. textEditCursor->setParag( parag );
  1465. textEditCursor->setIndex( index );
  1466. textEditCursor->gotoRight(); // not the same thing as index+1, in case of CR
  1467. txtObj->emitShowCursor();
  1468. }
  1469. return cmd;
  1470. }
  1471. KCommand * KoAutoFormat::doAutoReplaceNumber( KoTextCursor* textEditCursor, KoTextParag *parag, int& index, const TQString & word , KoTextObject *txtObj )
  1472. {
  1473. unsigned int length = word.length();
  1474. if ( length != 3 )
  1475. return 0L;
  1476. KoTextDocument * textdoc = parag->textDocument();
  1477. int start = index - length;
  1478. if( word == TQString("1/2") || word == TQString("1/4") || word == TQString("3/4") )
  1479. {
  1480. KoTextCursor cursor( parag->document() );
  1481. cursor.setParag( parag );
  1482. cursor.setIndex( start );
  1483. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1484. cursor.setIndex( start + length );
  1485. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1486. TQString replacement;
  1487. if( word == TQString("1/2") )
  1488. replacement=TQString("½");
  1489. else if (word == TQString("1/4") )
  1490. replacement=TQString("¼");
  1491. else if (word == TQString("3/4") )
  1492. replacement=TQString("¾");
  1493. TQString cmdName = i18n("Autocorrect for Fraction");
  1494. KCommand *cmd =txtObj->replaceSelectionCommand( textEditCursor, replacement,
  1495. cmdName,
  1496. KoTextDocument::HighlightSelection );
  1497. txtObj->emitHideCursor();
  1498. textEditCursor->gotoRight();
  1499. txtObj->emitShowCursor();
  1500. index = index - length + replacement.length();
  1501. return cmd;
  1502. }
  1503. return 0L;
  1504. }
  1505. void KoAutoFormat::detectStartOfLink(KoTextParag * parag, int const index, bool const insertedDot)
  1506. {
  1507. TQString word;
  1508. KoTextString *s = parag->string();
  1509. for ( int i = 0; i < index; ++i )
  1510. {
  1511. word.append( s->at( i ).c );
  1512. }
  1513. if (word.find("http")!=-1 || word.find("https")!=-1 || word.find("mailto")!=-1 || word.find("ftp")!=-1 || word.find("file")!=-1
  1514. || word.find("news")!=-1 || word.find('@')!=-1)
  1515. m_ignoreUpperCase=true;
  1516. else
  1517. {
  1518. int const tmp_pos=word.find("www.");
  1519. if (tmp_pos!=-1 && (word.find('.',tmp_pos+4)!=-1 || insertedDot) )
  1520. m_ignoreUpperCase=true;
  1521. }
  1522. }
  1523. void KoAutoFormat::doAutoDetectUrl( KoTextCursor *textEditCursor, KoTextParag *parag, int &index, TQString & word, KoTextObject *txtObj )
  1524. {
  1525. kdDebug() << "link:" << word << endl;
  1526. char link_type = 0;
  1527. int pos = word.find("http://");
  1528. int tmp_pos = word.find("https://");
  1529. if(tmp_pos<pos && tmp_pos!=-1)
  1530. pos = tmp_pos;
  1531. tmp_pos = word.find("mailto:/");
  1532. if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
  1533. pos = tmp_pos;
  1534. tmp_pos = word.find("ftp://");
  1535. if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
  1536. pos = tmp_pos;
  1537. tmp_pos = word.find("ftp.");
  1538. if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
  1539. {
  1540. pos = tmp_pos;
  1541. link_type = 3;
  1542. }
  1543. tmp_pos = word.find("file:/");
  1544. if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
  1545. pos = tmp_pos;
  1546. tmp_pos = word.find("news:");
  1547. if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1)
  1548. pos = tmp_pos;
  1549. tmp_pos = word.find("www.");
  1550. if((tmp_pos<pos || pos==-1 ) && tmp_pos!=-1 && word.find('.',tmp_pos+4)!=-1 )
  1551. {
  1552. pos = tmp_pos;
  1553. link_type = 2;
  1554. }
  1555. tmp_pos = word.find('@');
  1556. if ( pos == -1 && tmp_pos != -1 )
  1557. {
  1558. pos = tmp_pos-1;
  1559. TQChar c;
  1560. while( pos>=0 )
  1561. {
  1562. c = word.at(pos);
  1563. if ( c.isPunct() && c!='.'&& c!='_') break;
  1564. else --pos;
  1565. }
  1566. if ( pos == tmp_pos-1 ) //it not a valid address
  1567. {
  1568. m_ignoreUpperCase = false;
  1569. pos = -1;
  1570. }
  1571. else
  1572. ++pos;
  1573. link_type = 1;
  1574. }
  1575. if(pos!=-1)
  1576. {
  1577. // A URL inside e.g. quotes (like "http://www.koffice.org" with the quotes) shouldn't include the quote in the URL.
  1578. while ( !word.at(word.length()-1).isLetter() && !word.at(word.length()-1).isDigit() && word.at(word.length()-1)!='/')
  1579. {
  1580. word.truncate(word.length()-1);
  1581. --index;
  1582. }
  1583. word.remove(0,pos);
  1584. unsigned int const length = word.length();
  1585. int const start = index - length;
  1586. KoTextCursor cursor( parag->document() );
  1587. KoTextDocument * textdoc = parag->textDocument();
  1588. cursor.setParag( parag );
  1589. cursor.setIndex( start );
  1590. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1591. cursor.setIndex( start + length );
  1592. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1593. TQString newWord = word;
  1594. if(link_type==1)
  1595. newWord = TQString("mailto:") + word;
  1596. else if(link_type==2)
  1597. newWord = TQString("http://") + word;
  1598. else if(link_type==3)
  1599. newWord = TQString("ftp://") + word;
  1600. KoVariable* var = new KoLinkVariable( textdoc, word, newWord, m_varFormatCollection->format( "STRING" ), m_varCollection );
  1601. CustomItemsMap customItemsMap;
  1602. customItemsMap.insert( 0, var );
  1603. KoTextFormat * lastFormat = parag->at( start )->format();
  1604. int origCursorIndex = textEditCursor->index();
  1605. txtObj->insert( textEditCursor, lastFormat, KoTextObject::customItemChar(), i18n("Insert Variable"),
  1606. KoTextDocument::HighlightSelection, KoTextObject::DefaultInsertFlags, customItemsMap );
  1607. var->recalc();
  1608. parag->invalidate(0);
  1609. parag->setChanged( true );
  1610. // adjust index
  1611. index -= length-1; // we removed length chars and inserted one instead
  1612. txtObj->emitHideCursor();
  1613. textEditCursor->setIndex( origCursorIndex - (length-1) );
  1614. txtObj->emitShowCursor();
  1615. // ###### TODO: Move to a common method, this code is duplicated...
  1616. if ( m_completion && m_addCompletionWord && m_listCompletion->items().count() < m_nbMaxCompletionWord )
  1617. {
  1618. if (word.length()>= m_minCompletionWordLength && !word.isEmpty() && m_listCompletion->makeCompletion(word).isEmpty())
  1619. {
  1620. kdDebug() << "Adding:" << word << endl;
  1621. m_listCompletion->addItem( word );
  1622. if ( word.length() > m_countMaxWords )
  1623. m_countMaxWords = word.length();
  1624. }
  1625. }
  1626. }
  1627. }
  1628. void KoAutoFormat::doAutoIncludeUpperUpper(KoTextCursor* /*textEditCursor*/, KoTextParag *parag, KoTextObject* /*txtObj*/ )
  1629. {
  1630. KoTextString *s = parag->string();
  1631. if( s->length() < 2 )
  1632. return;
  1633. for (int i=0; i<=(s->length() - 1);i++)
  1634. {
  1635. TQString word;
  1636. for ( int j = i ; j < s->length() - 1; j++ )
  1637. {
  1638. TQChar ch = s->at( j ).c;
  1639. if ( ch.isSpace() )
  1640. break;
  1641. word.append( ch );
  1642. }
  1643. if( word.length() > 2 && word.left(2)==word.left(2).upper() && word.at(3)!=word.at(3).upper() )
  1644. {
  1645. if ( m_twoUpperLetterException.findIndex(word )==-1)
  1646. m_twoUpperLetterException.append( word);
  1647. }
  1648. i+=word.length();
  1649. }
  1650. }
  1651. void KoAutoFormat::doAutoIncludeAbbreviation(KoTextCursor* /*textEditCursor*/, KoTextParag *parag, KoTextObject* /*txtObj*/ )
  1652. {
  1653. KoTextString *s = parag->string();
  1654. if( s->length() < 2 )
  1655. return;
  1656. for (int i=0; i<=(s->length() - 1);i++)
  1657. {
  1658. TQString wordAfter;
  1659. TQString word;
  1660. for ( int j = i ; j < s->length() - 1; j++ )
  1661. {
  1662. TQChar ch = s->at( j ).c;
  1663. if ( ch.isSpace() )
  1664. break;
  1665. word.append( ch );
  1666. }
  1667. if ( isMark( word.at(word.length()-1)) )
  1668. {
  1669. for ( int j = i+word.length()+1 ; j < s->length() - 1; j++ )
  1670. {
  1671. TQChar ch = s->at( j ).c;
  1672. if ( ch.isSpace() )
  1673. break;
  1674. wordAfter.append( ch );
  1675. }
  1676. if( word.length()>1 && !wordAfter.isEmpty() && wordAfter.at(0)==wordAfter.at(0).lower())
  1677. {
  1678. if ( m_upperCaseExceptions.findIndex(word )==-1)
  1679. m_upperCaseExceptions.append( word );
  1680. }
  1681. }
  1682. i+=word.length();
  1683. if( !wordAfter.isEmpty())
  1684. {
  1685. i+=wordAfter.length()+1;
  1686. }
  1687. }
  1688. }
  1689. KCommand * KoAutoFormat::doAutoChangeFormat( KoTextCursor *textEditCursor, KoTextParag *parag,int index, const TQString & word, KoTextObject *txtObj )
  1690. {
  1691. bool underline = (word.at(0)=='_' && word.at(word.length()-1)=='_');
  1692. bool bold = (word.at(0)=='*' && word.at(word.length()-1)=='*');
  1693. if( bold || underline)
  1694. {
  1695. TQString replacement=word.mid(1,word.length()-2);
  1696. int start = index - word.length();
  1697. KoTextDocument * textdoc = parag->textDocument();
  1698. KMacroCommand *macro=new KMacroCommand(i18n("Autocorrection: Change Format"));
  1699. KoTextCursor cursor( parag->document() );
  1700. cursor.setParag( parag );
  1701. cursor.setIndex( start );
  1702. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1703. cursor.setIndex( start + word.length() );
  1704. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1705. macro->addCommand(txtObj->replaceSelectionCommand( textEditCursor, replacement,
  1706. i18n("Autocorrect Word"),
  1707. KoTextDocument::HighlightSelection));
  1708. KoTextFormat * lastFormat = parag->at( start )->format();
  1709. KoTextFormat * newFormat = new KoTextFormat(*lastFormat);
  1710. cursor.setIndex( start );
  1711. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1712. cursor.setIndex( start + word.length()-2 );
  1713. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1714. if( bold)
  1715. {
  1716. newFormat->setBold(true);
  1717. macro->addCommand(txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::Bold , false,KoTextDocument::HighlightSelection ));
  1718. }
  1719. else if( underline )
  1720. {
  1721. newFormat->setUnderline(true);
  1722. macro->addCommand(txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::Underline , false,KoTextDocument::HighlightSelection ));
  1723. }
  1724. txtObj->emitHideCursor();
  1725. textEditCursor->gotoRight();
  1726. txtObj->emitShowCursor();
  1727. return macro;
  1728. }
  1729. return 0L;
  1730. }
  1731. KCommand *KoAutoFormat::doUseBulletStyle(KoTextCursor * /*textEditCursor*/, KoTextParag *parag, KoTextObject *txtObj, int& index )
  1732. {
  1733. KoTextDocument * textdoc = parag->textDocument();
  1734. KoTextCursor cursor( parag->document() );
  1735. KoTextString *s = parag->string();
  1736. TQChar ch = s->at( 0 ).c;
  1737. if( m_useBulletStyle && (ch =='*' || ch == '-' || ch =='+') && (s->at(1).c).isSpace())
  1738. {
  1739. if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_FOOTNOTE )
  1740. return 0L;
  1741. KMacroCommand *macroCmd = new KMacroCommand( i18n("Autocorrect (use bullet style)"));
  1742. cursor.setParag( parag );
  1743. cursor.setIndex( 0 );
  1744. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1745. cursor.setParag( parag );
  1746. cursor.setIndex( 2 );
  1747. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1748. KCommand *cmd=txtObj->removeSelectedTextCommand( &cursor, KoTextDocument::HighlightSelection );
  1749. // Adjust index
  1750. index -= 2;
  1751. if(cmd)
  1752. macroCmd->addCommand(cmd);
  1753. cursor.setParag( parag );
  1754. cursor.setIndex( 0 );
  1755. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1756. cursor.setIndex( 2 );
  1757. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1758. KoParagCounter c;
  1759. if( m_bulletStyle.isNull() && (ch == '*' || ch == '+' || ch == '-'))
  1760. {
  1761. if ( ch =='*')
  1762. {
  1763. c.setNumbering( KoParagCounter::NUM_LIST );
  1764. c.setStyle( KoParagCounter::STYLE_DISCBULLET );
  1765. }
  1766. else if ( ch =='+' || ch=='-')
  1767. {
  1768. c.setNumbering( KoParagCounter::NUM_LIST );
  1769. c.setStyle( KoParagCounter::STYLE_CUSTOMBULLET );
  1770. if ( ch =='-' )
  1771. c.setCustomBulletCharacter( '-' );
  1772. else if ( ch=='+')
  1773. c.setCustomBulletCharacter( '+' );
  1774. }
  1775. }
  1776. else
  1777. {
  1778. c.setNumbering( KoParagCounter::NUM_LIST );
  1779. c.setStyle( KoParagCounter::STYLE_CUSTOMBULLET );
  1780. c.setCustomBulletCharacter( m_bulletStyle );
  1781. }
  1782. c.setSuffix(TQString());
  1783. cmd=txtObj->setCounterCommand( &cursor, c ,KoTextDocument::HighlightSelection );
  1784. if( cmd)
  1785. macroCmd->addCommand(cmd);
  1786. if (parag->next() )
  1787. cursor.setParag( parag->next() );
  1788. else
  1789. return 0L;
  1790. cursor.setIndex( 0 );
  1791. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1792. cursor.setIndex( 0 );
  1793. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1794. cmd=txtObj->setCounterCommand( &cursor, c ,KoTextDocument::HighlightSelection );
  1795. if(cmd)
  1796. macroCmd->addCommand(cmd);
  1797. return macroCmd;
  1798. }
  1799. return 0L;
  1800. }
  1801. KCommand *KoAutoFormat::doUseNumberStyle(KoTextCursor * /*textEditCursor*/, KoTextParag *parag, KoTextObject *txtObj, int& index )
  1802. {
  1803. if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_FOOTNOTE )
  1804. return 0L;
  1805. KoTextDocument * textdoc = parag->textDocument();
  1806. KoTextCursor cursor( parag->document() );
  1807. KoTextString *s = parag->string();
  1808. TQString word;
  1809. for ( int i = 0 ; i < s->length() - 1; i++ )
  1810. {
  1811. TQChar ch = s->at( i ).c;
  1812. if ( ch.isSpace() )
  1813. break;
  1814. word.append( ch );
  1815. }
  1816. TQChar punct=word[word.length()-1];
  1817. if( punct.isPunct() )
  1818. {
  1819. TQString number=word.mid(0,word.length()-1);
  1820. bool ok;
  1821. uint val=number.toUInt(&ok);
  1822. if( ok )
  1823. {
  1824. KMacroCommand *macroCmd = new KMacroCommand( i18n("Autocorrect (use number style)"));
  1825. cursor.setParag( parag );
  1826. cursor.setIndex( 0 );
  1827. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1828. cursor.setParag( parag );
  1829. cursor.setIndex( word.length()+1 );
  1830. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1831. KCommand *cmd=txtObj->removeSelectedTextCommand( &cursor, KoTextDocument::HighlightSelection );
  1832. // Adjust index
  1833. index -= word.length()+1;
  1834. if(cmd)
  1835. macroCmd->addCommand(cmd);
  1836. // Apply counter to this paragraph
  1837. cursor.setParag( parag );
  1838. cursor.setIndex( 0 );
  1839. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1840. cursor.setIndex( 2 );
  1841. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1842. KoParagCounter c;
  1843. c.setNumbering( KoParagCounter::NUM_LIST );
  1844. c.setStyle( KoParagCounter::STYLE_NUM );
  1845. c.setSuffix(TQString( punct ));
  1846. c.setStartNumber( (int)val);
  1847. // Look at which number this parag will have without a restart counter flag,
  1848. // to see if we need it. Thanks to Shaheed for number() taking a parag as param,
  1849. // so that it works even if the parag doesn't have this counter yet!
  1850. if ( c.number( parag ) != (int)val )
  1851. c.setRestartCounter( true );
  1852. cmd=txtObj->setCounterCommand( &cursor, c, KoTextDocument::HighlightSelection );
  1853. if( cmd)
  1854. macroCmd->addCommand(cmd);
  1855. // Apply counter to next paragraph too
  1856. // but without restart
  1857. c.setRestartCounter( false );
  1858. cursor.setParag( parag->next() );
  1859. cursor.setIndex( 0 );
  1860. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1861. cursor.setIndex( 0 );
  1862. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1863. cmd=txtObj->setCounterCommand( &cursor, c, KoTextDocument::HighlightSelection );
  1864. if(cmd)
  1865. macroCmd->addCommand(cmd);
  1866. return macroCmd;
  1867. }
  1868. }
  1869. return 0L;
  1870. }
  1871. KCommand * KoAutoFormat::doRemoveSpaceBeginEndLine( KoTextCursor *textEditCursor, KoTextParag *parag, KoTextObject *txtObj, int &index )
  1872. {
  1873. KoTextString *s = parag->string();
  1874. KoTextDocument * textdoc = parag->textDocument();
  1875. KoTextCursor cursor( parag->document() );
  1876. KMacroCommand *macroCmd = 0L;
  1877. // Cut away spaces at end of paragraph
  1878. for ( int i = parag->lastCharPos(); i >= 0; --i )
  1879. {
  1880. TQChar ch = s->at( i ).c;
  1881. if ( ch != ' ' ) // was: !ch.isSpace(), but this includes tabs, and this option is only about spaces
  1882. {
  1883. if( i == parag->lastCharPos() )
  1884. break;
  1885. cursor.setParag( parag );
  1886. cursor.setIndex( i+1 );
  1887. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1888. cursor.setParag( parag );
  1889. cursor.setIndex( parag->lastCharPos()+1 );
  1890. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1891. KCommand *cmd=txtObj->replaceSelectionCommand( &cursor, "", TQString(), KoTextDocument::HighlightSelection );
  1892. if(cmd)
  1893. {
  1894. if ( index > i )
  1895. index = i;
  1896. if ( !macroCmd )
  1897. macroCmd = new KMacroCommand( i18n("Autocorrect (remove start and end line space)"));
  1898. macroCmd->addCommand(cmd);
  1899. }
  1900. break;
  1901. }
  1902. }
  1903. // Cut away spaces at start of parag.
  1904. for ( int i = 0 ; i <= parag->lastCharPos() ; i++ )
  1905. {
  1906. TQChar ch = s->at( i ).c;
  1907. if ( ch != ' ' ) // was: !ch.isSpace(), but this includes tabs, and this option is only about spaces
  1908. {
  1909. if( i == 0 )
  1910. break;
  1911. cursor.setParag( parag );
  1912. cursor.setIndex( 0 );
  1913. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1914. cursor.setParag( parag );
  1915. cursor.setIndex( i );
  1916. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1917. KCommand *cmd=txtObj->replaceSelectionCommand( &cursor, "", TQString(), KoTextDocument::HighlightSelection );
  1918. if(cmd)
  1919. {
  1920. index -= i; // adjust index
  1921. if ( !macroCmd )
  1922. macroCmd = new KMacroCommand( i18n("Autocorrect (remove start and end line space)"));
  1923. macroCmd->addCommand(cmd);
  1924. }
  1925. break;
  1926. }
  1927. }
  1928. if( macroCmd )
  1929. {
  1930. txtObj->emitHideCursor();
  1931. textEditCursor->setParag( parag->next() );
  1932. //textEditCursor->cursorgotoRight();
  1933. txtObj->emitShowCursor();
  1934. }
  1935. return macroCmd;
  1936. }
  1937. KCommand *KoAutoFormat::doCapitalizeNameOfDays( KoTextCursor* textEditCursor, KoTextParag *parag, int index, const TQString & word , KoTextObject *txtObj )
  1938. {
  1939. //m_cacheNameOfDays
  1940. //todo
  1941. int pos = m_cacheNameOfDays.findIndex( word.lower() );
  1942. if ( pos == -1 )
  1943. return 0L;
  1944. KoTextDocument * textdoc = parag->textDocument();
  1945. TQString replaceStr= m_cacheNameOfDays[pos];
  1946. int start = index - replaceStr.length();
  1947. int length = replaceStr.length();
  1948. if( word.at(0).isLetter() && word.at(0)==word.at(0).lower() )
  1949. {
  1950. KoTextCursor cursor( parag->document() );
  1951. cursor.setParag( parag );
  1952. cursor.setIndex( start );
  1953. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  1954. cursor.setIndex( start + length );
  1955. TQString replacement = replaceStr.at(0).upper() + replaceStr.right( length-1 );
  1956. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  1957. TQString cmdName=i18n("Capitalize Name of Days");
  1958. KCommand *cmd =txtObj->replaceSelectionCommand( textEditCursor, replacement,
  1959. cmdName,
  1960. KoTextDocument::HighlightSelection );
  1961. txtObj->emitHideCursor();
  1962. textEditCursor->gotoRight();
  1963. txtObj->emitShowCursor();
  1964. return cmd;
  1965. }
  1966. return 0L;
  1967. }
  1968. KCommand *KoAutoFormat::doAutoSuperScript( KoTextCursor* textEditCursor, KoTextParag *parag, int index, const TQString & word , KoTextObject *txtObj )
  1969. {
  1970. KoAutoFormatEntryMap::Iterator it = m_superScriptEntries.begin();
  1971. bool found = false;
  1972. TQString replace;
  1973. for ( ; it != m_superScriptEntries.end() ; ++it )
  1974. {
  1975. if( it.key()==word)
  1976. {
  1977. replace = it.data().replace();
  1978. found = true;
  1979. break;
  1980. }
  1981. else if ( it.key()=="othernb")
  1982. {
  1983. TQString tmp = it.data().replace();
  1984. int pos = word.find( tmp );
  1985. if( pos != -1)
  1986. {
  1987. if( pos + tmp.length() == word.length())
  1988. {
  1989. bool ok;
  1990. word.left( pos ).toInt( &ok);
  1991. if( ok )
  1992. {
  1993. replace = tmp;
  1994. found = true;
  1995. break;
  1996. }
  1997. }
  1998. }
  1999. }
  2000. }
  2001. if (found )
  2002. {
  2003. KoTextDocument * textdoc = parag->textDocument();
  2004. int start = index - replace.length();
  2005. KoTextFormat * lastFormat = parag->at( start )->format();
  2006. KoTextFormat * newFormat = new KoTextFormat(*lastFormat);
  2007. KoTextCursor cursor( parag->document() );
  2008. cursor.setParag( parag );
  2009. cursor.setIndex( start );
  2010. textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
  2011. cursor.setIndex( start + word.length() -1 );
  2012. textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
  2013. newFormat->setVAlign(KoTextFormat::AlignSuperScript);
  2014. KCommand *cmd =txtObj->setFormatCommand( textEditCursor, 0L, newFormat, KoTextFormat::VAlign , false,KoTextDocument::HighlightSelection );
  2015. textdoc->removeSelection( KoTextDocument::HighlightSelection );
  2016. return cmd;
  2017. }
  2018. return 0L;
  2019. }
  2020. bool KoAutoFormat::doIgnoreDoubleSpace( KoTextParag *parag, int index, TQChar ch )
  2021. {
  2022. if( m_ignoreDoubleSpace && ch==' ' && index >= 0 && !parag->hasAnySelection() )
  2023. {
  2024. KoTextString *s = parag->string();
  2025. TQChar ch = s->at( index ).c;
  2026. if ( ch==' ' )
  2027. return true;
  2028. }
  2029. return false;
  2030. }
  2031. void KoAutoFormat::configTypographicSimpleQuotes( TypographicQuotes _tq )
  2032. {
  2033. m_typographicSimpleQuotes = _tq;
  2034. }
  2035. void KoAutoFormat::configTypographicDoubleQuotes( TypographicQuotes _tq )
  2036. {
  2037. m_typographicDoubleQuotes = _tq;
  2038. }
  2039. void KoAutoFormat::configUpperCase( bool _uc )
  2040. {
  2041. m_convertUpperCase = _uc;
  2042. }
  2043. void KoAutoFormat::configUpperUpper( bool _uu )
  2044. {
  2045. m_convertUpperUpper = _uu;
  2046. }
  2047. void KoAutoFormat::configAdvancedAutocorrect( bool _aa )
  2048. {
  2049. m_advancedAutoCorrect = _aa;
  2050. }
  2051. void KoAutoFormat::configAutoDetectUrl(bool _au)
  2052. {
  2053. m_autoDetectUrl=_au;
  2054. }
  2055. void KoAutoFormat::configIgnoreDoubleSpace( bool _ids)
  2056. {
  2057. m_ignoreDoubleSpace=_ids;
  2058. }
  2059. void KoAutoFormat::configRemoveSpaceBeginEndLine( bool _space)
  2060. {
  2061. m_removeSpaceBeginEndLine=_space;
  2062. }
  2063. void KoAutoFormat::configUseBulletStyle( bool _ubs)
  2064. {
  2065. m_useBulletStyle=_ubs;
  2066. }
  2067. void KoAutoFormat::configBulletStyle( TQChar b )
  2068. {
  2069. m_bulletStyle = b;
  2070. }
  2071. void KoAutoFormat::configAutoChangeFormat( bool b)
  2072. {
  2073. m_autoChangeFormat = b;
  2074. }
  2075. void KoAutoFormat::configAutoReplaceNumber( bool b )
  2076. {
  2077. m_autoReplaceNumber = b;
  2078. }
  2079. void KoAutoFormat::configAutoNumberStyle( bool b )
  2080. {
  2081. m_useAutoNumberStyle = b;
  2082. }
  2083. void KoAutoFormat::configCompletion( bool b )
  2084. {
  2085. m_completion = b;
  2086. }
  2087. void KoAutoFormat::configToolTipCompletion( bool b )
  2088. {
  2089. m_toolTipCompletion = b;
  2090. if (!b && m_completionBox)
  2091. {
  2092. delete m_completionBox;
  2093. m_completionBox = 0;
  2094. }
  2095. }
  2096. void KoAutoFormat::configKeyCompletionAction( KeyCompletionAction action )
  2097. {
  2098. m_keyCompletionAction = action;
  2099. }
  2100. void KoAutoFormat::configAppendSpace( bool b)
  2101. {
  2102. m_completionAppendSpace= b;
  2103. }
  2104. void KoAutoFormat::configMinWordLength( uint val )
  2105. {
  2106. m_minCompletionWordLength = val;
  2107. }
  2108. void KoAutoFormat::configNbMaxCompletionWord( uint val )
  2109. {
  2110. m_nbMaxCompletionWord = val;
  2111. }
  2112. void KoAutoFormat::configAddCompletionWord( bool b )
  2113. {
  2114. m_addCompletionWord= b;
  2115. }
  2116. bool KoAutoFormat::isUpper( const TQChar &c )
  2117. {
  2118. return c.lower() != c;
  2119. }
  2120. bool KoAutoFormat::isLower( const TQChar &c )
  2121. {
  2122. // Note that this is not the same as !isUpper !
  2123. // For instance '1' is not lower nor upper,
  2124. return c.upper() != c;
  2125. }
  2126. bool KoAutoFormat::isMark( const TQChar &c )
  2127. {
  2128. return ( c == TQChar( '.' ) ||
  2129. c == TQChar( '?' ) ||
  2130. c == TQChar( '!' ) );
  2131. }
  2132. bool KoAutoFormat::isSeparator( const TQChar &c )
  2133. {
  2134. return ( !c.isLetter() && !c.isNumber() && !c.isDigit() );
  2135. }
  2136. void KoAutoFormat::buildMaxLen()
  2137. {
  2138. m_maxFindLength = 0;
  2139. TQDictIterator<KoAutoFormatEntry> it( m_entries );
  2140. for( ; it.current(); ++it )
  2141. {
  2142. m_maxFindLength = TQMAX( m_maxFindLength, it.currentKey().length() );
  2143. }
  2144. TQDictIterator<KoAutoFormatEntry> it2( m_allLanguages );
  2145. for( ; it2.current(); ++it2 )
  2146. {
  2147. m_maxFindLength = TQMAX( m_maxFindLength, it2.currentKey().length() );
  2148. }
  2149. }
  2150. TQStringList KoAutoFormat::listCompletion() const
  2151. {
  2152. return m_listCompletion->items();
  2153. }
  2154. void KoAutoFormat::configIncludeTwoUpperUpperLetterException( bool b)
  2155. {
  2156. m_includeTwoUpperLetterException = b;
  2157. }
  2158. void KoAutoFormat::configIncludeAbbreviation( bool b )
  2159. {
  2160. m_includeAbbreviation = b;
  2161. }
  2162. void KoAutoFormat::configAutoSuperScript( bool b )
  2163. {
  2164. m_bAutoSuperScript = b;
  2165. }
  2166. void KoAutoFormat::configCorrectionWithFormat( bool b)
  2167. {
  2168. m_bAutoCorrectionWithFormat = b;
  2169. }
  2170. void KoAutoFormat::configCapitalizeNameOfDays( bool b)
  2171. {
  2172. m_bCapitalizeNameOfDays = b;
  2173. }
  2174. void KoAutoFormat::configAutoFormatLanguage( const TQString &_lang)
  2175. {
  2176. m_autoFormatLanguage=_lang;
  2177. }
  2178. KCommand *KoAutoFormat::applyAutoFormat( KoTextObject * obj )
  2179. {
  2180. KoTextParag * parag = obj->textDocument()->firstParag();
  2181. KoTextCursor *cursor = new KoTextCursor( obj->textDocument() );
  2182. KMacroCommand *macro = 0L;
  2183. while ( parag )
  2184. {
  2185. cursor->setIndex(0);
  2186. for (int i=0;i<parag->length();i++)
  2187. {
  2188. cursor->gotoRight();
  2189. //kdDebug() << "ch:" << parag->string()->at(i).c << endl;
  2190. if (i == parag->length()-1)
  2191. doAutoFormat(cursor,parag,i,'\n',obj);
  2192. else
  2193. doAutoFormat(cursor,parag,i, parag->string()->at(i).c,obj);
  2194. }
  2195. parag = parag->next();
  2196. }
  2197. delete cursor;
  2198. return macro;
  2199. }
  2200. void KoAutoFormat::changeTextFormat(KoSearchContext *formatOptions, KoTextFormat * format, int & flags )
  2201. {
  2202. if (formatOptions )
  2203. {
  2204. if (formatOptions->m_optionsMask & KoSearchContext::Bold)
  2205. {
  2206. format->setBold( formatOptions->m_options & KoSearchContext::Bold);
  2207. flags |=KoTextFormat::Bold;
  2208. }
  2209. if ( formatOptions->m_optionsMask & KoSearchContext::Size)
  2210. {
  2211. format->setPointSize( formatOptions->m_size );
  2212. flags |=KoTextFormat::Size;
  2213. }
  2214. if ( formatOptions->m_optionsMask & KoSearchContext::Family)
  2215. {
  2216. format->setFamily( formatOptions->m_family );
  2217. flags |=KoTextFormat::Family;
  2218. }
  2219. if ( formatOptions->m_optionsMask & KoSearchContext::Color)
  2220. {
  2221. format->setColor(formatOptions->m_color);
  2222. flags |=KoTextFormat::Color;
  2223. }
  2224. if ( formatOptions->m_optionsMask & KoSearchContext::BgColor)
  2225. {
  2226. format->setTextBackgroundColor(formatOptions->m_backGroundColor);
  2227. flags |=KoTextFormat::TextBackgroundColor;
  2228. }
  2229. if ( formatOptions->m_optionsMask & KoSearchContext::Italic)
  2230. {
  2231. format->setItalic( formatOptions->m_options & KoSearchContext::Italic);
  2232. flags |=KoTextFormat::Italic;
  2233. }
  2234. if ( formatOptions->m_optionsMask & KoSearchContext::WordByWord)
  2235. {
  2236. format->setWordByWord( formatOptions->m_options & KoSearchContext::WordByWord );
  2237. flags |=KoTextFormat::WordByWord;
  2238. }
  2239. if ( formatOptions->m_optionsMask & KoSearchContext::Shadow)
  2240. {
  2241. if ( formatOptions->m_options & KoSearchContext::Shadow )
  2242. format->setShadow( 1, 1, TQt::gray );
  2243. else
  2244. format->setShadow( 0, 0, TQColor() );
  2245. flags |=KoTextFormat::ShadowText;
  2246. }
  2247. if ( formatOptions->m_optionsMask & KoSearchContext::Underline)
  2248. {
  2249. format->setUnderlineType(formatOptions->m_underline);
  2250. flags |=KoTextFormat::ExtendUnderLine;
  2251. }
  2252. if ( formatOptions->m_optionsMask & KoSearchContext::StrikeOut)
  2253. {
  2254. format->setStrikeOutType(formatOptions->m_strikeOut);
  2255. flags |= KoTextFormat::StrikeOut;
  2256. }
  2257. if ( formatOptions->m_optionsMask & KoSearchContext::VertAlign)
  2258. {
  2259. format->setVAlign(formatOptions->m_vertAlign);
  2260. flags |=KoTextFormat::VAlign;
  2261. }
  2262. if ( formatOptions->m_optionsMask & KoSearchContext::Attribute)
  2263. {
  2264. format->setAttributeFont(formatOptions->m_attribute);
  2265. flags |= KoTextFormat::Attribute;
  2266. }
  2267. if (formatOptions->m_optionsMask & KoSearchContext::Language)
  2268. {
  2269. flags |= KoTextFormat::Language;
  2270. format->setLanguage( formatOptions->m_language );
  2271. }
  2272. }
  2273. }
  2274. #include "KoAutoFormat.moc"