lib

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