00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "KoTextObject.h"
00022 #include "KoTextParag.h"
00023 #include "KoParagCounter.h"
00024 #include "KoTextZoomHandler.h"
00025 #include "KoTextCommand.h"
00026 #include "KoStyleCollection.h"
00027 #include "KoFontDia.h"
00028 #include "KoOasisContext.h"
00029 #include "KoVariable.h"
00030 #include "KoAutoFormat.h"
00031 #include <KoXmlNS.h>
00032 #include <KoDom.h>
00033
00034 #include <klocale.h>
00035 #include <kdebug.h>
00036 #include <kapplication.h>
00037
00038 #include <qtimer.h>
00039 #include <qregexp.h>
00040 #include <qprogressdialog.h>
00041
00042 #include <assert.h>
00043
00044
00045
00046
00047 const char KoTextObject::s_customItemChar = '#';
00048
00049 struct KoTextObject::KoTextObjectPrivate
00050 {
00051 public:
00052 KoTextObjectPrivate() {
00053 afterFormattingEmitted = false;
00054 abortFormatting = false;
00055 }
00056 bool afterFormattingEmitted;
00057 bool abortFormatting;
00058 };
00059
00060 KoTextObject::KoTextObject( KoTextZoomHandler *zh, const QFont& defaultFont,
00061 const QString &defaultLanguage, bool hyphenation,
00062 KoParagStyle* defaultStyle, int tabStopWidth,
00063 QObject* parent, const char *name )
00064 : QObject( parent, name ), m_defaultStyle( defaultStyle ), undoRedoInfo( this )
00065 {
00066 textdoc = new KoTextDocument( zh, new KoTextFormatCollection( defaultFont, QColor(),defaultLanguage, hyphenation ) );
00067 if ( tabStopWidth != -1 )
00068 textdoc->setTabStops( tabStopWidth );
00069 init();
00070 }
00071
00072 KoTextObject::KoTextObject( KoTextDocument* _textdoc, KoParagStyle* defaultStyle,
00073 QObject* parent, const char *name )
00074 : QObject( parent, name ), m_defaultStyle( defaultStyle ), undoRedoInfo( this )
00075 {
00076 textdoc = _textdoc;
00077 init();
00078 }
00079
00080 void KoTextObject::init()
00081 {
00082 d = new KoTextObjectPrivate;
00083 m_needsSpellCheck = true;
00084 m_protectContent = false;
00085 m_visible=true;
00086 m_availableHeight = -1;
00087 m_lastFormatted = textdoc->firstParag();
00088 m_highlightSelectionAdded = false;
00089 interval = 0;
00090 changeIntervalTimer = new QTimer( this );
00091 connect( changeIntervalTimer, SIGNAL( timeout() ),
00092 this, SLOT( doChangeInterval() ) );
00093
00094 formatTimer = new QTimer( this );
00095 connect( formatTimer, SIGNAL( timeout() ),
00096 this, SLOT( formatMore() ) );
00097
00098
00099 if ( m_lastFormatted && m_defaultStyle )
00100 m_lastFormatted->applyStyle( m_defaultStyle );
00101
00102 connect( textdoc, SIGNAL( paragraphDeleted( KoTextParag* ) ),
00103 this, SIGNAL( paragraphDeleted( KoTextParag* ) ) );
00104 connect( textdoc, SIGNAL( paragraphDeleted( KoTextParag* ) ),
00105 this, SLOT( slotParagraphDeleted( KoTextParag* ) ) );
00106 connect( textdoc, SIGNAL( newCommand( KCommand* ) ),
00107 this, SIGNAL( newCommand( KCommand* ) ) );
00108 connect( textdoc, SIGNAL( repaintChanged() ),
00109 this, SLOT( emitRepaintChanged() ) );
00110
00111 connect( this, SIGNAL(paragraphModified( KoTextParag*, int, int , int ) ),
00112 this, SLOT(slotParagraphModified(KoTextParag *, int, int , int)));
00113 connect( this, SIGNAL(paragraphCreated( KoTextParag* )),
00114 this, SLOT(slotParagraphCreated(KoTextParag *)));
00115 }
00116
00117 KoTextObject::~KoTextObject()
00118 {
00119
00120
00121 undoRedoInfo.clear();
00122 delete textdoc; textdoc = 0;
00123 delete d;
00124 }
00125
00126 int KoTextObject::availableHeight() const
00127 {
00128 if ( m_availableHeight == -1 )
00129 emit const_cast<KoTextObject *>(this)->availableHeightNeeded();
00130 Q_ASSERT( m_availableHeight != -1 );
00131 return m_availableHeight;
00132 }
00133
00134 void KoTextObject::slotParagraphModified(KoTextParag * , int _type, int , int)
00135 {
00136 if ( _type == ChangeFormat)
00137 return;
00138 m_needsSpellCheck = true;
00139 }
00140
00141 void KoTextObject::slotParagraphCreated(KoTextParag * )
00142 {
00143 m_needsSpellCheck = true;
00144 }
00145
00146 void KoTextObject::slotParagraphDeleted(KoTextParag * parag)
00147 {
00148 if ( m_lastFormatted == parag )
00149 m_lastFormatted = parag->next();
00150
00151
00152
00153 }
00154
00155 int KoTextObject::docFontSize( KoTextFormat * format ) const
00156 {
00157 Q_ASSERT( format );
00158 return format->pointSize();
00159 }
00160
00161 int KoTextObject::zoomedFontSize( int docFontSize ) const
00162 {
00163 kdDebug(32500) << "KoTextObject::zoomedFontSize: docFontSize=" << docFontSize
00164 << " - in LU: " << KoTextZoomHandler::ptToLayoutUnitPt( docFontSize ) << endl;
00165 return KoTextZoomHandler::ptToLayoutUnitPt( docFontSize );
00166 }
00167
00168
00169 class KoHasCustomItemVisitor : public KoParagVisitor
00170 {
00171 public:
00172 KoHasCustomItemVisitor() : KoParagVisitor() { }
00173
00174 virtual bool visit( KoTextParag *parag, int start, int end )
00175 {
00176 for ( int i = start ; i < end ; ++i )
00177 {
00178 KoTextStringChar * ch = parag->at( i );
00179 if ( ch->isCustom() )
00180 return false;
00181 }
00182 return true;
00183 }
00184 };
00185
00186 bool KoTextObject::selectionHasCustomItems( KoTextDocument::SelectionId selectionId ) const
00187 {
00188 KoHasCustomItemVisitor visitor;
00189 bool noneFound = textdoc->visitSelection( selectionId, &visitor );
00190 return !noneFound;
00191 }
00192
00193 void KoTextObject::slotAfterUndoRedo()
00194 {
00195 formatMore( 2 );
00196 emit repaintChanged( this );
00197 emit updateUI( true );
00198 emit showCursor();
00199 emit ensureCursorVisible();
00200 }
00201
00202 void KoTextObject::clearUndoRedoInfo()
00203 {
00204 undoRedoInfo.clear();
00205 }
00206
00207
00208 void KoTextObject::checkUndoRedoInfo( KoTextCursor * cursor, UndoRedoInfo::Type t )
00209 {
00210 if ( undoRedoInfo.valid() && ( t != undoRedoInfo.type || cursor != undoRedoInfo.cursor ) ) {
00211 undoRedoInfo.clear();
00212 }
00213 undoRedoInfo.type = t;
00214 undoRedoInfo.cursor = cursor;
00215 }
00216
00217 void KoTextObject::undo()
00218 {
00219 undoRedoInfo.clear();
00220 emit hideCursor();
00221 KoTextCursor *cursor = new KoTextCursor( textdoc );
00222 KoTextCursor *c = textdoc->undo( cursor );
00223 if ( !c ) {
00224 delete cursor;
00225 emit showCursor();
00226 return;
00227 }
00228
00229
00230
00231 emit setCursor( c );
00232 setLastFormattedParag( textdoc->firstParag() );
00233 delete cursor;
00234 QTimer::singleShot( 0, this, SLOT( slotAfterUndoRedo() ) );
00235 }
00236
00237 void KoTextObject::redo()
00238 {
00239 undoRedoInfo.clear();
00240 emit hideCursor();
00241 KoTextCursor *cursor = new KoTextCursor( textdoc );
00242 KoTextCursor *c = textdoc->redo( cursor );
00243 if ( !c ) {
00244 delete cursor;
00245 emit showCursor();
00246 return;
00247 }
00248 emit setCursor( c );
00249 setLastFormattedParag( textdoc->firstParag() );
00250 delete cursor;
00251 QTimer::singleShot( 0, this, SLOT( slotAfterUndoRedo() ) );
00252 }
00253
00254 KoTextObject::UndoRedoInfo::UndoRedoInfo( KoTextObject *to )
00255 : type( Invalid ), textobj(to), cursor( 0 )
00256 {
00257 text = QString::null;
00258 id = -1;
00259 index = -1;
00260 placeHolderCmd = 0L;
00261 }
00262
00263 bool KoTextObject::UndoRedoInfo::valid() const
00264 {
00265 return text.length() > 0 && id >= 0 && index >= 0 && type != Invalid;
00266 }
00267
00268 void KoTextObject::UndoRedoInfo::clear()
00269 {
00270 if ( valid() ) {
00271 KoTextDocument* textdoc = textobj->textDocument();
00272 switch (type) {
00273 case Insert:
00274 case Return:
00275 {
00276 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, id, index, text.rawData(), customItemsMap, oldParagLayouts );
00277 textdoc->addCommand( cmd );
00278 Q_ASSERT( placeHolderCmd );
00279 if ( placeHolderCmd )
00280 {
00281
00282 if ( !customItemsMap.isEmpty() )
00283 {
00284 CustomItemsMap::Iterator it = customItemsMap.begin();
00285 for ( ; it != customItemsMap.end(); ++it )
00286 {
00287 KoTextCustomItem * item = it.data();
00288 KCommand * itemCmd = item->createCommand();
00289 if ( itemCmd )
00290 placeHolderCmd->addCommand( itemCmd );
00291 }
00292 placeHolderCmd->addCommand( new KoTextCommand( textobj, QString::null ) );
00293 }
00294 else
00295 {
00296 placeHolderCmd->addCommand( new KoTextCommand( textobj, QString::null ) );
00297 }
00298 }
00299 } break;
00300 case Delete:
00301 case RemoveSelected:
00302 {
00303 KoTextDocCommand * cmd = textobj->deleteTextCommand( textdoc, id, index, text.rawData(), customItemsMap, oldParagLayouts );
00304 textdoc->addCommand( cmd );
00305 Q_ASSERT( placeHolderCmd );
00306 placeHolderCmd->addCommand( new KoTextCommand( textobj, QString::null ) );
00307
00308 if ( !customItemsMap.isEmpty() )
00309 {
00310 customItemsMap.deleteAll( placeHolderCmd );
00311 }
00312 } break;
00313 case Invalid:
00314 break;
00315 }
00316 }
00317 type = Invalid;
00318
00319
00320 text = QString::null;
00321 id = -1;
00322 index = -1;
00323 oldParagLayouts.clear();
00324 customItemsMap.clear();
00325 placeHolderCmd = 0;
00326 }
00327
00328 void KoTextObject::copyCharFormatting( KoTextParag *parag, int position, int index , bool moveCustomItems )
00329 {
00330 KoTextStringChar * ch = parag->at( position );
00331 if ( ch->format() ) {
00332 ch->format()->addRef();
00333 undoRedoInfo.text.at( index ).setFormat( ch->format() );
00334 }
00335 if ( ch->isCustom() )
00336 {
00337 kdDebug(32500) << "KoTextObject::copyCharFormatting moving custom item " << ch->customItem() << " to text's " << index << " char" << endl;
00338 undoRedoInfo.customItemsMap.insert( index, ch->customItem() );
00339
00340
00341 if ( moveCustomItems )
00342 parag->removeCustomItem(position);
00343
00344 }
00345 }
00346
00347
00348 void KoTextObject::readFormats( KoTextCursor &c1, KoTextCursor &c2, bool copyParagLayouts, bool moveCustomItems )
00349 {
00350
00351 int oldLen = undoRedoInfo.text.length();
00352 if ( c1.parag() == c2.parag() ) {
00353 undoRedoInfo.text += c1.parag()->string()->toString().mid( c1.index(), c2.index() - c1.index() );
00354 for ( int i = c1.index(); i < c2.index(); ++i )
00355 copyCharFormatting( c1.parag(), i, oldLen + i - c1.index(), moveCustomItems );
00356 } else {
00357 int lastIndex = oldLen;
00358 int i;
00359
00360
00361 undoRedoInfo.text += c1.parag()->string()->toString().mid( c1.index(), c1.parag()->length() - 1 - c1.index() ) + '\n';
00362 for ( i = c1.index(); i < c1.parag()->length(); ++i, ++lastIndex )
00363 copyCharFormatting( c1.parag(), i, lastIndex, moveCustomItems );
00364
00365 KoTextParag *p = c1.parag()->next();
00366 while ( p && p != c2.parag() ) {
00367 undoRedoInfo.text += p->string()->toString().left( p->length() - 1 ) + '\n';
00368
00369 for ( i = 0; i < p->length(); ++i )
00370 copyCharFormatting( p, i, i + lastIndex, moveCustomItems );
00371 lastIndex += p->length();
00372
00373 p = p->next();
00374 }
00375
00376 undoRedoInfo.text += c2.parag()->string()->toString().left( c2.index() );
00377 for ( i = 0; i < c2.index(); ++i )
00378 copyCharFormatting( c2.parag(), i, i + lastIndex, moveCustomItems );
00379 }
00380
00381 if ( copyParagLayouts ) {
00382 KoTextParag *p = c1.parag();
00383 while ( p ) {
00384 undoRedoInfo.oldParagLayouts << p->paragLayout();
00385 if ( p == c2.parag() )
00386 break;
00387 p = p->next();
00388 }
00389 }
00390 }
00391
00392 void KoTextObject::newPlaceHolderCommand( const QString & name )
00393 {
00394 Q_ASSERT( !undoRedoInfo.placeHolderCmd );
00395 if ( undoRedoInfo.placeHolderCmd ) kdDebug(32500) << kdBacktrace();
00396 undoRedoInfo.placeHolderCmd = new KMacroCommand( name );
00397 emit newCommand( undoRedoInfo.placeHolderCmd );
00398 }
00399
00400 void KoTextObject::storeParagUndoRedoInfo( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId )
00401 {
00402 undoRedoInfo.clear();
00403 undoRedoInfo.oldParagLayouts.clear();
00404 undoRedoInfo.text = " ";
00405 undoRedoInfo.index = 1;
00406 if ( cursor && !textdoc->hasSelection( selectionId, true ) ) {
00407 KoTextParag * p = cursor->parag();
00408 undoRedoInfo.id = p->paragId();
00409 undoRedoInfo.eid = p->paragId();
00410 undoRedoInfo.oldParagLayouts << p->paragLayout();
00411 }
00412 else{
00413 Q_ASSERT( textdoc->hasSelection( selectionId, true ) );
00414 KoTextParag *start = textdoc->selectionStart( selectionId );
00415 KoTextParag *end = textdoc->selectionEnd( selectionId );
00416 undoRedoInfo.id = start->paragId();
00417 undoRedoInfo.eid = end->paragId();
00418 for ( ; start && start != end->next() ; start = start->next() )
00419 {
00420 undoRedoInfo.oldParagLayouts << start->paragLayout();
00421
00422 }
00423 }
00424 }
00425
00426 void KoTextObject::doKeyboardAction( KoTextCursor * cursor, KoTextFormat * & , KeyboardAction action )
00427 {
00428 KoTextParag * parag = cursor->parag();
00429 setLastFormattedParag( parag );
00430 emit hideCursor();
00431 bool doUpdateCurrentFormat = true;
00432 switch ( action ) {
00433 case ActionDelete: {
00434 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete );
00435 if ( !undoRedoInfo.valid() ) {
00436 newPlaceHolderCommand( i18n("Delete Text") );
00437 undoRedoInfo.id = parag->paragId();
00438 undoRedoInfo.index = cursor->index();
00439 undoRedoInfo.text = QString::null;
00440 undoRedoInfo.oldParagLayouts << parag->paragLayout();
00441 }
00442 if ( !cursor->atParagEnd() )
00443 {
00444 KoTextStringChar * ch = parag->at( cursor->index() );
00445 undoRedoInfo.text += ch->c;
00446 copyCharFormatting( parag, cursor->index(), undoRedoInfo.text.length()-1, true );
00447 }
00448 KoParagLayout paragLayout;
00449 if ( parag->next() )
00450 paragLayout = parag->next()->paragLayout();
00451
00452 KoTextParag *old = cursor->parag();
00453 if ( cursor->remove() ) {
00454 if ( old != cursor->parag() && m_lastFormatted == old )
00455 m_lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0;
00456 undoRedoInfo.text += "\n";
00457 undoRedoInfo.oldParagLayouts << paragLayout;
00458 } else
00459 emit paragraphModified( old, RemoveChar, cursor->index(), 1 );
00460 } break;
00461 case ActionBackspace: {
00462
00463 if ( parag->counter() && parag->counter()->style() != KoParagCounter::STYLE_NONE && cursor->index() == 0 ) {
00464
00465
00466 KoParagCounter c;
00467 c.setDepth( parag->counter()->depth() );
00468 KCommand *cmd=setCounterCommand( cursor, c );
00469 if(cmd)
00470 emit newCommand(cmd);
00471 }
00472 else if ( !cursor->atParagStart() )
00473 {
00474 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete );
00475 if ( !undoRedoInfo.valid() ) {
00476 newPlaceHolderCommand( i18n("Delete Text") );
00477 undoRedoInfo.id = parag->paragId();
00478 undoRedoInfo.index = cursor->index();
00479 undoRedoInfo.text = QString::null;
00480 undoRedoInfo.oldParagLayouts << parag->paragLayout();
00481 }
00482 undoRedoInfo.text.insert( 0, cursor->parag()->at( cursor->index()-1 ) );
00483 copyCharFormatting( cursor->parag(), cursor->index()-1, 0, true );
00484 undoRedoInfo.index = cursor->index()-1;
00485
00486 cursor->removePreviousChar();
00487 emit paragraphModified( cursor->parag(), RemoveChar, cursor->index(),1 );
00488 m_lastFormatted = cursor->parag();
00489 } else if ( parag->prev() ) {
00490 emit paragraphDeleted( cursor->parag() );
00491 clearUndoRedoInfo();
00492 textdoc->setSelectionStart( KoTextDocument::Temp, cursor );
00493 cursor->gotoPreviousLetter();
00494 textdoc->setSelectionEnd( KoTextDocument::Temp, cursor );
00495 removeSelectedText( cursor, KoTextDocument::Temp, i18n( "Delete Text" ) );
00496 emit paragraphModified( cursor->parag(), AddChar, cursor->index(), cursor->parag()->length() - cursor->index() );
00497 }
00498 } break;
00499 case ActionReturn: {
00500 checkUndoRedoInfo( cursor, UndoRedoInfo::Return );
00501 if ( !undoRedoInfo.valid() ) {
00502 newPlaceHolderCommand( i18n("Insert Text") );
00503 undoRedoInfo.id = cursor->parag()->paragId();
00504 undoRedoInfo.index = cursor->index();
00505 undoRedoInfo.text = QString::null;
00506 }
00507 undoRedoInfo.text += "\n";
00508 if ( cursor->parag() )
00509 {
00510 QString last_line = cursor->parag()->toString();
00511 last_line.remove(0,last_line.find(' ')+1);
00512
00513 if( last_line.isEmpty() && cursor->parag()->counter() && cursor->parag()->counter()->numbering() == KoParagCounter::NUM_LIST )
00514 {
00515 KoParagCounter c;
00516 KCommand *cmd=setCounterCommand( cursor, c );
00517 if(cmd)
00518 emit newCommand(cmd);
00519 setLastFormattedParag( cursor->parag() );
00520 cursor->parag()->setNoCounter();
00521
00522 formatMore( 2 );
00523 emit repaintChanged( this );
00524 emit ensureCursorVisible();
00525 emit showCursor();
00526 emit updateUI( doUpdateCurrentFormat );
00527 return;
00528 }
00529 else
00530 cursor->splitAndInsertEmptyParag();
00531 }
00532
00533 Q_ASSERT( cursor->parag()->prev() );
00534 setLastFormattedParag( cursor->parag() );
00535
00536 doUpdateCurrentFormat = false;
00537 KoParagStyle * style = cursor->parag()->prev()->style();
00538 if ( style )
00539 {
00540 KoParagStyle * newStyle = style->followingStyle();
00541 if ( newStyle && style != newStyle )
00542 {
00543 doUpdateCurrentFormat = true;
00544
00545
00546 }
00547 }
00548 if ( cursor->parag()->joinBorder() && cursor->parag()->bottomBorder().width() > 0 )
00549 cursor->parag()->prev()->setChanged( true );
00550 if ( cursor->parag()->joinBorder() && cursor->parag()->next() && cursor->parag()->next()->joinBorder() && cursor->parag()->bottomBorder() == cursor->parag()->next()->bottomBorder())
00551 cursor->parag()->next()->setChanged( true );
00552 emit paragraphCreated( cursor->parag() );
00553
00554 } break;
00555 case ActionKill:
00556
00557 if ( !cursor->atParagEnd() || cursor->parag()->next() ) {
00558 checkUndoRedoInfo( cursor, UndoRedoInfo::Delete );
00559 if ( !undoRedoInfo.valid() ) {
00560 newPlaceHolderCommand( i18n("Delete Text") );
00561 undoRedoInfo.id = cursor->parag()->paragId();
00562 undoRedoInfo.index = cursor->index();
00563 undoRedoInfo.text = QString::null;
00564 undoRedoInfo.oldParagLayouts << parag->paragLayout();
00565 }
00566 if ( cursor->atParagEnd() ) {
00567
00568 KoParagLayout paragLayout = parag->next()->paragLayout();
00569 if ( cursor->remove() )
00570 {
00571 m_lastFormatted = cursor->parag();
00572 undoRedoInfo.text += "\n";
00573 undoRedoInfo.oldParagLayouts << paragLayout;
00574 }
00575 } else {
00576 int oldLen = undoRedoInfo.text.length();
00577 undoRedoInfo.text += cursor->parag()->string()->toString().mid( cursor->index() );
00578 for ( int i = cursor->index(); i < cursor->parag()->length(); ++i )
00579 copyCharFormatting( cursor->parag(), i, oldLen + i - cursor->index(), true );
00580 cursor->killLine();
00581 emit paragraphModified( cursor->parag(), RemoveChar, cursor->index(), cursor->parag()->length()-cursor->index() );
00582 }
00583 }
00584 break;
00585 }
00586
00587 if ( !undoRedoInfo.customItemsMap.isEmpty() )
00588 clearUndoRedoInfo();
00589
00590 formatMore( 2 );
00591 emit repaintChanged( this );
00592 emit ensureCursorVisible();
00593 emit showCursor();
00594 emit updateUI( doUpdateCurrentFormat );
00595 }
00596
00597 void KoTextObject::insert( KoTextCursor * cursor, KoTextFormat * currentFormat,
00598 const QString &txt, const QString & commandName, KoTextDocument::SelectionId selectionId,
00599 int insertFlags, CustomItemsMap customItemsMap )
00600 {
00601 if ( protectContent() )
00602 return;
00603 const bool checkNewLine = insertFlags & CheckNewLine;
00604 const bool removeSelected = ( insertFlags & DoNotRemoveSelected ) == 0;
00605 const bool repaint = ( insertFlags & DoNotRepaint ) == 0;
00606
00607 bool tinyRepaint = !checkNewLine;
00608 if ( repaint )
00609 emit hideCursor();
00610 if ( textdoc->hasSelection( selectionId, true ) && removeSelected ) {
00611 kdDebug() << k_funcinfo << "removing selection " << selectionId << endl;
00612
00613 emitNewCommand(replaceSelectionCommand( cursor, txt, commandName, selectionId, insertFlags, customItemsMap ));
00614 return;
00615 }
00616
00617 if ( insertFlags & OverwriteMode ) {
00618 textdoc->setSelectionStart( KoTextDocument::Temp, cursor );
00619 KoTextCursor oc = *cursor;
00620 kdDebug(32500) << "overwrite: going to insert " << txt.length() << " chars; idx=" << oc.index() << endl;
00621 oc.setIndex( QMIN( oc.index() + (int)txt.length(), oc.parag()->lastCharPos() + 1 ) );
00622 kdDebug(32500) << "overwrite: removing from " << cursor->index() << " to " << oc.index() << endl;
00623 if ( oc.index() > cursor->index() )
00624 {
00625 textdoc->setSelectionEnd( KoTextDocument::Temp, &oc );
00626 int newInsertFlags = insertFlags & ~OverwriteMode;
00627 newInsertFlags &= ~DoNotRemoveSelected;
00628 emitNewCommand(replaceSelectionCommand( cursor, txt, commandName, KoTextDocument::Temp, newInsertFlags, customItemsMap ));
00629 return;
00630 }
00631 }
00632 KoTextCursor c2 = *cursor;
00633
00634 if ( !customItemsMap.isEmpty() )
00635 clearUndoRedoInfo();
00636 checkUndoRedoInfo( cursor, UndoRedoInfo::Insert );
00637 if ( !undoRedoInfo.valid() ) {
00638 if ( !commandName.isNull() )
00639 newPlaceHolderCommand( commandName );
00640 undoRedoInfo.id = cursor->parag()->paragId();
00641 undoRedoInfo.index = cursor->index();
00642 undoRedoInfo.text = QString::null;
00643 }
00644 int oldLen = undoRedoInfo.text.length();
00645 KoTextCursor oldCursor = *cursor;
00646 bool wasChanged = cursor->parag()->hasChanged();
00647 int origLine;
00648 oldCursor.parag()->lineStartOfChar( oldCursor.index(), 0, &origLine );
00649
00650
00651 cursor->insert( txt, checkNewLine );
00652
00653 setLastFormattedParag( checkNewLine ? oldCursor.parag() : cursor->parag() );
00654
00655 if ( !customItemsMap.isEmpty() ) {
00656 customItemsMap.insertItems( oldCursor, txt.length() );
00657 undoRedoInfo.customItemsMap = customItemsMap;
00658 tinyRepaint = false;
00659 }
00660
00661 textdoc->setSelectionStart( KoTextDocument::Temp, &oldCursor );
00662 textdoc->setSelectionEnd( KoTextDocument::Temp, cursor );
00663
00664 textdoc->setFormat( KoTextDocument::Temp, currentFormat, KoTextFormat::Format );
00665 textdoc->setFormat( KoTextDocument::InputMethodPreedit, currentFormat, KoTextFormat::Format );
00666 textdoc->removeSelection( KoTextDocument::Temp );
00667
00668 if ( !customItemsMap.isEmpty() ) {
00669
00670 CustomItemsMap::Iterator it = customItemsMap.begin();
00671 for ( ; it != customItemsMap.end(); ++it )
00672 it.data()->resize();
00673 }
00674
00675
00676
00677
00678 #if 0
00679 KoTextParag *parag = cursor->parag();
00680 if ( !checkNewLine && m_lastFormatted == parag && ( !parag->next() || parag->next()->isValid() ) )
00681 {
00682 parag->format();
00683 m_lastFormatted = m_lastFormatted->next();
00684 }
00685 #endif
00686
00687
00688 ensureFormatted( cursor->parag() );
00689
00690
00691
00692
00693 if ( !checkNewLine && tinyRepaint && !wasChanged )
00694 {
00695
00696
00697 Q_ASSERT( cursor->parag() == oldCursor.parag() );
00698 KoTextParag* parag = cursor->parag();
00699
00700
00701
00702 parag->setChanged( false );
00703 parag->setLineChanged( origLine - 1 );
00704 }
00705
00706 if ( repaint ) {
00707 emit repaintChanged( this );
00708 emit ensureCursorVisible();
00709 emit showCursor();
00710
00711 if ( oldCursor.index() == 0 && oldCursor.parag()->alignment() == Qt::AlignAuto )
00712 emit updateUI( true );
00713
00714 }
00715 undoRedoInfo.text += txt;
00716 for ( int i = 0; i < (int)txt.length(); ++i ) {
00717 if ( txt[ oldLen + i ] != '\n' )
00718 copyCharFormatting( c2.parag(), c2.index(), oldLen + i, false );
00719 c2.gotoNextLetter();
00720 }
00721
00722 if ( !removeSelected ) {
00723
00724
00725 if ( textdoc->removeSelection( selectionId ) && repaint )
00726 selectionChangedNotify();
00727 }
00728 if ( !customItemsMap.isEmpty()
00729 && !commandName.isNull() ) {
00730 clearUndoRedoInfo();
00731 }
00732
00733
00734 emit paragraphModified( oldCursor.parag(), AddChar, cursor->index(), txt.length() );
00735 if (checkNewLine) {
00736 KoTextParag* p = oldCursor.parag()->next();
00737 while ( p && p != cursor->parag() ) {
00738 emit paragraphCreated( p );
00739 p = p->next();
00740 }
00741 }
00742 }
00743
00744 void KoTextObject::pasteText( KoTextCursor * cursor, const QString & text, KoTextFormat * currentFormat, bool removeSelected )
00745 {
00746 if ( protectContent() )
00747 return;
00748 kdDebug(32500) << "KoTextObject::pasteText cursor parag=" << cursor->parag()->paragId() << endl;
00749 QString t = text;
00750
00751 QRegExp crlf( QString::fromLatin1("\r\n") );
00752 t.replace( crlf, QChar('\n') );
00753
00754 for ( int i=0; (uint) i<t.length(); i++ ) {
00755 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' )
00756 t[ i ] = ' ';
00757 }
00758 if ( !t.isEmpty() )
00759 {
00760 int insertFlags = CheckNewLine;
00761 if ( !removeSelected )
00762 insertFlags |= DoNotRemoveSelected;
00763 insert( cursor, currentFormat, t, i18n("Paste Text"),
00764 KoTextDocument::Standard, insertFlags );
00765 formatMore( 2 );
00766 emit repaintChanged( this );
00767 }
00768 }
00769
00770 KCommand* KoTextObject::setParagLayoutCommand( KoTextCursor * cursor, const KoParagLayout& paragLayout,
00771 KoTextDocument::SelectionId selectionId, int paragLayoutFlags,
00772 int marginIndex, bool createUndoRedo )
00773 {
00774 if ( protectContent() )
00775 return 0;
00776 storeParagUndoRedoInfo( cursor, selectionId );
00777 undoRedoInfo.type = UndoRedoInfo::Invalid;
00778 if ( paragLayoutFlags != 0 )
00779 {
00780 emit hideCursor();
00781 if ( !textdoc->hasSelection( selectionId, true ) ) {
00782 cursor->parag()->setParagLayout( paragLayout, paragLayoutFlags, marginIndex );
00783 setLastFormattedParag( cursor->parag() );
00784 } else {
00785 KoTextParag *start = textdoc->selectionStart( selectionId );
00786 KoTextParag *end = textdoc->selectionEnd( selectionId );
00787 for ( ; start && start != end->next() ; start = start->next() ) {
00788 if ( paragLayoutFlags == KoParagLayout::BulletNumber && start->length() <= 1 )
00789 continue;
00790 start->setParagLayout( paragLayout, paragLayoutFlags, marginIndex );
00791 }
00792 setLastFormattedParag( start );
00793 }
00794
00795 formatMore( 2 );
00796 emit repaintChanged( this );
00797 emit showCursor();
00798 emit updateUI( true );
00799
00800 if ( createUndoRedo )
00801 {
00802
00803 KoTextDocCommand * cmd = new KoTextParagCommand( textdoc, undoRedoInfo.id, undoRedoInfo.eid,
00804 undoRedoInfo.oldParagLayouts,
00805 paragLayout, paragLayoutFlags,
00806 (QStyleSheetItem::Margin)marginIndex );
00807 textdoc->addCommand( cmd );
00808 return new KoTextCommand( this, "related to KoTextParagCommand" );
00809 }
00810 }
00811 return 0;
00812 }
00813
00814
00815 void KoTextObject::applyStyle( KoTextCursor * cursor, const KoParagStyle * newStyle,
00816 KoTextDocument::SelectionId selectionId,
00817 int paragLayoutFlags, int formatFlags,
00818 bool createUndoRedo, bool interactive )
00819 {
00820 KCommand *cmd = applyStyleCommand( cursor, newStyle, selectionId,
00821 paragLayoutFlags, formatFlags,
00822 createUndoRedo, interactive );
00823 if ( createUndoRedo && cmd )
00824 emit newCommand( cmd );
00825 else
00826 Q_ASSERT( !cmd );
00827 }
00828
00829 KCommand *KoTextObject::applyStyleCommand( KoTextCursor * cursor, const KoParagStyle * newStyle,
00830 KoTextDocument::SelectionId selectionId,
00831 int paragLayoutFlags, int formatFlags,
00832 bool createUndoRedo, bool interactive )
00833 {
00834 if ( protectContent())
00835 return 0L;
00836 if ( interactive )
00837 emit hideCursor();
00838 if ( !textdoc->hasSelection( selectionId, true ) && !cursor)
00839 return 0L;
00845 KMacroCommand * macroCmd = createUndoRedo ? new KMacroCommand( i18n("Apply Style %1").
00846 arg(newStyle->displayName() ) ) : 0;
00847
00848
00849
00850 KCommand* cmd = setParagLayoutCommand( cursor, newStyle->paragLayout(), selectionId, paragLayoutFlags, -1, createUndoRedo );
00851 if ( cmd )
00852 macroCmd->addCommand( cmd );
00853
00854
00855
00856 KoTextParag * firstParag;
00857 KoTextParag * lastParag;
00858 if ( !textdoc->hasSelection( selectionId, true ) ) {
00859
00860 firstParag = cursor->parag();
00861 lastParag = cursor->parag();
00862 }
00863 else
00864 {
00865 firstParag = textdoc->selectionStart( selectionId );
00866 lastParag = textdoc->selectionEnd( selectionId );
00867 }
00868
00869 if ( formatFlags != 0 )
00870 {
00871 KoTextFormat * newFormat = textdoc->formatCollection()->format( &newStyle->format() );
00872
00873 if ( createUndoRedo )
00874 {
00875 QValueList<KoTextFormat *> lstFormats;
00876
00877 for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() )
00878 {
00879
00880 lstFormats.append( parag->paragFormat() );
00881 }
00882 KoTextCursor c1( textdoc );
00883 c1.setParag( firstParag );
00884 c1.setIndex( 0 );
00885 KoTextCursor c2( textdoc );
00886 c2.setParag( lastParag );
00887 c2.setIndex( lastParag->string()->length() );
00888 undoRedoInfo.clear();
00889 undoRedoInfo.type = UndoRedoInfo::Invalid;
00890 readFormats( c1, c2 );
00891
00892 KoTextDocCommand * cmd = new KoTextFormatCommand( textdoc, firstParag->paragId(), 0,
00893 lastParag->paragId(), c2.index(),
00894 undoRedoInfo.text.rawData(), newFormat,
00895 formatFlags );
00896 textdoc->addCommand( cmd );
00897 macroCmd->addCommand( new KoTextCommand( this, "related to KoTextFormatCommand" ) );
00898
00899
00900 cmd = new KoParagFormatCommand( textdoc, firstParag->paragId(), lastParag->paragId(),
00901 lstFormats, newFormat );
00902 textdoc->addCommand( cmd );
00903 macroCmd->addCommand( new KoTextCommand( this, "related to KoParagFormatCommand" ) );
00904 }
00905
00906
00907 for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() )
00908 {
00909
00910
00911 parag->setFormat( 0, parag->string()->length(), newFormat, true, formatFlags );
00912 parag->setFormat( newFormat );
00913 }
00914
00915
00916 }
00917
00918
00919 QPtrListIterator<KoTextCustomItem> cit( textdoc->allCustomItems() );
00920 for ( ; cit.current() ; ++cit )
00921 cit.current()->resize();
00922
00923
00924 if ( interactive )
00925 {
00926 setLastFormattedParag( firstParag );
00927 formatMore( 2 );
00928 emit repaintChanged( this );
00929 emit updateUI( true );
00930 emit showCursor();
00931 }
00932
00933 undoRedoInfo.clear();
00934
00935 return macroCmd;
00936 }
00937
00938 void KoTextObject::applyStyleChange( KoStyleChangeDefMap changed )
00939 {
00940 #if 0 //#ifndef NDEBUG
00941 kdDebug(32500) << "KoTextObject::applyStyleChange " << changed.count() << " styles." << endl;
00942 for( KoStyleChangeDefMap::const_iterator it = changed.begin(); it != changed.end(); ++it ) {
00943 kdDebug(32500) << " " << it.key()->name()
00944 << " paragLayoutChanged=" << (*it).paragLayoutChanged
00945 << " formatChanged=" << (*it).formatChanged
00946 << endl;
00947 }
00948 #endif
00949
00950 KoTextParag *p = textdoc->firstParag();
00951 while ( p ) {
00952 KoStyleChangeDefMap::Iterator it = changed.find( p->style() );
00953 if ( it != changed.end() )
00954 {
00955 if ( (*it).paragLayoutChanged == -1 || (*it).formatChanged == -1 )
00956 {
00957 p->setStyle( m_defaultStyle );
00958
00959 }
00960 else
00961 {
00962
00963 KoTextCursor cursor( textdoc );
00964 cursor.setParag( p );
00965 cursor.setIndex( 0 );
00966
00967 applyStyle( &cursor, it.key(),
00968 KoTextDocument::Temp,
00969 (*it).paragLayoutChanged, (*it).formatChanged,
00970 false, false );
00971 }
00972 } else {
00973
00974 }
00975
00976 p = p->next();
00977 }
00978 setLastFormattedParag( textdoc->firstParag() );
00979 formatMore( 2 );
00980 emit repaintChanged( this );
00981 emit updateUI( true );
00982 }
00983
00985 KCommand *KoTextObject::setFormatCommand( const KoTextFormat *format, int flags, bool zoomFont )
00986 {
00987 textdoc->selectAll( KoTextDocument::Temp );
00988 KCommand *cmd = setFormatCommand( 0L, 0L, format, flags, zoomFont, KoTextDocument::Temp );
00989 textdoc->removeSelection( KoTextDocument::Temp );
00990 return cmd;
00991 }
00992
00993 KCommand * KoTextObject::setFormatCommand( KoTextCursor * cursor, KoTextFormat ** pCurrentFormat, const KoTextFormat *format, int flags, bool , KoTextDocument::SelectionId selectionId )
00994 {
00995 KCommand *ret = 0;
00996 if ( protectContent() )
00997 return ret;
00998
00999 KoTextFormat* newFormat = 0;
01000
01001
01002
01003 bool isNewFormat = ( pCurrentFormat && *pCurrentFormat && (*pCurrentFormat)->key() != format->key() );
01004 if ( isNewFormat || !pCurrentFormat )
01005 {
01006 #if 0
01007 int origFontSize = 0;
01008 if ( zoomFont )
01009 {
01010 origFontSize = format->pointSize();
01011 format->setPointSize( zoomedFontSize( origFontSize ) );
01012
01013 }
01014 #endif
01015
01016 if ( pCurrentFormat )
01017 (*pCurrentFormat)->removeRef();
01018
01019 newFormat = textdoc->formatCollection()->format( format );
01020 if ( newFormat->isMisspelled() ) {
01021 KoTextFormat fNoMisspelled( *newFormat );
01022 newFormat->removeRef();
01023 fNoMisspelled.setMisspelled( false );
01024 newFormat = textdoc->formatCollection()->format( &fNoMisspelled );
01025 }
01026 if ( pCurrentFormat )
01027 (*pCurrentFormat) = newFormat;
01028 }
01029
01030 if ( textdoc->hasSelection( selectionId, true ) ) {
01031 emit hideCursor();
01032 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01033 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01034 undoRedoInfo.clear();
01035 int id = c1.parag()->paragId();
01036 int index = c1.index();
01037 int eid = c2.parag()->paragId();
01038 int eindex = c2.index();
01039 readFormats( c1, c2 );
01040
01041 textdoc->setFormat( selectionId, format, flags );
01042 if ( !undoRedoInfo.customItemsMap.isEmpty() )
01043 {
01044
01045 CustomItemsMap::Iterator it = undoRedoInfo.customItemsMap.begin();
01046 for ( ; it != undoRedoInfo.customItemsMap.end(); ++it )
01047 it.data()->resize();
01048 }
01049 KoTextFormatCommand *cmd = new KoTextFormatCommand(
01050 textdoc, id, index, eid, eindex, undoRedoInfo.text.rawData(),
01051 format, flags );
01052 textdoc->addCommand( cmd );
01053 ret = new KoTextCommand( this, i18n("Format Text") );
01054 undoRedoInfo.clear();
01055 setLastFormattedParag( c1.parag() );
01056 formatMore( 2 );
01057 emit repaintChanged( this );
01058 emit showCursor();
01059 }
01060 if ( isNewFormat ) {
01061 emit showCurrentFormat();
01062
01063 if ( cursor && cursor->index() == cursor->parag()->length() - 1 ) {
01064 newFormat->addRef();
01065 cursor->parag()->string()->setFormat( cursor->index(), newFormat, TRUE );
01066 if ( cursor->parag()->length() == 1 ) {
01067 newFormat->addRef();
01068 cursor->parag()->setFormat( newFormat );
01069 cursor->parag()->invalidate(0);
01070 cursor->parag()->format();
01071 emit repaintChanged( this );
01072 }
01073 }
01074 }
01075 return ret;
01076 }
01077
01078 void KoTextObject::setFormat( KoTextCursor * cursor, KoTextFormat ** currentFormat, KoTextFormat *format, int flags, bool zoomFont )
01079 {
01080 if ( protectContent() )
01081 return;
01082 KCommand *cmd = setFormatCommand( cursor, currentFormat, format, flags, zoomFont );
01083 if (cmd)
01084 emit newCommand( cmd );
01085 }
01086
01087 void KoTextObject::emitNewCommand(KCommand *cmd)
01088 {
01089 if(cmd)
01090 emit newCommand( cmd );
01091 }
01092
01093 KCommand *KoTextObject::setCounterCommand( KoTextCursor * cursor, const KoParagCounter & counter, KoTextDocument::SelectionId selectionId )
01094 {
01095 if ( protectContent() )
01096 return 0L;
01097 const KoParagCounter * curCounter = 0L;
01098 if(cursor)
01099 curCounter=cursor->parag()->counter();
01100 if ( !textdoc->hasSelection( selectionId, true ) &&
01101 curCounter && counter == *curCounter ) {
01102 return 0L;
01103 }
01104 emit hideCursor();
01105 storeParagUndoRedoInfo( cursor, selectionId );
01106 if ( !textdoc->hasSelection( selectionId, true ) && cursor) {
01107 cursor->parag()->setCounter( counter );
01108 setLastFormattedParag( cursor->parag() );
01109 } else {
01110 KoTextParag *start = textdoc->selectionStart( selectionId );
01111 KoTextParag *end = textdoc->selectionEnd( selectionId );
01112 #if 0
01113
01114 if ( start != end && end->length() <= 1 )
01115 {
01116 end = end->prev();
01117 undoRedoInfo.eid = end->paragId();
01118 }
01119 #endif
01120 setLastFormattedParag( start );
01121 for ( ; start && start != end->next() ; start = start->next() )
01122 {
01123 if ( start->length() > 1 )
01124 start->setCounter( counter );
01125 }
01126 }
01127 formatMore( 2 );
01128 emit repaintChanged( this );
01129 if ( !undoRedoInfo.newParagLayout.counter )
01130 undoRedoInfo.newParagLayout.counter = new KoParagCounter;
01131 *undoRedoInfo.newParagLayout.counter = counter;
01132 KoTextParagCommand *cmd = new KoTextParagCommand(
01133 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01134 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01135 KoParagLayout::BulletNumber );
01136 textdoc->addCommand( cmd );
01137
01138 undoRedoInfo.clear();
01139 emit showCursor();
01140 emit updateUI( true );
01141 return new KoTextCommand( this, i18n("Change List Type") );
01142 }
01143
01144 KCommand * KoTextObject::setAlignCommand( KoTextCursor * cursor, int align, KoTextDocument::SelectionId selectionId )
01145 {
01146 if ( protectContent() )
01147 return 0L;
01148 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01149 (int)cursor->parag()->alignment() == align )
01150 return 0L;
01151
01152 emit hideCursor();
01153 storeParagUndoRedoInfo( cursor ,selectionId );
01154 if ( !textdoc->hasSelection( selectionId, true ) &&cursor ) {
01155 cursor->parag()->setAlign(align);
01156 setLastFormattedParag( cursor->parag() );
01157 }
01158 else
01159 {
01160 KoTextParag *start = textdoc->selectionStart( selectionId );
01161 KoTextParag *end = textdoc->selectionEnd( selectionId );
01162 setLastFormattedParag( start );
01163 for ( ; start && start != end->next() ; start = start->next() )
01164 start->setAlign(align);
01165 }
01166 formatMore( 2 );
01167 emit repaintChanged( this );
01168 undoRedoInfo.newParagLayout.alignment = align;
01169 KoTextParagCommand *cmd = new KoTextParagCommand(
01170 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01171 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01172 KoParagLayout::Alignment );
01173 textdoc->addCommand( cmd );
01174 undoRedoInfo.clear();
01175 emit showCursor();
01176 emit updateUI( true );
01177 return new KoTextCommand( this, i18n("Change Alignment") );
01178 }
01179
01180 KCommand * KoTextObject::setMarginCommand( KoTextCursor * cursor, QStyleSheetItem::Margin m, double margin , KoTextDocument::SelectionId selectionId ) {
01181 if ( protectContent() )
01182 return 0L;
01183
01184
01185
01186 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01187 cursor->parag()->margin(m) == margin )
01188 return 0L;
01189
01190 emit hideCursor();
01191 storeParagUndoRedoInfo( cursor, selectionId );
01192 if ( !textdoc->hasSelection( selectionId, true )&&cursor ) {
01193 cursor->parag()->setMargin(m, margin);
01194 setLastFormattedParag( cursor->parag() );
01195 }
01196 else
01197 {
01198 KoTextParag *start = textdoc->selectionStart( selectionId );
01199 KoTextParag *end = textdoc->selectionEnd( selectionId );
01200 setLastFormattedParag( start );
01201 for ( ; start && start != end->next() ; start = start->next() )
01202 start->setMargin(m, margin);
01203 }
01204 formatMore( 2 );
01205 emit repaintChanged( this );
01206 undoRedoInfo.newParagLayout.margins[m] = margin;
01207 KoTextParagCommand *cmd = new KoTextParagCommand(
01208 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01209 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01210 KoParagLayout::Margins, m );
01211 textdoc->addCommand( cmd );
01212 QString name;
01213 if ( m == QStyleSheetItem::MarginFirstLine )
01214 name = i18n("Change First Line Indent");
01215 else if ( m == QStyleSheetItem::MarginLeft || m == QStyleSheetItem::MarginRight )
01216 name = i18n("Change Indent");
01217 else
01218 name = i18n("Change Paragraph Spacing");
01219 undoRedoInfo.clear();
01220 emit showCursor();
01221 emit updateUI( true );
01222 return new KoTextCommand( this, name );
01223 }
01224
01225 KCommand * KoTextObject::setBackgroundColorCommand( KoTextCursor * cursor,
01226 const QColor & color,
01227 KoTextDocument::SelectionId selectionId ) {
01228 if ( protectContent() )
01229 return 0L;
01230
01231 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01232 cursor->parag()->backgroundColor() == color )
01233 return 0L;
01234
01235 emit hideCursor();
01236 storeParagUndoRedoInfo( cursor, selectionId );
01237 if ( !textdoc->hasSelection( selectionId, true )&&cursor )
01238 {
01239
01240 cursor->parag()->setBackgroundColor(color);
01241 setLastFormattedParag( cursor->parag() );
01242 }
01243 else
01244 {
01245
01246 KoTextParag *start = textdoc->selectionStart( selectionId );
01247 KoTextParag *end = textdoc->selectionEnd( selectionId );
01248 setLastFormattedParag( start );
01249 for ( ; start && start != end->next() ; start = start->next() )
01250 start->setBackgroundColor(color);
01251 }
01252 formatMore( 2 );
01253 emit repaintChanged( this );
01254
01255
01256 undoRedoInfo.newParagLayout.backgroundColor = color;
01257 KoTextParagCommand *cmd = new KoTextParagCommand(
01258 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01259 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01260 KoParagLayout::BackgroundColor );
01261 textdoc->addCommand( cmd );
01262 undoRedoInfo.clear();
01263
01264 emit showCursor();
01265 emit updateUI( true );
01266 return new KoTextCommand( this, i18n("Change Paragraph Background Color" ) );
01267 }
01268
01269 KCommand * KoTextObject::setLineSpacingCommand( KoTextCursor * cursor, double spacing, KoParagLayout::SpacingType _type, KoTextDocument::SelectionId selectionId )
01270 {
01271 if ( protectContent() )
01272 return 0L;
01273
01274
01275
01276
01277 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01278 cursor->parag()->kwLineSpacing() == spacing
01279 && cursor->parag()->kwLineSpacingType() == _type)
01280 return 0L;
01281
01282 emit hideCursor();
01283 storeParagUndoRedoInfo( cursor, selectionId );
01284 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01285 cursor->parag()->setLineSpacing(spacing);
01286 cursor->parag()->setLineSpacingType( _type);
01287 setLastFormattedParag( cursor->parag() );
01288 }
01289 else
01290 {
01291 KoTextParag *start = textdoc->selectionStart( selectionId );
01292 KoTextParag *end = textdoc->selectionEnd( selectionId );
01293 setLastFormattedParag( start );
01294 for ( ; start && start != end->next() ; start = start->next() )
01295 {
01296 start->setLineSpacing(spacing);
01297 start->setLineSpacingType( _type);
01298 }
01299 }
01300 formatMore( 2 );
01301 emit repaintChanged( this );
01302 undoRedoInfo.newParagLayout.setLineSpacingValue( spacing );
01303 undoRedoInfo.newParagLayout.lineSpacingType = _type;
01304 KoTextParagCommand *cmd = new KoTextParagCommand(
01305 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01306 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01307 KoParagLayout::LineSpacing );
01308 textdoc->addCommand( cmd );
01309
01310 undoRedoInfo.clear();
01311 emit showCursor();
01312 return new KoTextCommand( this, i18n("Change Line Spacing") );
01313 }
01314
01315
01316 KCommand * KoTextObject::setBordersCommand( KoTextCursor * cursor, const KoBorder& leftBorder, const KoBorder& rightBorder, const KoBorder& topBorder, const KoBorder& bottomBorder , KoTextDocument::SelectionId selectionId )
01317 {
01318 if ( protectContent() )
01319 return 0L;
01320 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01321 cursor->parag()->leftBorder() ==leftBorder &&
01322 cursor->parag()->rightBorder() ==rightBorder &&
01323 cursor->parag()->topBorder() ==topBorder &&
01324 cursor->parag()->bottomBorder() ==bottomBorder )
01325 return 0L;
01326
01327 emit hideCursor();
01328 bool borderOutline = false;
01329 storeParagUndoRedoInfo( cursor, selectionId );
01330 if ( !textdoc->hasSelection( selectionId, true ) ) {
01331 cursor->parag()->setLeftBorder(leftBorder);
01332 cursor->parag()->setRightBorder(rightBorder);
01333 cursor->parag()->setBottomBorder(bottomBorder);
01334 cursor->parag()->setTopBorder(topBorder);
01335 setLastFormattedParag( cursor->parag() );
01336
01337 if ( cursor->parag()->next() )
01338 cursor->parag()->next()->setChanged( true );
01339 if ( cursor->parag()->prev() )
01340 cursor->parag()->prev()->setChanged( true );
01341 }
01342 else
01343 {
01344 KoTextParag *start = textdoc->selectionStart( selectionId );
01345 KoTextParag *end = textdoc->selectionEnd( selectionId );
01346 setLastFormattedParag( start );
01347 KoBorder tmpBorder;
01348 tmpBorder.setPenWidth(0);
01349 for ( ; start && start != end->next() ; start = start->next() )
01350 {
01351 start->setLeftBorder(leftBorder);
01352 start->setRightBorder(rightBorder);
01353
01354 start->setTopBorder(tmpBorder);
01355 start->setBottomBorder(tmpBorder);
01356 }
01357 end->setBottomBorder(bottomBorder);
01358 textdoc->selectionStart( selectionId )->setTopBorder(topBorder);
01359 borderOutline = true;
01360
01361 if ( start && start->prev() )
01362 start->prev()->setChanged( true );
01363 if ( end && end->next() )
01364 end->next()->setChanged( true );
01365 }
01366 formatMore( 2 );
01367 emit repaintChanged( this );
01368 undoRedoInfo.newParagLayout.leftBorder=leftBorder;
01369 undoRedoInfo.newParagLayout.rightBorder=rightBorder;
01370 undoRedoInfo.newParagLayout.topBorder=topBorder;
01371 undoRedoInfo.newParagLayout.bottomBorder=bottomBorder;
01372
01373 KoTextParagCommand *cmd = new KoTextParagCommand(
01374 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01375 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01376 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1, borderOutline);
01377 textdoc->addCommand( cmd );
01378
01379 undoRedoInfo.clear();
01380 emit showCursor();
01381 emit updateUI( true );
01382 return new KoTextCommand( this, i18n("Change Borders") );
01383 }
01384
01385 KCommand * KoTextObject::setJoinBordersCommand( KoTextCursor * cursor, bool join, KoTextDocument::SelectionId selectionId )
01386 {
01387 if ( protectContent() )
01388 return 0L;
01389 if ( !textdoc->hasSelection( selectionId, true ) &&
01390 cursor && cursor->parag()->joinBorder() == join )
01391 return 0L;
01392
01393 emit hideCursor();
01394 bool borderOutline = false;
01395 storeParagUndoRedoInfo( cursor, KoTextDocument::Standard );
01396 if ( !textdoc->hasSelection( selectionId, true ) )
01397 {
01398 cursor->parag()->setJoinBorder( join );
01399 setLastFormattedParag( cursor->parag() );
01400
01401 if ( cursor->parag()->next() )
01402 cursor->parag()->next()->setChanged( true );
01403 if ( cursor->parag()->prev() )
01404 cursor->parag()->prev()->setChanged( true );
01405 }
01406 else
01407 {
01408 KoTextParag *start = textdoc->selectionStart( selectionId );
01409 KoTextParag *end = textdoc->selectionEnd( selectionId );
01410 setLastFormattedParag( start );
01411 for ( ; start && start != end->next() ; start = start->next() )
01412 {
01413 start->setJoinBorder( true );
01414 }
01415 end->setJoinBorder ( true );
01416 borderOutline = true;
01417
01418 if ( start && start->prev() )
01419 start->prev()->setChanged( true );
01420 if ( end && end->next() )
01421 end->next()->setChanged( true );
01422 }
01423 formatMore( 2 );
01424
01425 emit repaintChanged( this );
01426 undoRedoInfo.newParagLayout.joinBorder=join;
01427
01428 KoTextParagCommand *cmd = new KoTextParagCommand(
01429 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01430 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01431 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1, borderOutline);
01432 textdoc->addCommand( cmd );
01433
01434 undoRedoInfo.clear();
01435 emit ensureCursorVisible();
01436 emit showCursor();
01437 emit updateUI( true );
01438 return new KoTextCommand( this, i18n("Change Join Borders") );
01439 }
01440
01441
01442 KCommand * KoTextObject::setTabListCommand( KoTextCursor * cursor, const KoTabulatorList &tabList, KoTextDocument::SelectionId selectionId )
01443 {
01444 if ( protectContent() )
01445 return 0L;
01446 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01447 cursor->parag()->tabList() == tabList )
01448 return 0L;
01449
01450 emit hideCursor();
01451 storeParagUndoRedoInfo( cursor, selectionId );
01452
01453 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01454 cursor->parag()->setTabList( tabList );
01455 setLastFormattedParag( cursor->parag() );
01456 }
01457 else
01458 {
01459 KoTextParag *start = textdoc->selectionStart( selectionId );
01460 KoTextParag *end = textdoc->selectionEnd( selectionId );
01461 setLastFormattedParag( start );
01462 for ( ; start && start != end->next() ; start = start->next() )
01463 start->setTabList( tabList );
01464 }
01465
01466 formatMore( 2 );
01467 emit repaintChanged( this );
01468 undoRedoInfo.newParagLayout.setTabList( tabList );
01469 KoTextParagCommand *cmd = new KoTextParagCommand(
01470 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01471 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01472 KoParagLayout::Tabulator);
01473 textdoc->addCommand( cmd );
01474 undoRedoInfo.clear();
01475 emit showCursor();
01476 emit updateUI( true );
01477 return new KoTextCommand( this, i18n("Change Tabulator") );
01478 }
01479
01480 KCommand * KoTextObject::setParagDirectionCommand( KoTextCursor * cursor, QChar::Direction d, KoTextDocument::SelectionId selectionId )
01481 {
01482 if ( protectContent() )
01483 return 0L;
01484 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01485 cursor->parag()->direction() == d )
01486 return 0L;
01487
01488 emit hideCursor();
01489 storeParagUndoRedoInfo( cursor, selectionId );
01490
01491 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01492 cursor->parag()->setDirection( d );
01493 setLastFormattedParag( cursor->parag() );
01494 }
01495 else
01496 {
01497 KoTextParag *start = textdoc->selectionStart( selectionId );
01498 KoTextParag *end = textdoc->selectionEnd( selectionId );
01499 setLastFormattedParag( start );
01500 for ( ; start && start != end->next() ; start = start->next() )
01501 start->setDirection( d );
01502 }
01503
01504 formatMore( 2 );
01505 emit repaintChanged( this );
01507 #if 0
01508 undoRedoInfo.newParagLayout.direction = d;
01509 KoTextParagCommand *cmd = new KoTextParagCommand(
01510 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01511 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01512 KoParagLayout::Shadow);
01513 textdoc->addCommand( cmd );
01514 #endif
01515 undoRedoInfo.clear();
01516 emit showCursor();
01517 emit updateUI( true );
01518 #if 0
01519 return new KoTextCommand( this, i18n("Change Shadow") );
01520 #else
01521 return 0L;
01522 #endif
01523 }
01524
01525 void KoTextObject::removeSelectedText( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId, const QString & cmdName, bool createUndoRedo )
01526 {
01527 if ( protectContent() )
01528 return ;
01529 emit hideCursor();
01530 if( createUndoRedo)
01531 {
01532 checkUndoRedoInfo( cursor, UndoRedoInfo::RemoveSelected );
01533 if ( !undoRedoInfo.valid() ) {
01534 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index );
01535 undoRedoInfo.text = QString::null;
01536 newPlaceHolderCommand( cmdName.isNull() ? i18n("Remove Selected Text") : cmdName );
01537 }
01538 }
01539 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01540 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01541 readFormats( c1, c2, true, true );
01542
01543
01544 textdoc->removeSelectedText( selectionId, cursor );
01545
01546 setLastFormattedParag( cursor->parag() );
01547 formatMore( 2 );
01548 emit repaintChanged( this );
01549 emit ensureCursorVisible();
01550 emit updateUI( true );
01551 emit showCursor();
01552 if(selectionId==KoTextDocument::Standard || selectionId==KoTextDocument::InputMethodPreedit)
01553 selectionChangedNotify();
01554 if ( createUndoRedo)
01555 undoRedoInfo.clear();
01556 }
01557
01558 KCommand * KoTextObject::removeSelectedTextCommand( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId, bool repaint )
01559 {
01560 if ( protectContent() )
01561 return 0L;
01562 if ( !textdoc->hasSelection( selectionId, true ) )
01563 return 0L;
01564
01565 undoRedoInfo.clear();
01566 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index );
01567 Q_ASSERT( undoRedoInfo.id >= 0 );
01568
01569 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01570 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01571 readFormats( c1, c2, true, true );
01572
01573 textdoc->removeSelectedText( selectionId, cursor );
01574
01575 KMacroCommand *macroCmd = new KMacroCommand( i18n("Remove Selected Text") );
01576
01577 KoTextDocCommand *cmd = deleteTextCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index,
01578 undoRedoInfo.text.rawData(),
01579 undoRedoInfo.customItemsMap,
01580 undoRedoInfo.oldParagLayouts );
01581 textdoc->addCommand(cmd);
01582 macroCmd->addCommand(new KoTextCommand( this, QString::null ));
01583
01584 if(!undoRedoInfo.customItemsMap.isEmpty())
01585 undoRedoInfo.customItemsMap.deleteAll( macroCmd );
01586
01587 undoRedoInfo.type = UndoRedoInfo::Invalid;
01588 undoRedoInfo.clear();
01589 if ( repaint )
01590 selectionChangedNotify();
01591 return macroCmd;
01592 }
01593
01594 KCommand* KoTextObject::replaceSelectionCommand( KoTextCursor * cursor, const QString & replacement,
01595 const QString & cmdName,
01596 KoTextDocument::SelectionId selectionId,
01597 int insertFlags,
01598 CustomItemsMap customItemsMap )
01599 {
01600 if ( protectContent() )
01601 return 0L;
01602 Q_ASSERT( ( insertFlags & DoNotRemoveSelected ) == 0 );
01603 const bool repaint = ( insertFlags & DoNotRepaint ) == 0;
01604 if ( repaint )
01605 emit hideCursor();
01606
01607 KMacroCommand * macroCmd = new KMacroCommand( cmdName );
01608
01609
01610 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01611 KoTextFormat * format = c1.parag()->at( c1.index() )->format();
01612 format->addRef();
01613
01614
01615 KCommand* removeSelCmd = removeSelectedTextCommand( cursor, selectionId, repaint );
01616 if ( removeSelCmd )
01617 macroCmd->addCommand( removeSelCmd );
01618
01619
01620 insert( cursor, format,
01621 replacement, QString::null ,
01622 selectionId, insertFlags | DoNotRemoveSelected, customItemsMap );
01623
01624 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index,
01625 undoRedoInfo.text.rawData(),
01626 CustomItemsMap(), undoRedoInfo.oldParagLayouts );
01627 textdoc->addCommand( cmd );
01628 macroCmd->addCommand( new KoTextCommand( this, QString::null ) );
01629
01630 undoRedoInfo.type = UndoRedoInfo::Invalid;
01631 undoRedoInfo.clear();
01632
01633 format->removeRef();
01634
01635 setLastFormattedParag( c1.parag() );
01636 if ( repaint )
01637 {
01638 formatMore( 2 );
01639 emit repaintChanged( this );
01640 emit ensureCursorVisible();
01641 emit updateUI( true );
01642 emit showCursor();
01643 if(selectionId==KoTextDocument::Standard)
01644 selectionChangedNotify();
01645 }
01646 return macroCmd;
01647 }
01648
01649 KCommand * KoTextObject::insertParagraphCommand( KoTextCursor *cursor )
01650 {
01651 if ( protectContent() )
01652 return 0L;
01653 return replaceSelectionCommand( cursor, "\n", QString::null, KoTextDocument::Standard, CheckNewLine );
01654 }
01655
01656 void KoTextObject::highlightPortion( KoTextParag * parag, int index, int length, bool repaint )
01657 {
01658 if ( !m_highlightSelectionAdded )
01659 {
01660 textdoc->addSelection( KoTextDocument::HighlightSelection );
01661 textdoc->setSelectionColor( KoTextDocument::HighlightSelection,
01662 QApplication::palette().color( QPalette::Active, QColorGroup::Dark ) );
01663 textdoc->setInvertSelectionText( KoTextDocument::HighlightSelection, true );
01664 m_highlightSelectionAdded = true;
01665 }
01666
01667 removeHighlight(repaint);
01668 KoTextCursor cursor( textdoc );
01669 cursor.setParag( parag );
01670 cursor.setIndex( index );
01671 textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
01672 cursor.setIndex( index + length );
01673 textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
01674 if ( repaint ) {
01675 parag->setChanged( true );
01676 emit repaintChanged( this );
01677 }
01678 }
01679
01680 void KoTextObject::removeHighlight(bool repaint)
01681 {
01682 if ( textdoc->hasSelection( KoTextDocument::HighlightSelection, true ) )
01683 {
01684 KoTextParag * oldParag = textdoc->selectionStart( KoTextDocument::HighlightSelection );
01685 oldParag->setChanged( true );
01686 textdoc->removeSelection( KoTextDocument::HighlightSelection );
01687 }
01688 if ( repaint )
01689 emit repaintChanged( this );
01690 }
01691
01692 void KoTextObject::selectAll( bool select )
01693 {
01694 if ( !select )
01695 textdoc->removeSelection( KoTextDocument::Standard );
01696 else
01697 textdoc->selectAll( KoTextDocument::Standard );
01698 selectionChangedNotify();
01699 }
01700
01701 void KoTextObject::selectionChangedNotify( bool enableActions )
01702 {
01703 emit repaintChanged( this );
01704 if ( enableActions )
01705 emit selectionChanged( hasSelection() );
01706 }
01707
01708 void KoTextObject::setViewArea( QWidget* w, int maxY )
01709 {
01710 m_mapViewAreas.replace( w, maxY );
01711 }
01712
01713 void KoTextObject::setLastFormattedParag( KoTextParag *parag )
01714 {
01715
01716 if ( !m_lastFormatted || !parag || m_lastFormatted->paragId() >= parag->paragId() ) {
01717 m_lastFormatted = parag;
01718 }
01719 }
01720
01721 void KoTextObject::ensureFormatted( KoTextParag * parag, bool emitAfterFormatting )
01722 {
01723 if ( !textdoc->lastParag() )
01724 return;
01725
01726 if ( !parag->isValid() && m_lastFormatted == 0 )
01727 m_lastFormatted = parag;
01728
01729 while ( !parag->isValid() )
01730 {
01731 if ( !m_lastFormatted ) {
01732 kdWarning() << "ensureFormatted for parag " << parag << " " << parag->paragId() << " still not formatted, but m_lastFormatted==0" << endl;
01733 return;
01734 }
01735
01736 bool ret = formatMore( QMAX( 1, parag->paragId() - m_lastFormatted->paragId() ), emitAfterFormatting );
01737 if ( !ret ) {
01738
01739 break;
01740 }
01741 }
01742
01743 }
01744
01745 bool KoTextObject::formatMore( int count , bool emitAfterFormatting )
01746 {
01747 if ( ( !m_lastFormatted && d->afterFormattingEmitted )
01748 || !m_visible || m_availableHeight == -1 )
01749 return false;
01750
01751 if ( !textdoc->lastParag() )
01752 return false;
01753
01754 if ( d->abortFormatting ) {
01755 d->abortFormatting = false;
01756 return false;
01757 }
01758
01759 if ( count == 0 )
01760 {
01761 formatTimer->start( interval, TRUE );
01762 return true;
01763 }
01764
01765 int bottom = 0;
01766 if ( m_lastFormatted )
01767 {
01768 d->afterFormattingEmitted = false;
01769
01770 int viewsBottom = 0;
01771 QMapIterator<QWidget *, int> mapIt = m_mapViewAreas.begin();
01772 for ( ; mapIt != m_mapViewAreas.end() ; ++mapIt )
01773 viewsBottom = QMAX( viewsBottom, mapIt.data() );
01774
01775 #ifdef DEBUG_FORMAT_MORE
01776 kdDebug(32500) << "formatMore " << name()
01777 << " lastFormatted id=" << m_lastFormatted->paragId()
01778 << " lastFormatted's top=" << m_lastFormatted->rect().top()
01779 << " lastFormatted's height=" << m_lastFormatted->rect().height()
01780 << " count=" << count << " viewsBottom=" << viewsBottom
01781 << " availableHeight=" << m_availableHeight << endl;
01782 #endif
01783 if ( m_lastFormatted->prev() == 0 )
01784 {
01785 emit formattingFirstParag();
01786 #ifdef TIMING_FORMAT
01787 kdDebug(32500) << "formatMore " << name() << ". First parag -> starting timer" << endl;
01788 m_time.start();
01789 #endif
01790 }
01791
01792
01793
01794
01795 int i;
01796 for ( i = 0;
01797 m_lastFormatted && bottom + m_lastFormatted->rect().height() <= m_availableHeight &&
01798 ( i < count || bottom <= viewsBottom ) ; ++i )
01799 {
01800 KoTextParag* parag = m_lastFormatted;
01801 #ifdef DEBUG_FORMAT_MORE
01802 kdDebug(32500) << "formatMore formatting " << parag << " id=" << parag->paragId() << endl;
01803 #endif
01804 assert( parag->string() );
01805 parag->format();
01806 bottom = parag->rect().top() + parag->rect().height();
01807 #if 0 //def DEBUG_FORMAT_MORE
01808 kdDebug(32500) << "formatMore(inside) top=" << parag->rect().top()
01809 << " height=" << parag->rect().height()
01810 << " bottom=" << bottom << " m_lastFormatted(next parag) = " << m_lastFormatted->next() << endl;
01811 #endif
01812
01813
01814 if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_CHAPTER
01815 && parag->counter()->depth() == 0 )
01816 emit chapterParagraphFormatted( parag );
01817
01818 if ( d->abortFormatting ) {
01819 #ifdef DEBUG_FORMAT_MORE
01820 kdDebug(32500) << "formatMore formatting aborted. " << endl;
01821 #endif
01822 d->abortFormatting = false;
01823 return false;
01824 }
01825
01826 if ( parag != m_lastFormatted )
01827 kdWarning() << "Some code changed m_lastFormatted during formatting! Was " << parag->paragId() << ", is now " << m_lastFormatted->paragId() << endl;
01828 #if 0 // This happens now that formatting can 'abort' (e.g. due to page not yet created)
01829 else if (!parag->isValid())
01830 kdWarning() << "PARAGRAPH " << parag->paragId() << " STILL INVALID AFTER FORMATTING" << endl;
01831 #endif
01832 m_lastFormatted = parag->next();
01833 }
01834 }
01835 else
01836 {
01837 QRect rect = textdoc->lastParag()->rect();
01838 bottom = rect.top() + rect.height();
01839 }
01840 #ifdef DEBUG_FORMAT_MORE
01841 QString id;
01842 if ( m_lastFormatted ) id = QString(" (%1)").arg(m_lastFormatted->paragId());
01843 kdDebug(32500) << "formatMore finished formatting. "
01844 << " bottom=" << bottom
01845 << " m_lastFormatted=" << m_lastFormatted << id
01846 << endl;
01847 #endif
01848
01849 if ( emitAfterFormatting )
01850 {
01851 d->afterFormattingEmitted = true;
01852 bool needMoreSpace = false;
01853
01854 if ( ( bottom > m_availableHeight ) ||
01855 ( m_lastFormatted && bottom + m_lastFormatted->rect().height() > m_availableHeight ) )
01856 needMoreSpace = true;
01857
01858 bool abort = needMoreSpace;
01859 emit afterFormatting( bottom, m_lastFormatted, &abort );
01860 if ( abort )
01861 return false;
01862 else if ( needMoreSpace && m_lastFormatted )
01863 return formatMore( 2 );
01864 }
01865
01866
01867 if ( m_lastFormatted )
01868 {
01869 formatTimer->start( interval, TRUE );
01870 #ifdef DEBUG_FORMAT_MORE
01871 kdDebug(32500) << name() << " formatMore: will have to format more. formatTimer->start with interval=" << interval << endl;
01872 #endif
01873 }
01874 else
01875 {
01876 interval = QMAX( 0, interval );
01877 #ifdef DEBUG_FORMAT_MORE
01878 kdDebug(32500) << name() << " formatMore: all formatted interval=" << interval << endl;
01879 #endif
01880 #ifdef TIMING_FORMAT
01881
01882 kdDebug(32500) << "formatMore: " << name() << " all formatted. Took "
01883 << (double)(m_time.elapsed()) / 1000 << " seconds." << endl;
01884 #endif
01885 }
01886 return true;
01887 }
01888
01889 void KoTextObject::abortFormatting()
01890 {
01891 d->abortFormatting = true;
01892 }
01893
01894 void KoTextObject::doChangeInterval()
01895 {
01896
01897 interval = 0;
01898 }
01899
01900 void KoTextObject::typingStarted()
01901 {
01902
01903 changeIntervalTimer->stop();
01904 interval = 10;
01905 }
01906
01907 void KoTextObject::typingDone()
01908 {
01909 changeIntervalTimer->start( 100, TRUE );
01910 }
01911
01912
01913
01914 KCommand *KoTextObject::changeCaseOfTextParag( int cursorPosStart, int cursorPosEnd,
01915 KoChangeCaseDia::TypeOfCase _type,
01916 KoTextCursor *cursor, KoTextParag *parag )
01917 {
01918 if ( protectContent() )
01919 return 0L;
01920
01921 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") );
01922 KoTextFormat *curFormat = parag->paragraphFormat();
01923 const QString text = parag->string()->toString().mid( cursorPosStart, cursorPosEnd - cursorPosStart );
01924 int posStart = cursorPosStart;
01925 int posEnd = cursorPosStart;
01926 KoTextCursor c1( textdoc );
01927 KoTextCursor c2( textdoc );
01928
01929 for ( int i = cursorPosStart; i < cursorPosEnd; ++i )
01930 {
01931 KoTextStringChar & ch = *(parag->at(i));
01932 KoTextFormat * newFormat = ch.format();
01933 if( ch.isCustom() )
01934 {
01935 posEnd = i;
01936 c1.setParag( parag );
01937 c1.setIndex( posStart );
01938 c2.setParag( parag );
01939 c2.setIndex( posEnd );
01940
01941
01942 const QString repl = text.mid( posStart, posEnd - posStart );
01943 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01944 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01945 macroCmd->addCommand(replaceSelectionCommand(
01946 cursor, textChangedCase(repl,_type),
01947 QString::null, KoTextDocument::Temp));
01948 do
01949 {
01950 ++i;
01951 }
01952 while( parag->at(i)->isCustom() && i != cursorPosEnd);
01953 posStart=i;
01954 posEnd=i;
01955 }
01956 else
01957 {
01958 if ( newFormat != curFormat )
01959 {
01960 posEnd=i;
01961 c1.setParag( parag );
01962 c1.setIndex( posStart );
01963 c2.setParag( parag );
01964 c2.setIndex( posEnd );
01965
01966
01967 const QString repl = text.mid( posStart, posEnd - posStart );
01968 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01969 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01970 macroCmd->addCommand(replaceSelectionCommand(
01971 cursor, textChangedCase(repl,_type),
01972 QString::null, KoTextDocument::Temp));
01973 posStart=i;
01974 posEnd=i;
01975 curFormat = newFormat;
01976 }
01977 }
01978 }
01979 if ( posStart != cursorPosEnd )
01980 {
01981
01982 c1.setParag( parag );
01983 c1.setIndex( posStart );
01984 c2.setParag( parag );
01985 c2.setIndex( cursorPosEnd );
01986
01987 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01988 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01989 const QString repl = text.mid( posStart, cursorPosEnd - posStart );
01990 macroCmd->addCommand(replaceSelectionCommand(
01991 cursor, textChangedCase(repl,_type),
01992 QString::null, KoTextDocument::Temp));
01993 }
01994 return macroCmd;
01995
01996 }
01997
01998 KCommand *KoTextObject::changeCaseOfText(KoTextCursor *cursor,KoChangeCaseDia::TypeOfCase _type)
01999 {
02000 if ( protectContent() )
02001 return 0L;
02002 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") );
02003
02004 KoTextCursor start = textdoc->selectionStartCursor( KoTextDocument::Standard );
02005 KoTextCursor end = textdoc->selectionEndCursor( KoTextDocument::Standard );
02006 emit hideCursor();
02007
02008 if ( start.parag() == end.parag() )
02009 {
02010 int endIndex = QMIN( start.parag()->length() - 1, end.index() );
02011 macroCmd->addCommand( changeCaseOfTextParag( start.index(), endIndex, _type,
02012 cursor, start.parag() ) );
02013 }
02014 else
02015 {
02016 macroCmd->addCommand( changeCaseOfTextParag( start.index(), start.parag()->length() - 1, _type,
02017 cursor, start.parag() ) );
02018 KoTextParag *p = start.parag()->next();
02019 while ( p && p != end.parag() )
02020 {
02021 macroCmd->addCommand( changeCaseOfTextParag(0, p->length() - 1, _type, cursor, p ) );
02022 p = p->next();
02023 }
02024 if ( p )
02025 {
02026 int endIndex = QMIN( p->length() - 1, end.index() );
02027 macroCmd->addCommand( changeCaseOfTextParag(0, endIndex, _type, cursor, end.parag() ));
02028 }
02029 }
02030 formatMore( 2 );
02031 emit repaintChanged( this );
02032 emit ensureCursorVisible();
02033 emit updateUI( true );
02034 emit showCursor();
02035 return macroCmd;
02036 }
02037
02038 QString KoTextObject::textChangedCase(const QString& _text,KoChangeCaseDia::TypeOfCase _type)
02039 {
02040 QString text(_text);
02041 switch(_type)
02042 {
02043 case KoChangeCaseDia::UpperCase:
02044 text=text.upper();
02045 break;
02046 case KoChangeCaseDia::LowerCase:
02047 text=text.lower();
02048 break;
02049 case KoChangeCaseDia::TitleCase:
02050 for(uint i=0;i<text.length();i++)
02051 {
02052 if(text.at(i)!=' ')
02053 {
02054 QChar prev = text.at(QMAX(i-1,0));
02055 if(i==0 || prev == ' ' || prev == '\n' || prev == '\t')
02056 text=text.replace(i, 1, text.at(i).upper() );
02057 else
02058 text=text.replace(i, 1, text.at(i).lower() );
02059 }
02060 }
02061 break;
02062 case KoChangeCaseDia::ToggleCase:
02063 for(uint i=0;i<text.length();i++)
02064 {
02065 QString repl=QString(text.at(i));
02066 if(text.at(i)!=text.at(i).upper())
02067 repl=repl.upper();
02068 else if(text.at(i).lower()!=text.at(i))
02069 repl=repl.lower();
02070 text=text.replace(i, 1, repl );
02071 }
02072 break;
02073 case KoChangeCaseDia::SentenceCase:
02074 for(uint i=0;i<text.length();i++)
02075 {
02076 if(text.at(i)!=' ')
02077 {
02078 QChar prev = text.at(QMAX(i-1,0));
02079 if(i==0 || prev == '\n' ||prev.isPunct())
02080 text=text.replace(i, 1, text.at(i).upper() );
02081 }
02082 }
02083 break;
02084 default:
02085 kdDebug(32500)<<"Error in changeCaseOfText !\n";
02086 break;
02087
02088 }
02089 return text;
02090 }
02091
02092
02093 KoTextFormat * KoTextObject::currentFormat() const
02094 {
02095
02096
02097 KoTextStringChar *ch = textdoc->firstParag()->at( 0 );
02098 return ch->format();
02099 }
02100
02101 const KoParagLayout * KoTextObject::currentParagLayoutFormat() const
02102 {
02103 KoTextParag * parag = textdoc->firstParag();
02104 return &(parag->paragLayout());
02105 }
02106
02107 bool KoTextObject::rtl() const
02108 {
02109 return textdoc->firstParag()->string()->isRightToLeft();
02110 }
02111
02112 void KoTextObject::loadOasisContent( const QDomElement &bodyElem, KoOasisContext& context, KoStyleCollection * styleColl )
02113 {
02114 textDocument()->clear(false);
02115 setLastFormattedParag( 0L );
02116
02117 KoTextParag *lastParagraph = textDocument()->loadOasisText( bodyElem, context, 0, styleColl, 0 );
02118
02119 if ( !lastParagraph )
02120 {
02121
02122 textDocument()->clear( true );
02123 textDocument()->firstParag()->setStyle( styleColl->findStyle( "Standard" ) );
02124 }
02125 else
02126 textDocument()->setLastParag( lastParagraph );
02127
02128 setLastFormattedParag( textDocument()->firstParag() );
02129 }
02130
02131 KoTextCursor KoTextObject::pasteOasisText( const QDomElement &bodyElem, KoOasisContext& context,
02132 KoTextCursor& cursor, KoStyleCollection * styleColl )
02133 {
02134 KoTextCursor resultCursor( cursor );
02135 KoTextParag* lastParagraph = cursor.parag();
02136 bool removeNewline = false;
02137 uint pos = cursor.index();
02138 if ( pos == 0 && lastParagraph->length() <= 1 ) {
02139
02140 lastParagraph = lastParagraph->prev();
02141 lastParagraph = textDocument()->loadOasisText( bodyElem, context, lastParagraph, styleColl, cursor.parag() );
02142 if ( lastParagraph ) {
02143 resultCursor.setParag( lastParagraph );
02144 resultCursor.setIndex( lastParagraph->length() - 1 );
02145 }
02146 removeNewline = true;
02147 } else {
02148
02149
02150 for ( QDomNode text (bodyElem.firstChild()); !text.isNull(); text = text.nextSibling() )
02151 {
02152 QDomElement tag = text.toElement();
02153 if ( tag.isNull() ) continue;
02154
02155
02156
02157 QDomElement tagToLoad = tag;
02158 if ( tag.localName() == "numbered-paragraph" ) {
02159 QDomElement npchild;
02160 forEachElement( npchild, tag )
02161 {
02162 if ( npchild.localName() == "p" || npchild.localName() == "h" ) {
02163 tagToLoad = npchild;
02164 break;
02165 }
02166 }
02167 }
02168
02169 if ( tagToLoad.localName() == "p" || tagToLoad.localName() == "h" ) {
02170 context.styleStack().save();
02171 context.fillStyleStack( tagToLoad, KoXmlNS::text, "style-name", "paragraph" );
02172
02173
02174 lastParagraph->loadOasisSpan( tagToLoad, context, pos, true );
02175 context.styleStack().restore();
02176
02177 lastParagraph->setChanged( true );
02178 lastParagraph->invalidate( 0 );
02179
02180
02181 resultCursor.setParag( lastParagraph );
02182 resultCursor.setIndex( pos );
02183 resultCursor.splitAndInsertEmptyParag( FALSE, TRUE );
02184 removeNewline = true;
02185
02186
02187 const_cast<QDomElement &>( bodyElem ).removeChild( tag );
02188 }
02189 break;
02190 }
02191 resultCursor.setParag( lastParagraph );
02192 resultCursor.setIndex( pos );
02193
02194 lastParagraph = textDocument()->loadOasisText( bodyElem, context, lastParagraph, styleColl, lastParagraph->next() );
02195 if ( lastParagraph != resultCursor.parag() )
02196 {
02197 removeNewline = true;
02198 resultCursor.setParag( lastParagraph );
02199 resultCursor.setIndex( lastParagraph->length() - 1 );
02200 }
02201 }
02202 KoTextParag* p = resultCursor.parag();
02203 if ( p ) p = p->next();
02204
02205 if ( removeNewline && resultCursor.remove() ) {
02206 if ( m_lastFormatted == p ) {
02207 m_lastFormatted = resultCursor.parag();
02208 }
02209 }
02210 return resultCursor;
02211 }
02212
02213 void KoTextObject::saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const
02214 {
02215 textDocument()->saveOasisContent( writer, context );
02216 }
02217
02218 KCommand *KoTextObject::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags,int marginIndex)
02219 {
02220 if ( protectContent() )
02221 return 0L;
02222 textdoc->selectAll( KoTextDocument::Temp );
02223 KoTextCursor *cursor = new KoTextCursor( textdoc );
02224 KCommand* cmd = setParagLayoutCommand( cursor, *newLayout, KoTextDocument::Temp,
02225 flags, marginIndex, true );
02226 textdoc->removeSelection( KoTextDocument::Temp );
02227 delete cursor;
02228 return cmd;
02229 }
02230
02231 void KoTextObject::setFormat( KoTextFormat * newFormat, int flags, bool zoomFont )
02232 {
02233 if ( protectContent() )
02234 return ;
02235
02236 textdoc->selectAll( KoTextDocument::Temp );
02237 KCommand *cmd = setFormatCommand( 0L, 0L, newFormat,
02238 flags, zoomFont, KoTextDocument::Temp );
02239 textdoc->removeSelection( KoTextDocument::Temp );
02240 if (cmd)
02241 emit newCommand( cmd );
02242
02243 KoTextFormat format = *currentFormat();
02244
02245 emit showFormatObject(format);
02246 }
02247
02248 KCommand *KoTextObject::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type)
02249 {
02250 if ( protectContent() )
02251 return 0L;
02252 textdoc->selectAll( KoTextDocument::Standard );
02253 KoTextCursor *cursor = new KoTextCursor( textdoc );
02254 KCommand* cmd = changeCaseOfText(cursor, _type);
02255 textdoc->removeSelection( KoTextDocument::Standard );
02256 delete cursor;
02257 return cmd;
02258 }
02259
02260 void KoTextObject::setNeedSpellCheck(bool b)
02261 {
02262 m_needsSpellCheck = b;
02263 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next())
02264 parag->string()->setNeedsSpellCheck( b );
02265 }
02266
02267 bool KoTextObject::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words, ulong & sentences, ulong & syllables, ulong & lines, bool selected )
02268 {
02269
02270
02271
02272 QStringList subs_syl;
02273 subs_syl << "cial" << "tia" << "cius" << "cious" << "giu" << "ion" << "iou";
02274 QStringList subs_syl_regexp;
02275 subs_syl_regexp << "sia$" << "ely$";
02276
02277 QStringList add_syl;
02278 add_syl << "ia" << "riet" << "dien" << "iu" << "io" << "ii";
02279 QStringList add_syl_regexp;
02280 add_syl_regexp << "[aeiouym]bl$" << "[aeiou]{3}" << "^mc" << "ism$"
02281 << "[^l]lien" << "^coa[dglx]." << "[^gq]ua[^auieo]" << "dnt$";
02282
02283 QString s;
02284 KoTextParag * parag = textdoc->firstParag();
02285 for ( ; parag ; parag = parag->next() )
02286 {
02287 if ( progress )
02288 {
02289 progress->setProgress(progress->progress()+1);
02290
02291 kapp->processEvents();
02292 if ( progress->wasCancelled() )
02293 return false;
02294 }
02295
02296
02297
02298
02299
02300
02301
02302 bool hasTrailingSpace = true;
02303 if ( !selected ) {
02304 s = parag->string()->toString();
02305 lines += parag->lines();
02306 } else {
02307 if ( parag->hasSelection( KoTextDocument::Standard ) ) {
02308 hasTrailingSpace = false;
02309 s = parag->string()->toString();
02310 if ( !( parag->fullSelected( KoTextDocument::Standard ) ) ) {
02311 s = s.mid( parag->selectionStart( KoTextDocument::Standard ), parag->selectionEnd( KoTextDocument::Standard ) - parag->selectionStart( KoTextDocument::Standard ) );
02312 lines+=numberOfparagraphLineSelected(parag);
02313 }
02314 else
02315 lines += parag->lines();
02316 } else {
02317 continue;
02318 }
02319 }
02320
02321
02322 for ( uint i = 0 ; i < s.length() - ( hasTrailingSpace ? 1 : 0 ) ; ++i )
02323 {
02324 QChar ch = s[i];
02325 ++charsWithSpace;
02326 if ( !ch.isSpace() )
02327 ++charsWithoutSpace;
02328 }
02329
02330
02331
02332
02333
02334
02335
02336 QRegExp re("\\s+");
02337 QStringList wordlist = QStringList::split(re, s);
02338 words += wordlist.count();
02339 re.setCaseSensitive(false);
02340 for ( QStringList::Iterator it = wordlist.begin(); it != wordlist.end(); ++it ) {
02341 QString word = *it;
02342 re.setPattern("[!?.,:_\"-]");
02343 word.remove(re);
02344 if ( word.length() <= 3 ) {
02345 syllables++;
02346 continue;
02347 }
02348 re.setPattern("e$");
02349 word.remove(re);
02350 re.setPattern("[^aeiouy]+");
02351 QStringList syls = QStringList::split(re, word);
02352 int word_syllables = 0;
02353 for ( QStringList::Iterator it = subs_syl.begin(); it != subs_syl.end(); ++it ) {
02354 if( word.find(*it, 0, false) != -1 )
02355 word_syllables--;
02356 }
02357 for ( QStringList::Iterator it = subs_syl_regexp.begin(); it != subs_syl_regexp.end(); ++it ) {
02358 re.setPattern(*it);
02359 if( word.find(re) != -1 )
02360 word_syllables--;
02361 }
02362 for ( QStringList::Iterator it = add_syl.begin(); it != add_syl.end(); ++it ) {
02363 if( word.find(*it, 0, false) != -1 )
02364 word_syllables++;
02365 }
02366 for ( QStringList::Iterator it = add_syl_regexp.begin(); it != add_syl_regexp.end(); ++it ) {
02367 re.setPattern(*it);
02368 if( word.find(re) != -1 )
02369 word_syllables++;
02370 }
02371 word_syllables += syls.count();
02372 if ( word_syllables == 0 )
02373 word_syllables = 1;
02374 syllables += word_syllables;
02375 }
02376 re.setCaseSensitive(true);
02377
02378
02379
02380 s = s.stripWhiteSpace();
02381 QChar lastchar = s.at(s.length());
02382 if( ! s.isEmpty() && ! KoAutoFormat::isMark( lastchar ) ) {
02383 s = s + ".";
02384 }
02385 re.setPattern("[.?!]+");
02386 s.replace(re, ".");
02387 re.setPattern("\\d\\.\\d");
02388 s.replace(re, "0,0");
02389 re.setPattern("[A-Z]\\.+");
02390 s.replace(re, "*");
02391 for ( uint i = 0 ; i < s.length() ; ++i )
02392 {
02393 QChar ch = s[i];
02394 if ( KoAutoFormat::isMark( ch ) )
02395 ++sentences;
02396 }
02397 }
02398 return true;
02399 }
02400
02401 int KoTextObject::numberOfparagraphLineSelected( KoTextParag *parag)
02402 {
02403 int indexOfLineStart;
02404 int lineStart;
02405 int lineEnd;
02406 KoTextCursor c1 = textdoc->selectionStartCursor( KoTextDocument::Standard );
02407 KoTextCursor c2 = textdoc->selectionEndCursor( KoTextDocument::Standard );
02408 parag->lineStartOfChar( c1.index(), &indexOfLineStart, &lineStart );
02409
02410 parag->lineStartOfChar( c2.index(), &indexOfLineStart, &lineEnd );
02411 return (lineEnd - lineStart+1);
02412 }
02413
02414 KoVariable* KoTextObject::variableAtPoint( const QPoint& iPoint ) const
02415 {
02416 KoTextCursor cursor( textDocument() );
02417 int variablePosition = -1;
02418 cursor.place( iPoint, textDocument()->firstParag(), false, &variablePosition );
02419 if ( variablePosition == -1 )
02420 return 0;
02421 return variableAtPosition( cursor.parag(), variablePosition );
02422 }
02423
02424 KoVariable* KoTextObject::variableAtPosition( KoTextParag* parag, int index ) const
02425 {
02426 KoTextStringChar * ch = parag->at( index );
02427 if ( ch->isCustom() )
02428 return dynamic_cast<KoVariable *>( ch->customItem() );
02429 return 0;
02430 }
02431
02432 const char * KoTextObject::acceptSelectionMimeType()
02433 {
02434 return "application/vnd.oasis.opendocument.";
02435 }
02436
02437 QCString KoTextObject::providesOasis( QMimeSource* mime )
02438 {
02439 const char* fmt;
02440 const char* acceptMimeType = acceptSelectionMimeType();
02441 for ( int i = 0; (fmt = mime->format(i)); ++i )
02442 {
02443 if ( QString( fmt ).startsWith( acceptMimeType ) )
02444 {
02445 return fmt;
02446 }
02447 }
02448 return "";
02449 }
02450
02451 #ifndef NDEBUG
02452 void KoTextObject::printRTDebug(int info)
02453 {
02454 KoTextParag* lastParag = 0;
02455 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next())
02456 {
02457 assert( parag->prev() == lastParag );
02458 parag->printRTDebug( info );
02459 lastParag = parag;
02460 }
02461 if ( info == 1 )
02462 textdoc->formatCollection()->debug();
02463 }
02464 #endif
02465
02467
02468 KCommand *KoTextFormatInterface::setBoldCommand(bool on)
02469 {
02470 KoTextFormat format( *currentFormat() );
02471 format.setBold( on );
02472 return setFormatCommand( &format, KoTextFormat::Bold );
02473 }
02474
02475 KCommand *KoTextFormatInterface::setItalicCommand( bool on)
02476 {
02477 KoTextFormat format( *currentFormat() );
02478 format.setItalic( on );
02479 return setFormatCommand( &format, KoTextFormat::Italic );
02480 }
02481
02482 KCommand *KoTextFormatInterface::setUnderlineCommand( bool on )
02483 {
02484 KoTextFormat format( *currentFormat() );
02485 format.setUnderlineType( on ? KoTextFormat::U_SIMPLE : KoTextFormat::U_NONE);
02486 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02487 }
02488
02489 KCommand *KoTextFormatInterface::setUnderlineColorCommand( const QColor &color )
02490 {
02491 KoTextFormat format( *currentFormat() );
02492 format.setTextUnderlineColor( color);
02493 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02494 }
02495
02496 KCommand *KoTextFormatInterface::setDoubleUnderlineCommand( bool on )
02497 {
02498 KoTextFormat format( *currentFormat() );
02499 format.setUnderlineType( on ? KoTextFormat::U_DOUBLE : KoTextFormat::U_NONE);
02500 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02501 }
02502
02503 KCommand *KoTextFormatInterface::setStrikeOutCommand( bool on )
02504 {
02505 KoTextFormat format( *currentFormat() );
02506 format.setStrikeOutType( on ? KoTextFormat::S_SIMPLE : KoTextFormat::S_NONE);
02507 return setFormatCommand( &format, KoTextFormat::StrikeOut );
02508 }
02509
02510 KCommand *KoTextFormatInterface::setTextBackgroundColorCommand(const QColor & col)
02511 {
02512 KoTextFormat format( *currentFormat() );
02513 format.setTextBackgroundColor( col );
02514 return setFormatCommand( &format, KoTextFormat::TextBackgroundColor );
02515 }
02516
02517 KCommand *KoTextFormatInterface::setPointSizeCommand( int s )
02518 {
02519 KoTextFormat format( *currentFormat() );
02520 format.setPointSize( s );
02521 return setFormatCommand( &format, KoTextFormat::Size, true );
02522 }
02523
02524 KCommand *KoTextFormatInterface::setFamilyCommand(const QString &font)
02525 {
02526 KoTextFormat format( *currentFormat() );
02527 format.setFamily( font );
02528 return setFormatCommand( &format, KoTextFormat::Family );
02529 }
02530
02531 QColor KoTextFormatInterface::textBackgroundColor() const
02532 {
02533 return currentFormat()->textBackgroundColor();
02534 }
02535
02536 QColor KoTextFormatInterface::textUnderlineColor()const
02537 {
02538 return currentFormat()->textUnderlineColor();
02539 }
02540
02541 QColor KoTextFormatInterface::textColor() const
02542 {
02543 return currentFormat()->color();
02544 }
02545
02546 bool KoTextFormatInterface::textUnderline()const
02547 {
02548 return currentFormat()->underline();
02549 }
02550
02551 bool KoTextFormatInterface::textDoubleUnderline()const
02552 {
02553 return currentFormat()->doubleUnderline();
02554 }
02555
02556 bool KoTextFormatInterface::textBold()const
02557 {
02558 return currentFormat()->font().bold();
02559 }
02560
02561 bool KoTextFormatInterface::textStrikeOut()const
02562 {
02563 return currentFormat()->font().strikeOut();
02564 }
02565
02566 bool KoTextFormatInterface::textItalic() const
02567 {
02568 return currentFormat()->font().italic();
02569 }
02570
02571 bool KoTextFormatInterface::textSubScript() const
02572 {
02573 return (currentFormat()->vAlign()==KoTextFormat::AlignSubScript);
02574 }
02575
02576 bool KoTextFormatInterface::textSuperScript() const
02577 {
02578 return (currentFormat()->vAlign()==KoTextFormat::AlignSuperScript);
02579 }
02580
02581 double KoTextFormatInterface::shadowDistanceX() const
02582 {
02583 return currentFormat()->shadowDistanceX();
02584 }
02585
02586 double KoTextFormatInterface::shadowDistanceY() const
02587 {
02588 return currentFormat()->shadowDistanceY();
02589 }
02590
02591 QColor KoTextFormatInterface::shadowColor() const
02592 {
02593 return currentFormat()->shadowColor();
02594 }
02595
02596 KoTextFormat::AttributeStyle KoTextFormatInterface::fontAttribute() const
02597 {
02598 return currentFormat()->attributeFont();
02599 }
02600
02601 double KoTextFormatInterface::relativeTextSize() const
02602 {
02603 return currentFormat()->relativeTextSize();
02604 }
02605
02606 int KoTextFormatInterface::offsetFromBaseLine()const
02607 {
02608 return currentFormat()->offsetFromBaseLine();
02609 }
02610
02611 bool KoTextFormatInterface::wordByWord()const
02612 {
02613 return currentFormat()->wordByWord();
02614 }
02615
02616 bool KoTextFormatInterface::hyphenation()const
02617 {
02618 return currentFormat()->hyphenation();
02619 }
02620
02621 KoTextFormat::UnderlineType KoTextFormatInterface::underlineType()const
02622 {
02623 return currentFormat()->underlineType();
02624 }
02625
02626 KoTextFormat::StrikeOutType KoTextFormatInterface::strikeOutType()const
02627 {
02628 return currentFormat()->strikeOutType();
02629 }
02630
02631 KoTextFormat::UnderlineStyle KoTextFormatInterface::underlineStyle()const
02632 {
02633 return currentFormat()->underlineStyle();
02634 }
02635
02636 KoTextFormat::StrikeOutStyle KoTextFormatInterface::strikeOutStyle()const
02637 {
02638 return currentFormat()->strikeOutStyle();
02639 }
02640
02641 QFont KoTextFormatInterface::textFont() const
02642 {
02643 QFont fn( currentFormat()->font() );
02644
02645
02646 return fn;
02647 }
02648
02649 QString KoTextFormatInterface::textFontFamily()const
02650 {
02651 return currentFormat()->font().family();
02652 }
02653
02654 QString KoTextFormatInterface::language() const
02655 {
02656 return currentFormat()->language();
02657 }
02658
02659 KCommand *KoTextFormatInterface::setTextColorCommand(const QColor &color)
02660 {
02661 KoTextFormat format( *currentFormat() );
02662 format.setColor( color );
02663 return setFormatCommand( &format, KoTextFormat::Color );
02664 }
02665
02666 KCommand *KoTextFormatInterface::setTextSubScriptCommand(bool on)
02667 {
02668 KoTextFormat format( *currentFormat() );
02669 if(!on)
02670 format.setVAlign(KoTextFormat::AlignNormal);
02671 else
02672 format.setVAlign(KoTextFormat::AlignSubScript);
02673 return setFormatCommand( &format, KoTextFormat::VAlign );
02674 }
02675
02676 KCommand *KoTextFormatInterface::setTextSuperScriptCommand(bool on)
02677 {
02678 KoTextFormat format( *currentFormat() );
02679 if(!on)
02680 format.setVAlign(KoTextFormat::AlignNormal);
02681 else
02682 format.setVAlign(KoTextFormat::AlignSuperScript);
02683 return setFormatCommand( &format, KoTextFormat::VAlign );
02684 }
02685
02686 KCommand *KoTextFormatInterface::setDefaultFormatCommand()
02687 {
02688 KoTextFormatCollection * coll = currentFormat()->parent();
02689 Q_ASSERT(coll);
02690 if(coll)
02691 {
02692 KoTextFormat * format = coll->defaultFormat();
02693 return setFormatCommand( format, KoTextFormat::Format );
02694 } else {
02695 kdDebug() << "useless call to setDefaultFormatCommand at: " << kdBacktrace() << endl;
02696 }
02697 return 0;
02698 }
02699
02700 KCommand *KoTextFormatInterface::setAlignCommand(int align)
02701 {
02702 KoParagLayout format( *currentParagLayoutFormat() );
02703 format.alignment=align;
02704 return setParagLayoutFormatCommand(&format,KoParagLayout::Alignment);
02705 }
02706
02707 KCommand *KoTextFormatInterface::setHyphenationCommand( bool _b )
02708 {
02709 KoTextFormat format( *currentFormat() );
02710 format.setHyphenation( _b );
02711 return setFormatCommand( &format, KoTextFormat::Hyphenation);
02712 }
02713
02714
02715 KCommand *KoTextFormatInterface::setShadowTextCommand( double shadowDistanceX, double shadowDistanceY, const QColor& shadowColor )
02716 {
02717 KoTextFormat format( *currentFormat() );
02718 format.setShadow( shadowDistanceX, shadowDistanceY, shadowColor );
02719 return setFormatCommand( &format, KoTextFormat::ShadowText );
02720 }
02721
02722 KCommand *KoTextFormatInterface::setFontAttributeCommand( KoTextFormat::AttributeStyle _att)
02723 {
02724 KoTextFormat format( *currentFormat() );
02725 format.setAttributeFont( _att );
02726 return setFormatCommand( &format, KoTextFormat::Attribute );
02727 }
02728
02729 KCommand *KoTextFormatInterface::setRelativeTextSizeCommand( double _size )
02730 {
02731 KoTextFormat format( *currentFormat() );
02732 format.setRelativeTextSize( _size );
02733 return setFormatCommand( &format, KoTextFormat::VAlign );
02734 }
02735
02736 KCommand *KoTextFormatInterface::setOffsetFromBaseLineCommand( int _offset )
02737 {
02738 KoTextFormat format( *currentFormat() );
02739 format.setOffsetFromBaseLine( _offset );
02740 return setFormatCommand( &format, KoTextFormat::OffsetFromBaseLine );
02741 }
02742
02743 KCommand *KoTextFormatInterface::setWordByWordCommand( bool _b )
02744 {
02745 KoTextFormat format( *currentFormat() );
02746 format.setWordByWord( _b );
02747 return setFormatCommand( &format, KoTextFormat::WordByWord );
02748 }
02749
02750 #if 0
02751 void KoTextFormatInterface::setAlign(int align)
02752 {
02753 KCommand *cmd = setAlignCommand( align );
02754 emitNewCommand( cmd );
02755 }
02756
02757 void KoTextFormatInterface::setMargin(QStyleSheetItem::Margin m, double margin)
02758 {
02759 KCommand *cmd = setMarginCommand( m, margin );
02760 emitNewCommand( cmd );
02761 }
02762
02763 void KoTextFormatInterface::setTabList(const KoTabulatorList & tabList )
02764 {
02765 KCommand *cmd = setTabListCommand( tabList );
02766 emitNewCommand( cmd );
02767 }
02768
02769 void KoTextFormatInterface::setCounter(const KoParagCounter & counter )
02770 {
02771 KCommand *cmd = setCounterCommand( counter );
02772 emitNewCommand( cmd );
02773 }
02774
02775 void KoTextFormatInterface::setParagLayoutFormat( KoParagLayout *newLayout, int flags, int marginIndex)
02776 {
02777 KCommand *cmd = setParagLayoutFormatCommand(newLayout, flags, marginIndex);
02778 emitNewCommand( cmd );
02779 }
02780 #endif
02781
02782 KCommand *KoTextFormatInterface::setMarginCommand(QStyleSheetItem::Margin m, double margin)
02783 {
02784 KoParagLayout format( *currentParagLayoutFormat() );
02785 format.margins[m]=margin;
02786 return setParagLayoutFormatCommand(&format,KoParagLayout::Margins,(int)m);
02787 }
02788
02789 KCommand *KoTextFormatInterface::setTabListCommand(const KoTabulatorList & tabList )
02790 {
02791 KoParagLayout format( *currentParagLayoutFormat() );
02792 format.setTabList(tabList);
02793 return setParagLayoutFormatCommand(&format,KoParagLayout::Tabulator);
02794 }
02795
02796 KCommand *KoTextFormatInterface::setCounterCommand(const KoParagCounter & counter )
02797 {
02798 KoParagLayout format( *currentParagLayoutFormat() );
02799 if(!format.counter)
02800 format.counter = new KoParagCounter;
02801 *format.counter = counter;
02802 return setParagLayoutFormatCommand(&format,KoParagLayout::BulletNumber);
02803 }
02804
02805 KCommand *KoTextFormatInterface::setLanguageCommand(const QString &_lang)
02806 {
02807 KoTextFormat format( *currentFormat() );
02808 format.setLanguage(_lang);
02809 return setFormatCommand( &format, KoTextFormat::Language );
02810 }
02811
02812 KoTextDocCommand *KoTextFormatInterface::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts )
02813 {
02814 return textdoc->deleteTextCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts );
02815 }
02816
02817 #include "KoTextObject.moc"