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 storeParagUndoRedoInfo( cursor, selectionId );
01329 if ( !textdoc->hasSelection( selectionId, true ) ) {
01330 cursor->parag()->setLeftBorder(leftBorder);
01331 cursor->parag()->setRightBorder(rightBorder);
01332 cursor->parag()->setBottomBorder(bottomBorder);
01333 cursor->parag()->setTopBorder(topBorder);
01334 setLastFormattedParag( cursor->parag() );
01335
01336 if ( cursor->parag()->next() )
01337 cursor->parag()->next()->setChanged( true );
01338 if ( cursor->parag()->prev() )
01339 cursor->parag()->prev()->setChanged( true );
01340 }
01341 else
01342 {
01343 KoTextParag *start = textdoc->selectionStart( selectionId );
01344 KoTextParag *end = textdoc->selectionEnd( selectionId );
01345 setLastFormattedParag( start );
01346 for ( ; start && start != end->next() ; start = start->next() )
01347 {
01348 start->setLeftBorder(leftBorder);
01349 start->setRightBorder(rightBorder);
01350 start->setTopBorder(topBorder);
01351 start->setBottomBorder(bottomBorder);
01352 }
01353 textdoc->selectionStart( selectionId )->setTopBorder(topBorder);
01354
01355 if ( start && start->prev() )
01356 start->prev()->setChanged( true );
01357 if ( end && end->next() )
01358 end->next()->setChanged( true );
01359 }
01360 formatMore( 2 );
01361 emit repaintChanged( this );
01362 undoRedoInfo.newParagLayout.leftBorder=leftBorder;
01363 undoRedoInfo.newParagLayout.rightBorder=rightBorder;
01364 undoRedoInfo.newParagLayout.topBorder=topBorder;
01365 undoRedoInfo.newParagLayout.bottomBorder=bottomBorder;
01366
01367 KoTextParagCommand *cmd = new KoTextParagCommand(
01368 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01369 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01370 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1 );
01371 textdoc->addCommand( cmd );
01372
01373 undoRedoInfo.clear();
01374 emit showCursor();
01375 emit updateUI( true );
01376 return new KoTextCommand( this, i18n("Change Borders") );
01377 }
01378
01379 KCommand * KoTextObject::setJoinBordersCommand( KoTextCursor * cursor, bool join, KoTextDocument::SelectionId selectionId )
01380 {
01381 if ( protectContent() )
01382 return 0L;
01383 if ( !textdoc->hasSelection( selectionId, true ) &&
01384 cursor && cursor->parag()->joinBorder() == join )
01385 return 0L;
01386
01387 emit hideCursor();
01388 storeParagUndoRedoInfo( cursor, KoTextDocument::Standard );
01389 if ( !textdoc->hasSelection( selectionId, true ) )
01390 {
01391 cursor->parag()->setJoinBorder( join );
01392 setLastFormattedParag( cursor->parag() );
01393
01394 if ( cursor->parag()->next() )
01395 cursor->parag()->next()->setChanged( true );
01396 if ( cursor->parag()->prev() )
01397 cursor->parag()->prev()->setChanged( true );
01398 }
01399 else
01400 {
01401 KoTextParag *start = textdoc->selectionStart( selectionId );
01402 KoTextParag *end = textdoc->selectionEnd( selectionId );
01403 setLastFormattedParag( start );
01404 for ( ; start && start != end->next() ; start = start->next() )
01405 {
01406 start->setJoinBorder( true );
01407 }
01408 end->setJoinBorder ( true );
01409
01410 if ( start && start->prev() )
01411 start->prev()->setChanged( true );
01412 if ( end && end->next() )
01413 end->next()->setChanged( true );
01414 }
01415 formatMore( 2 );
01416
01417 emit repaintChanged( this );
01418 undoRedoInfo.newParagLayout.joinBorder=join;
01419
01420 KoTextParagCommand *cmd = new KoTextParagCommand(
01421 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01422 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01423 KoParagLayout::Borders, (QStyleSheetItem::Margin)-1 );
01424 textdoc->addCommand( cmd );
01425
01426 undoRedoInfo.clear();
01427 emit ensureCursorVisible();
01428 emit showCursor();
01429 emit updateUI( true );
01430 return new KoTextCommand( this, i18n("Change Join Borders") );
01431 }
01432
01433
01434 KCommand * KoTextObject::setTabListCommand( KoTextCursor * cursor, const KoTabulatorList &tabList, KoTextDocument::SelectionId selectionId )
01435 {
01436 if ( protectContent() )
01437 return 0L;
01438 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01439 cursor->parag()->tabList() == tabList )
01440 return 0L;
01441
01442 emit hideCursor();
01443 storeParagUndoRedoInfo( cursor, selectionId );
01444
01445 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01446 cursor->parag()->setTabList( tabList );
01447 setLastFormattedParag( cursor->parag() );
01448 }
01449 else
01450 {
01451 KoTextParag *start = textdoc->selectionStart( selectionId );
01452 KoTextParag *end = textdoc->selectionEnd( selectionId );
01453 setLastFormattedParag( start );
01454 for ( ; start && start != end->next() ; start = start->next() )
01455 start->setTabList( tabList );
01456 }
01457
01458 formatMore( 2 );
01459 emit repaintChanged( this );
01460 undoRedoInfo.newParagLayout.setTabList( tabList );
01461 KoTextParagCommand *cmd = new KoTextParagCommand(
01462 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01463 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01464 KoParagLayout::Tabulator);
01465 textdoc->addCommand( cmd );
01466 undoRedoInfo.clear();
01467 emit showCursor();
01468 emit updateUI( true );
01469 return new KoTextCommand( this, i18n("Change Tabulator") );
01470 }
01471
01472 KCommand * KoTextObject::setParagDirectionCommand( KoTextCursor * cursor, QChar::Direction d, KoTextDocument::SelectionId selectionId )
01473 {
01474 if ( protectContent() )
01475 return 0L;
01476 if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01477 cursor->parag()->direction() == d )
01478 return 0L;
01479
01480 emit hideCursor();
01481 storeParagUndoRedoInfo( cursor, selectionId );
01482
01483 if ( !textdoc->hasSelection( selectionId, true ) && cursor ) {
01484 cursor->parag()->setDirection( d );
01485 setLastFormattedParag( cursor->parag() );
01486 }
01487 else
01488 {
01489 KoTextParag *start = textdoc->selectionStart( selectionId );
01490 KoTextParag *end = textdoc->selectionEnd( selectionId );
01491 setLastFormattedParag( start );
01492 for ( ; start && start != end->next() ; start = start->next() )
01493 start->setDirection( d );
01494 }
01495
01496 formatMore( 2 );
01497 emit repaintChanged( this );
01499 #if 0
01500 undoRedoInfo.newParagLayout.direction = d;
01501 KoTextParagCommand *cmd = new KoTextParagCommand(
01502 textdoc, undoRedoInfo.id, undoRedoInfo.eid,
01503 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
01504 KoParagLayout::Shadow);
01505 textdoc->addCommand( cmd );
01506 #endif
01507 undoRedoInfo.clear();
01508 emit showCursor();
01509 emit updateUI( true );
01510 #if 0
01511 return new KoTextCommand( this, i18n("Change Shadow") );
01512 #else
01513 return 0L;
01514 #endif
01515 }
01516
01517 void KoTextObject::removeSelectedText( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId, const QString & cmdName, bool createUndoRedo )
01518 {
01519 if ( protectContent() )
01520 return ;
01521 emit hideCursor();
01522 if( createUndoRedo)
01523 {
01524 checkUndoRedoInfo( cursor, UndoRedoInfo::RemoveSelected );
01525 if ( !undoRedoInfo.valid() ) {
01526 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index );
01527 undoRedoInfo.text = QString::null;
01528 newPlaceHolderCommand( cmdName.isNull() ? i18n("Remove Selected Text") : cmdName );
01529 }
01530 }
01531 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01532 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01533 readFormats( c1, c2, true, true );
01534
01535
01536 textdoc->removeSelectedText( selectionId, cursor );
01537
01538 setLastFormattedParag( cursor->parag() );
01539 formatMore( 2 );
01540 emit repaintChanged( this );
01541 emit ensureCursorVisible();
01542 emit updateUI( true );
01543 emit showCursor();
01544 if(selectionId==KoTextDocument::Standard || selectionId==KoTextDocument::InputMethodPreedit)
01545 selectionChangedNotify();
01546 if ( createUndoRedo)
01547 undoRedoInfo.clear();
01548 }
01549
01550 KCommand * KoTextObject::removeSelectedTextCommand( KoTextCursor * cursor, KoTextDocument::SelectionId selectionId, bool repaint )
01551 {
01552 if ( protectContent() )
01553 return 0L;
01554 if ( !textdoc->hasSelection( selectionId, true ) )
01555 return 0L;
01556
01557 undoRedoInfo.clear();
01558 textdoc->selectionStart( selectionId, undoRedoInfo.id, undoRedoInfo.index );
01559 Q_ASSERT( undoRedoInfo.id >= 0 );
01560
01561 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01562 KoTextCursor c2 = textdoc->selectionEndCursor( selectionId );
01563 readFormats( c1, c2, true, true );
01564
01565 textdoc->removeSelectedText( selectionId, cursor );
01566
01567 KMacroCommand *macroCmd = new KMacroCommand( i18n("Remove Selected Text") );
01568
01569 KoTextDocCommand *cmd = deleteTextCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index,
01570 undoRedoInfo.text.rawData(),
01571 undoRedoInfo.customItemsMap,
01572 undoRedoInfo.oldParagLayouts );
01573 textdoc->addCommand(cmd);
01574 macroCmd->addCommand(new KoTextCommand( this, QString::null ));
01575
01576 if(!undoRedoInfo.customItemsMap.isEmpty())
01577 undoRedoInfo.customItemsMap.deleteAll( macroCmd );
01578
01579 undoRedoInfo.type = UndoRedoInfo::Invalid;
01580 undoRedoInfo.clear();
01581 if ( repaint )
01582 selectionChangedNotify();
01583 return macroCmd;
01584 }
01585
01586 KCommand* KoTextObject::replaceSelectionCommand( KoTextCursor * cursor, const QString & replacement,
01587 const QString & cmdName,
01588 KoTextDocument::SelectionId selectionId,
01589 int insertFlags,
01590 CustomItemsMap customItemsMap )
01591 {
01592 if ( protectContent() )
01593 return 0L;
01594 Q_ASSERT( ( insertFlags & DoNotRemoveSelected ) == 0 );
01595 const bool repaint = ( insertFlags & DoNotRepaint ) == 0;
01596 if ( repaint )
01597 emit hideCursor();
01598
01599 KMacroCommand * macroCmd = new KMacroCommand( cmdName );
01600
01601
01602 KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01603 KoTextFormat * format = c1.parag()->at( c1.index() )->format();
01604 format->addRef();
01605
01606
01607 KCommand* removeSelCmd = removeSelectedTextCommand( cursor, selectionId, repaint );
01608 if ( removeSelCmd )
01609 macroCmd->addCommand( removeSelCmd );
01610
01611
01612 insert( cursor, format,
01613 replacement, QString::null ,
01614 selectionId, insertFlags | DoNotRemoveSelected, customItemsMap );
01615
01616 KoTextDocCommand * cmd = new KoTextInsertCommand( textdoc, undoRedoInfo.id, undoRedoInfo.index,
01617 undoRedoInfo.text.rawData(),
01618 CustomItemsMap(), undoRedoInfo.oldParagLayouts );
01619 textdoc->addCommand( cmd );
01620 macroCmd->addCommand( new KoTextCommand( this, QString::null ) );
01621
01622 undoRedoInfo.type = UndoRedoInfo::Invalid;
01623 undoRedoInfo.clear();
01624
01625 format->removeRef();
01626
01627 setLastFormattedParag( c1.parag() );
01628 if ( repaint )
01629 {
01630 formatMore( 2 );
01631 emit repaintChanged( this );
01632 emit ensureCursorVisible();
01633 emit updateUI( true );
01634 emit showCursor();
01635 if(selectionId==KoTextDocument::Standard)
01636 selectionChangedNotify();
01637 }
01638 return macroCmd;
01639 }
01640
01641 KCommand * KoTextObject::insertParagraphCommand( KoTextCursor *cursor )
01642 {
01643 if ( protectContent() )
01644 return 0L;
01645 return replaceSelectionCommand( cursor, "\n", QString::null, KoTextDocument::Standard, CheckNewLine );
01646 }
01647
01648 void KoTextObject::highlightPortion( KoTextParag * parag, int index, int length, bool repaint )
01649 {
01650 if ( !m_highlightSelectionAdded )
01651 {
01652 textdoc->addSelection( KoTextDocument::HighlightSelection );
01653 textdoc->setSelectionColor( KoTextDocument::HighlightSelection,
01654 QApplication::palette().color( QPalette::Active, QColorGroup::Dark ) );
01655 textdoc->setInvertSelectionText( KoTextDocument::HighlightSelection, true );
01656 m_highlightSelectionAdded = true;
01657 }
01658
01659 removeHighlight(repaint);
01660 KoTextCursor cursor( textdoc );
01661 cursor.setParag( parag );
01662 cursor.setIndex( index );
01663 textdoc->setSelectionStart( KoTextDocument::HighlightSelection, &cursor );
01664 cursor.setIndex( index + length );
01665 textdoc->setSelectionEnd( KoTextDocument::HighlightSelection, &cursor );
01666 if ( repaint ) {
01667 parag->setChanged( true );
01668 emit repaintChanged( this );
01669 }
01670 }
01671
01672 void KoTextObject::removeHighlight(bool repaint)
01673 {
01674 if ( textdoc->hasSelection( KoTextDocument::HighlightSelection, true ) )
01675 {
01676 KoTextParag * oldParag = textdoc->selectionStart( KoTextDocument::HighlightSelection );
01677 oldParag->setChanged( true );
01678 textdoc->removeSelection( KoTextDocument::HighlightSelection );
01679 }
01680 if ( repaint )
01681 emit repaintChanged( this );
01682 }
01683
01684 void KoTextObject::selectAll( bool select )
01685 {
01686 if ( !select )
01687 textdoc->removeSelection( KoTextDocument::Standard );
01688 else
01689 textdoc->selectAll( KoTextDocument::Standard );
01690 selectionChangedNotify();
01691 }
01692
01693 void KoTextObject::selectionChangedNotify( bool enableActions )
01694 {
01695 emit repaintChanged( this );
01696 if ( enableActions )
01697 emit selectionChanged( hasSelection() );
01698 }
01699
01700 void KoTextObject::setViewArea( QWidget* w, int maxY )
01701 {
01702 m_mapViewAreas.replace( w, maxY );
01703 }
01704
01705 void KoTextObject::setLastFormattedParag( KoTextParag *parag )
01706 {
01707
01708 if ( !m_lastFormatted || !parag || m_lastFormatted->paragId() >= parag->paragId() ) {
01709 m_lastFormatted = parag;
01710 }
01711 }
01712
01713 void KoTextObject::ensureFormatted( KoTextParag * parag, bool emitAfterFormatting )
01714 {
01715 if ( !textdoc->lastParag() )
01716 return;
01717
01718 if ( !parag->isValid() && m_lastFormatted == 0 )
01719 m_lastFormatted = parag;
01720
01721 while ( !parag->isValid() )
01722 {
01723 if ( !m_lastFormatted ) {
01724 kdWarning() << "ensureFormatted for parag " << parag << " " << parag->paragId() << " still not formatted, but m_lastFormatted==0" << endl;
01725 return;
01726 }
01727
01728 bool ret = formatMore( QMAX( 1, parag->paragId() - m_lastFormatted->paragId() ), emitAfterFormatting );
01729 if ( !ret ) {
01730
01731 break;
01732 }
01733 }
01734
01735 }
01736
01737 bool KoTextObject::formatMore( int count , bool emitAfterFormatting )
01738 {
01739 if ( ( !m_lastFormatted && d->afterFormattingEmitted )
01740 || !m_visible || m_availableHeight == -1 )
01741 return false;
01742
01743 if ( !textdoc->lastParag() )
01744 return false;
01745
01746 if ( d->abortFormatting ) {
01747 d->abortFormatting = false;
01748 return false;
01749 }
01750
01751 if ( count == 0 )
01752 {
01753 formatTimer->start( interval, TRUE );
01754 return true;
01755 }
01756
01757 int bottom = 0;
01758 if ( m_lastFormatted )
01759 {
01760 d->afterFormattingEmitted = false;
01761
01762 int viewsBottom = 0;
01763 QMapIterator<QWidget *, int> mapIt = m_mapViewAreas.begin();
01764 for ( ; mapIt != m_mapViewAreas.end() ; ++mapIt )
01765 viewsBottom = QMAX( viewsBottom, mapIt.data() );
01766
01767 #ifdef DEBUG_FORMAT_MORE
01768 kdDebug(32500) << "formatMore " << name()
01769 << " lastFormatted id=" << m_lastFormatted->paragId()
01770 << " lastFormatted's top=" << m_lastFormatted->rect().top()
01771 << " lastFormatted's height=" << m_lastFormatted->rect().height()
01772 << " count=" << count << " viewsBottom=" << viewsBottom
01773 << " availableHeight=" << m_availableHeight << endl;
01774 #endif
01775 if ( m_lastFormatted->prev() == 0 )
01776 {
01777 emit formattingFirstParag();
01778 #ifdef TIMING_FORMAT
01779 kdDebug(32500) << "formatMore " << name() << ". First parag -> starting timer" << endl;
01780 m_time.start();
01781 #endif
01782 }
01783
01784
01785
01786
01787 int i;
01788 for ( i = 0;
01789 m_lastFormatted && bottom + m_lastFormatted->rect().height() <= m_availableHeight &&
01790 ( i < count || bottom <= viewsBottom ) ; ++i )
01791 {
01792 KoTextParag* parag = m_lastFormatted;
01793 #ifdef DEBUG_FORMAT_MORE
01794 kdDebug(32500) << "formatMore formatting " << parag << " id=" << parag->paragId() << endl;
01795 #endif
01796 assert( parag->string() );
01797 parag->format();
01798 bottom = parag->rect().top() + parag->rect().height();
01799 #if 0 //def DEBUG_FORMAT_MORE
01800 kdDebug(32500) << "formatMore(inside) top=" << parag->rect().top()
01801 << " height=" << parag->rect().height()
01802 << " bottom=" << bottom << " m_lastFormatted(next parag) = " << m_lastFormatted->next() << endl;
01803 #endif
01804
01805
01806 if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_CHAPTER
01807 && parag->counter()->depth() == 0 )
01808 emit chapterParagraphFormatted( parag );
01809
01810 if ( d->abortFormatting ) {
01811 #ifdef DEBUG_FORMAT_MORE
01812 kdDebug(32500) << "formatMore formatting aborted. " << endl;
01813 #endif
01814 d->abortFormatting = false;
01815 return false;
01816 }
01817
01818 if ( parag != m_lastFormatted )
01819 kdWarning() << "Some code changed m_lastFormatted during formatting! Was " << parag->paragId() << ", is now " << m_lastFormatted->paragId() << endl;
01820 #if 0 // This happens now that formatting can 'abort' (e.g. due to page not yet created)
01821 else if (!parag->isValid())
01822 kdWarning() << "PARAGRAPH " << parag->paragId() << " STILL INVALID AFTER FORMATTING" << endl;
01823 #endif
01824 m_lastFormatted = parag->next();
01825 }
01826 }
01827 else
01828 {
01829 QRect rect = textdoc->lastParag()->rect();
01830 bottom = rect.top() + rect.height();
01831 }
01832 #ifdef DEBUG_FORMAT_MORE
01833 QString id;
01834 if ( m_lastFormatted ) id = QString(" (%1)").arg(m_lastFormatted->paragId());
01835 kdDebug(32500) << "formatMore finished formatting. "
01836 << " bottom=" << bottom
01837 << " m_lastFormatted=" << m_lastFormatted << id
01838 << endl;
01839 #endif
01840
01841 if ( emitAfterFormatting )
01842 {
01843 d->afterFormattingEmitted = true;
01844 bool needMoreSpace = false;
01845
01846 if ( ( bottom > m_availableHeight ) ||
01847 ( m_lastFormatted && bottom + m_lastFormatted->rect().height() > m_availableHeight ) )
01848 needMoreSpace = true;
01849
01850 bool abort = needMoreSpace;
01851 emit afterFormatting( bottom, m_lastFormatted, &abort );
01852 if ( abort )
01853 return false;
01854 else if ( needMoreSpace && m_lastFormatted )
01855 return formatMore( 2 );
01856 }
01857
01858
01859 if ( m_lastFormatted )
01860 {
01861 formatTimer->start( interval, TRUE );
01862 #ifdef DEBUG_FORMAT_MORE
01863 kdDebug(32500) << name() << " formatMore: will have to format more. formatTimer->start with interval=" << interval << endl;
01864 #endif
01865 }
01866 else
01867 {
01868 interval = QMAX( 0, interval );
01869 #ifdef DEBUG_FORMAT_MORE
01870 kdDebug(32500) << name() << " formatMore: all formatted interval=" << interval << endl;
01871 #endif
01872 #ifdef TIMING_FORMAT
01873
01874 kdDebug(32500) << "formatMore: " << name() << " all formatted. Took "
01875 << (double)(m_time.elapsed()) / 1000 << " seconds." << endl;
01876 #endif
01877 }
01878 return true;
01879 }
01880
01881 void KoTextObject::abortFormatting()
01882 {
01883 d->abortFormatting = true;
01884 }
01885
01886 void KoTextObject::doChangeInterval()
01887 {
01888
01889 interval = 0;
01890 }
01891
01892 void KoTextObject::typingStarted()
01893 {
01894
01895 changeIntervalTimer->stop();
01896 interval = 10;
01897 }
01898
01899 void KoTextObject::typingDone()
01900 {
01901 changeIntervalTimer->start( 100, TRUE );
01902 }
01903
01904
01905
01906 KCommand *KoTextObject::changeCaseOfTextParag( int cursorPosStart, int cursorPosEnd,
01907 KoChangeCaseDia::TypeOfCase _type,
01908 KoTextCursor *cursor, KoTextParag *parag )
01909 {
01910 if ( protectContent() )
01911 return 0L;
01912
01913 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") );
01914 KoTextFormat *curFormat = parag->paragraphFormat();
01915 const QString text = parag->string()->toString().mid( cursorPosStart, cursorPosEnd - cursorPosStart );
01916 int posStart = cursorPosStart;
01917 int posEnd = cursorPosStart;
01918 KoTextCursor c1( textdoc );
01919 KoTextCursor c2( textdoc );
01920
01921 for ( int i = cursorPosStart; i < cursorPosEnd; ++i )
01922 {
01923 KoTextStringChar & ch = *(parag->at(i));
01924 KoTextFormat * newFormat = ch.format();
01925 if( ch.isCustom() )
01926 {
01927 posEnd = i;
01928 c1.setParag( parag );
01929 c1.setIndex( posStart );
01930 c2.setParag( parag );
01931 c2.setIndex( posEnd );
01932
01933
01934 const QString repl = text.mid( posStart, posEnd - posStart );
01935 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01936 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01937 macroCmd->addCommand(replaceSelectionCommand(
01938 cursor, textChangedCase(repl,_type),
01939 QString::null, KoTextDocument::Temp));
01940 do
01941 {
01942 ++i;
01943 }
01944 while( parag->at(i)->isCustom() && i != cursorPosEnd);
01945 posStart=i;
01946 posEnd=i;
01947 }
01948 else
01949 {
01950 if ( newFormat != curFormat )
01951 {
01952 posEnd=i;
01953 c1.setParag( parag );
01954 c1.setIndex( posStart );
01955 c2.setParag( parag );
01956 c2.setIndex( posEnd );
01957
01958
01959 const QString repl = text.mid( posStart, posEnd - posStart );
01960 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01961 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01962 macroCmd->addCommand(replaceSelectionCommand(
01963 cursor, textChangedCase(repl,_type),
01964 QString::null, KoTextDocument::Temp));
01965 posStart=i;
01966 posEnd=i;
01967 curFormat = newFormat;
01968 }
01969 }
01970 }
01971 if ( posStart != cursorPosEnd )
01972 {
01973
01974 c1.setParag( parag );
01975 c1.setIndex( posStart );
01976 c2.setParag( parag );
01977 c2.setIndex( cursorPosEnd );
01978
01979 textdoc->setSelectionStart( KoTextDocument::Temp, &c1 );
01980 textdoc->setSelectionEnd( KoTextDocument::Temp, &c2 );
01981 const QString repl = text.mid( posStart, cursorPosEnd - posStart );
01982 macroCmd->addCommand(replaceSelectionCommand(
01983 cursor, textChangedCase(repl,_type),
01984 QString::null, KoTextDocument::Temp));
01985 }
01986 return macroCmd;
01987
01988 }
01989
01990 KCommand *KoTextObject::changeCaseOfText(KoTextCursor *cursor,KoChangeCaseDia::TypeOfCase _type)
01991 {
01992 if ( protectContent() )
01993 return 0L;
01994 KMacroCommand * macroCmd = new KMacroCommand( i18n("Change Case") );
01995
01996 KoTextCursor start = textdoc->selectionStartCursor( KoTextDocument::Standard );
01997 KoTextCursor end = textdoc->selectionEndCursor( KoTextDocument::Standard );
01998 emit hideCursor();
01999
02000 if ( start.parag() == end.parag() )
02001 {
02002 int endIndex = QMIN( start.parag()->length() - 1, end.index() );
02003 macroCmd->addCommand( changeCaseOfTextParag( start.index(), endIndex, _type,
02004 cursor, start.parag() ) );
02005 }
02006 else
02007 {
02008 macroCmd->addCommand( changeCaseOfTextParag( start.index(), start.parag()->length() - 1, _type,
02009 cursor, start.parag() ) );
02010 KoTextParag *p = start.parag()->next();
02011 while ( p && p != end.parag() )
02012 {
02013 macroCmd->addCommand( changeCaseOfTextParag(0, p->length() - 1, _type, cursor, p ) );
02014 p = p->next();
02015 }
02016 if ( p )
02017 {
02018 int endIndex = QMIN( p->length() - 1, end.index() );
02019 macroCmd->addCommand( changeCaseOfTextParag(0, endIndex, _type, cursor, end.parag() ));
02020 }
02021 }
02022 formatMore( 2 );
02023 emit repaintChanged( this );
02024 emit ensureCursorVisible();
02025 emit updateUI( true );
02026 emit showCursor();
02027 return macroCmd;
02028 }
02029
02030 QString KoTextObject::textChangedCase(const QString& _text,KoChangeCaseDia::TypeOfCase _type)
02031 {
02032 QString text(_text);
02033 switch(_type)
02034 {
02035 case KoChangeCaseDia::UpperCase:
02036 text=text.upper();
02037 break;
02038 case KoChangeCaseDia::LowerCase:
02039 text=text.lower();
02040 break;
02041 case KoChangeCaseDia::TitleCase:
02042 for(uint i=0;i<text.length();i++)
02043 {
02044 if(text.at(i)!=' ')
02045 {
02046 QChar prev = text.at(QMAX(i-1,0));
02047 if(i==0 || prev == ' ' || prev == '\n' || prev == '\t')
02048 text=text.replace(i, 1, text.at(i).upper() );
02049 else
02050 text=text.replace(i, 1, text.at(i).lower() );
02051 }
02052 }
02053 break;
02054 case KoChangeCaseDia::ToggleCase:
02055 for(uint i=0;i<text.length();i++)
02056 {
02057 QString repl=QString(text.at(i));
02058 if(text.at(i)!=text.at(i).upper())
02059 repl=repl.upper();
02060 else if(text.at(i).lower()!=text.at(i))
02061 repl=repl.lower();
02062 text=text.replace(i, 1, repl );
02063 }
02064 break;
02065 case KoChangeCaseDia::SentenceCase:
02066 for(uint i=0;i<text.length();i++)
02067 {
02068 if(text.at(i)!=' ')
02069 {
02070 QChar prev = text.at(QMAX(i-1,0));
02071 if(i==0 || prev == '\n' ||prev.isPunct())
02072 text=text.replace(i, 1, text.at(i).upper() );
02073 }
02074 }
02075 break;
02076 default:
02077 kdDebug(32500)<<"Error in changeCaseOfText !\n";
02078 break;
02079
02080 }
02081 return text;
02082 }
02083
02084
02085 KoTextFormat * KoTextObject::currentFormat() const
02086 {
02087
02088
02089 KoTextStringChar *ch = textdoc->firstParag()->at( 0 );
02090 return ch->format();
02091 }
02092
02093 const KoParagLayout * KoTextObject::currentParagLayoutFormat() const
02094 {
02095 KoTextParag * parag = textdoc->firstParag();
02096 return &(parag->paragLayout());
02097 }
02098
02099 bool KoTextObject::rtl() const
02100 {
02101 return textdoc->firstParag()->string()->isRightToLeft();
02102 }
02103
02104 void KoTextObject::loadOasisContent( const QDomElement &bodyElem, KoOasisContext& context, KoStyleCollection * styleColl )
02105 {
02106 textDocument()->clear(false);
02107 setLastFormattedParag( 0L );
02108
02109 KoTextParag *lastParagraph = textDocument()->loadOasisText( bodyElem, context, 0, styleColl, 0 );
02110
02111 if ( !lastParagraph )
02112 {
02113
02114 textDocument()->clear( true );
02115 textDocument()->firstParag()->setStyle( styleColl->findStyle( "Standard" ) );
02116 }
02117 else
02118 textDocument()->setLastParag( lastParagraph );
02119
02120 setLastFormattedParag( textDocument()->firstParag() );
02121 }
02122
02123 KoTextCursor KoTextObject::pasteOasisText( const QDomElement &bodyElem, KoOasisContext& context,
02124 KoTextCursor& cursor, KoStyleCollection * styleColl )
02125 {
02126 KoTextCursor resultCursor( cursor );
02127 KoTextParag* lastParagraph = cursor.parag();
02128 bool removeNewline = false;
02129 uint pos = cursor.index();
02130 if ( pos == 0 && lastParagraph->length() <= 1 ) {
02131
02132 lastParagraph = lastParagraph->prev();
02133 lastParagraph = textDocument()->loadOasisText( bodyElem, context, lastParagraph, styleColl, cursor.parag() );
02134 if ( lastParagraph ) {
02135 resultCursor.setParag( lastParagraph );
02136 resultCursor.setIndex( lastParagraph->length() - 1 );
02137 }
02138 removeNewline = true;
02139 } else {
02140
02141
02142 for ( QDomNode text (bodyElem.firstChild()); !text.isNull(); text = text.nextSibling() )
02143 {
02144 QDomElement tag = text.toElement();
02145 if ( tag.isNull() ) continue;
02146
02147
02148
02149 QDomElement tagToLoad = tag;
02150 if ( tag.localName() == "numbered-paragraph" ) {
02151 QDomElement npchild;
02152 forEachElement( npchild, tag )
02153 {
02154 if ( npchild.localName() == "p" || npchild.localName() == "h" ) {
02155 tagToLoad = npchild;
02156 break;
02157 }
02158 }
02159 }
02160
02161 if ( tagToLoad.localName() == "p" || tagToLoad.localName() == "h" ) {
02162 context.styleStack().save();
02163 context.fillStyleStack( tagToLoad, KoXmlNS::text, "style-name", "paragraph" );
02164
02165
02166 lastParagraph->loadOasisSpan( tagToLoad, context, pos, true );
02167 context.styleStack().restore();
02168
02169 lastParagraph->setChanged( true );
02170 lastParagraph->invalidate( 0 );
02171
02172
02173 resultCursor.setParag( lastParagraph );
02174 resultCursor.setIndex( pos );
02175 resultCursor.splitAndInsertEmptyParag( FALSE, TRUE );
02176 removeNewline = true;
02177
02178
02179 const_cast<QDomElement &>( bodyElem ).removeChild( tag );
02180 }
02181 break;
02182 }
02183 resultCursor.setParag( lastParagraph );
02184 resultCursor.setIndex( pos );
02185
02186 lastParagraph = textDocument()->loadOasisText( bodyElem, context, lastParagraph, styleColl, lastParagraph->next() );
02187 if ( lastParagraph != resultCursor.parag() )
02188 {
02189 removeNewline = true;
02190 resultCursor.setParag( lastParagraph );
02191 resultCursor.setIndex( lastParagraph->length() - 1 );
02192 }
02193 }
02194 KoTextParag* p = resultCursor.parag();
02195 if ( p ) p = p->next();
02196
02197 if ( removeNewline && resultCursor.remove() ) {
02198 if ( m_lastFormatted == p ) {
02199 m_lastFormatted = resultCursor.parag();
02200 }
02201 }
02202 return resultCursor;
02203 }
02204
02205 void KoTextObject::saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const
02206 {
02207 textDocument()->saveOasisContent( writer, context );
02208 }
02209
02210 KCommand *KoTextObject::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags,int marginIndex)
02211 {
02212 if ( protectContent() )
02213 return 0L;
02214 textdoc->selectAll( KoTextDocument::Temp );
02215 KoTextCursor *cursor = new KoTextCursor( textdoc );
02216 KCommand* cmd = setParagLayoutCommand( cursor, *newLayout, KoTextDocument::Temp,
02217 flags, marginIndex, true );
02218 textdoc->removeSelection( KoTextDocument::Temp );
02219 delete cursor;
02220 return cmd;
02221 }
02222
02223 void KoTextObject::setFormat( KoTextFormat * newFormat, int flags, bool zoomFont )
02224 {
02225 if ( protectContent() )
02226 return ;
02227
02228 textdoc->selectAll( KoTextDocument::Temp );
02229 KCommand *cmd = setFormatCommand( 0L, 0L, newFormat,
02230 flags, zoomFont, KoTextDocument::Temp );
02231 textdoc->removeSelection( KoTextDocument::Temp );
02232 if (cmd)
02233 emit newCommand( cmd );
02234
02235 KoTextFormat format = *currentFormat();
02236
02237 emit showFormatObject(format);
02238 }
02239
02240 KCommand *KoTextObject::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type)
02241 {
02242 if ( protectContent() )
02243 return 0L;
02244 textdoc->selectAll( KoTextDocument::Standard );
02245 KoTextCursor *cursor = new KoTextCursor( textdoc );
02246 KCommand* cmd = changeCaseOfText(cursor, _type);
02247 textdoc->removeSelection( KoTextDocument::Standard );
02248 delete cursor;
02249 return cmd;
02250 }
02251
02252 void KoTextObject::setNeedSpellCheck(bool b)
02253 {
02254 m_needsSpellCheck = b;
02255 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next())
02256 parag->string()->setNeedsSpellCheck( b );
02257 }
02258
02259 bool KoTextObject::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words, ulong & sentences, ulong & syllables, ulong & lines, bool selected )
02260 {
02261
02262
02263
02264 QStringList subs_syl;
02265 subs_syl << "cial" << "tia" << "cius" << "cious" << "giu" << "ion" << "iou";
02266 QStringList subs_syl_regexp;
02267 subs_syl_regexp << "sia$" << "ely$";
02268
02269 QStringList add_syl;
02270 add_syl << "ia" << "riet" << "dien" << "iu" << "io" << "ii";
02271 QStringList add_syl_regexp;
02272 add_syl_regexp << "[aeiouym]bl$" << "[aeiou]{3}" << "^mc" << "ism$"
02273 << "[^l]lien" << "^coa[dglx]." << "[^gq]ua[^auieo]" << "dnt$";
02274
02275 QString s;
02276 KoTextParag * parag = textdoc->firstParag();
02277 for ( ; parag ; parag = parag->next() )
02278 {
02279 if ( progress )
02280 {
02281 progress->setProgress(progress->progress()+1);
02282
02283 kapp->processEvents();
02284 if ( progress->wasCancelled() )
02285 return false;
02286 }
02287
02288
02289
02290
02291
02292
02293
02294 bool hasTrailingSpace = true;
02295 if ( !selected ) {
02296 s = parag->string()->toString();
02297 lines += parag->lines();
02298 } else {
02299 if ( parag->hasSelection( KoTextDocument::Standard ) ) {
02300 hasTrailingSpace = false;
02301 s = parag->string()->toString();
02302 if ( !( parag->fullSelected( KoTextDocument::Standard ) ) ) {
02303 s = s.mid( parag->selectionStart( KoTextDocument::Standard ), parag->selectionEnd( KoTextDocument::Standard ) - parag->selectionStart( KoTextDocument::Standard ) );
02304 lines+=numberOfparagraphLineSelected(parag);
02305 }
02306 else
02307 lines += parag->lines();
02308 } else {
02309 continue;
02310 }
02311 }
02312
02313
02314 for ( uint i = 0 ; i < s.length() - ( hasTrailingSpace ? 1 : 0 ) ; ++i )
02315 {
02316 QChar ch = s[i];
02317 ++charsWithSpace;
02318 if ( !ch.isSpace() )
02319 ++charsWithoutSpace;
02320 }
02321
02322
02323
02324
02325
02326
02327
02328 QRegExp re("\\s+");
02329 QStringList wordlist = QStringList::split(re, s);
02330 words += wordlist.count();
02331 re.setCaseSensitive(false);
02332 for ( QStringList::Iterator it = wordlist.begin(); it != wordlist.end(); ++it ) {
02333 QString word = *it;
02334 re.setPattern("[!?.,:_\"-]");
02335 word.remove(re);
02336 if ( word.length() <= 3 ) {
02337 syllables++;
02338 continue;
02339 }
02340 re.setPattern("e$");
02341 word.remove(re);
02342 re.setPattern("[^aeiouy]+");
02343 QStringList syls = QStringList::split(re, word);
02344 int word_syllables = 0;
02345 for ( QStringList::Iterator it = subs_syl.begin(); it != subs_syl.end(); ++it ) {
02346 if( word.find(*it, 0, false) != -1 )
02347 word_syllables--;
02348 }
02349 for ( QStringList::Iterator it = subs_syl_regexp.begin(); it != subs_syl_regexp.end(); ++it ) {
02350 re.setPattern(*it);
02351 if( word.find(re) != -1 )
02352 word_syllables--;
02353 }
02354 for ( QStringList::Iterator it = add_syl.begin(); it != add_syl.end(); ++it ) {
02355 if( word.find(*it, 0, false) != -1 )
02356 word_syllables++;
02357 }
02358 for ( QStringList::Iterator it = add_syl_regexp.begin(); it != add_syl_regexp.end(); ++it ) {
02359 re.setPattern(*it);
02360 if( word.find(re) != -1 )
02361 word_syllables++;
02362 }
02363 word_syllables += syls.count();
02364 if ( word_syllables == 0 )
02365 word_syllables = 1;
02366 syllables += word_syllables;
02367 }
02368 re.setCaseSensitive(true);
02369
02370
02371
02372 s = s.stripWhiteSpace();
02373 QChar lastchar = s.at(s.length());
02374 if( ! s.isEmpty() && ! KoAutoFormat::isMark( lastchar ) ) {
02375 s = s + ".";
02376 }
02377 re.setPattern("[.?!]+");
02378 s.replace(re, ".");
02379 re.setPattern("\\d\\.\\d");
02380 s.replace(re, "0,0");
02381 re.setPattern("[A-Z]\\.+");
02382 s.replace(re, "*");
02383 for ( uint i = 0 ; i < s.length() ; ++i )
02384 {
02385 QChar ch = s[i];
02386 if ( KoAutoFormat::isMark( ch ) )
02387 ++sentences;
02388 }
02389 }
02390 return true;
02391 }
02392
02393 int KoTextObject::numberOfparagraphLineSelected( KoTextParag *parag)
02394 {
02395 int indexOfLineStart;
02396 int lineStart;
02397 int lineEnd;
02398 KoTextCursor c1 = textdoc->selectionStartCursor( KoTextDocument::Standard );
02399 KoTextCursor c2 = textdoc->selectionEndCursor( KoTextDocument::Standard );
02400 parag->lineStartOfChar( c1.index(), &indexOfLineStart, &lineStart );
02401
02402 parag->lineStartOfChar( c2.index(), &indexOfLineStart, &lineEnd );
02403 return (lineEnd - lineStart+1);
02404 }
02405
02406 KoVariable* KoTextObject::variableAtPoint( const QPoint& iPoint ) const
02407 {
02408 KoTextCursor cursor( textDocument() );
02409 int variablePosition = -1;
02410 cursor.place( iPoint, textDocument()->firstParag(), false, &variablePosition );
02411 if ( variablePosition == -1 )
02412 return 0;
02413 return variableAtPosition( cursor.parag(), variablePosition );
02414 }
02415
02416 KoVariable* KoTextObject::variableAtPosition( KoTextParag* parag, int index ) const
02417 {
02418 KoTextStringChar * ch = parag->at( index );
02419 if ( ch->isCustom() )
02420 return dynamic_cast<KoVariable *>( ch->customItem() );
02421 return 0;
02422 }
02423
02424 const char * KoTextObject::acceptSelectionMimeType()
02425 {
02426 return "application/vnd.oasis.opendocument.";
02427 }
02428
02429 QCString KoTextObject::providesOasis( QMimeSource* mime )
02430 {
02431 const char* fmt;
02432 const char* acceptMimeType = acceptSelectionMimeType();
02433 for ( int i = 0; (fmt = mime->format(i)); ++i )
02434 {
02435 if ( QString( fmt ).startsWith( acceptMimeType ) )
02436 {
02437 return fmt;
02438 }
02439 }
02440 return "";
02441 }
02442
02443 #ifndef NDEBUG
02444 void KoTextObject::printRTDebug(int info)
02445 {
02446 KoTextParag* lastParag = 0;
02447 for (KoTextParag * parag = textdoc->firstParag(); parag ; parag = parag->next())
02448 {
02449 assert( parag->prev() == lastParag );
02450 parag->printRTDebug( info );
02451 lastParag = parag;
02452 }
02453 if ( info == 1 )
02454 textdoc->formatCollection()->debug();
02455 }
02456 #endif
02457
02459
02460 KCommand *KoTextFormatInterface::setBoldCommand(bool on)
02461 {
02462 KoTextFormat format( *currentFormat() );
02463 format.setBold( on );
02464 return setFormatCommand( &format, KoTextFormat::Bold );
02465 }
02466
02467 KCommand *KoTextFormatInterface::setItalicCommand( bool on)
02468 {
02469 KoTextFormat format( *currentFormat() );
02470 format.setItalic( on );
02471 return setFormatCommand( &format, KoTextFormat::Italic );
02472 }
02473
02474 KCommand *KoTextFormatInterface::setUnderlineCommand( bool on )
02475 {
02476 KoTextFormat format( *currentFormat() );
02477 format.setUnderlineType( on ? KoTextFormat::U_SIMPLE : KoTextFormat::U_NONE);
02478 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02479 }
02480
02481 KCommand *KoTextFormatInterface::setUnderlineColorCommand( const QColor &color )
02482 {
02483 KoTextFormat format( *currentFormat() );
02484 format.setTextUnderlineColor( color);
02485 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02486 }
02487
02488 KCommand *KoTextFormatInterface::setDoubleUnderlineCommand( bool on )
02489 {
02490 KoTextFormat format( *currentFormat() );
02491 format.setUnderlineType( on ? KoTextFormat::U_DOUBLE : KoTextFormat::U_NONE);
02492 return setFormatCommand( &format, KoTextFormat::ExtendUnderLine );
02493 }
02494
02495 KCommand *KoTextFormatInterface::setStrikeOutCommand( bool on )
02496 {
02497 KoTextFormat format( *currentFormat() );
02498 format.setStrikeOutType( on ? KoTextFormat::S_SIMPLE : KoTextFormat::S_NONE);
02499 return setFormatCommand( &format, KoTextFormat::StrikeOut );
02500 }
02501
02502 KCommand *KoTextFormatInterface::setTextBackgroundColorCommand(const QColor & col)
02503 {
02504 KoTextFormat format( *currentFormat() );
02505 format.setTextBackgroundColor( col );
02506 return setFormatCommand( &format, KoTextFormat::TextBackgroundColor );
02507 }
02508
02509 KCommand *KoTextFormatInterface::setPointSizeCommand( int s )
02510 {
02511 KoTextFormat format( *currentFormat() );
02512 format.setPointSize( s );
02513 return setFormatCommand( &format, KoTextFormat::Size, true );
02514 }
02515
02516 KCommand *KoTextFormatInterface::setFamilyCommand(const QString &font)
02517 {
02518 KoTextFormat format( *currentFormat() );
02519 format.setFamily( font );
02520 return setFormatCommand( &format, KoTextFormat::Family );
02521 }
02522
02523 QColor KoTextFormatInterface::textBackgroundColor() const
02524 {
02525 return currentFormat()->textBackgroundColor();
02526 }
02527
02528 QColor KoTextFormatInterface::textUnderlineColor()const
02529 {
02530 return currentFormat()->textUnderlineColor();
02531 }
02532
02533 QColor KoTextFormatInterface::textColor() const
02534 {
02535 return currentFormat()->color();
02536 }
02537
02538 bool KoTextFormatInterface::textUnderline()const
02539 {
02540 return currentFormat()->underline();
02541 }
02542
02543 bool KoTextFormatInterface::textDoubleUnderline()const
02544 {
02545 return currentFormat()->doubleUnderline();
02546 }
02547
02548 bool KoTextFormatInterface::textBold()const
02549 {
02550 return currentFormat()->font().bold();
02551 }
02552
02553 bool KoTextFormatInterface::textStrikeOut()const
02554 {
02555 return currentFormat()->font().strikeOut();
02556 }
02557
02558 bool KoTextFormatInterface::textItalic() const
02559 {
02560 return currentFormat()->font().italic();
02561 }
02562
02563 bool KoTextFormatInterface::textSubScript() const
02564 {
02565 return (currentFormat()->vAlign()==KoTextFormat::AlignSubScript);
02566 }
02567
02568 bool KoTextFormatInterface::textSuperScript() const
02569 {
02570 return (currentFormat()->vAlign()==KoTextFormat::AlignSuperScript);
02571 }
02572
02573 double KoTextFormatInterface::shadowDistanceX() const
02574 {
02575 return currentFormat()->shadowDistanceX();
02576 }
02577
02578 double KoTextFormatInterface::shadowDistanceY() const
02579 {
02580 return currentFormat()->shadowDistanceY();
02581 }
02582
02583 QColor KoTextFormatInterface::shadowColor() const
02584 {
02585 return currentFormat()->shadowColor();
02586 }
02587
02588 KoTextFormat::AttributeStyle KoTextFormatInterface::fontAttribute() const
02589 {
02590 return currentFormat()->attributeFont();
02591 }
02592
02593 double KoTextFormatInterface::relativeTextSize() const
02594 {
02595 return currentFormat()->relativeTextSize();
02596 }
02597
02598 int KoTextFormatInterface::offsetFromBaseLine()const
02599 {
02600 return currentFormat()->offsetFromBaseLine();
02601 }
02602
02603 bool KoTextFormatInterface::wordByWord()const
02604 {
02605 return currentFormat()->wordByWord();
02606 }
02607
02608 bool KoTextFormatInterface::hyphenation()const
02609 {
02610 return currentFormat()->hyphenation();
02611 }
02612
02613 KoTextFormat::UnderlineType KoTextFormatInterface::underlineType()const
02614 {
02615 return currentFormat()->underlineType();
02616 }
02617
02618 KoTextFormat::StrikeOutType KoTextFormatInterface::strikeOutType()const
02619 {
02620 return currentFormat()->strikeOutType();
02621 }
02622
02623 KoTextFormat::UnderlineStyle KoTextFormatInterface::underlineStyle()const
02624 {
02625 return currentFormat()->underlineStyle();
02626 }
02627
02628 KoTextFormat::StrikeOutStyle KoTextFormatInterface::strikeOutStyle()const
02629 {
02630 return currentFormat()->strikeOutStyle();
02631 }
02632
02633 QFont KoTextFormatInterface::textFont() const
02634 {
02635 QFont fn( currentFormat()->font() );
02636
02637
02638 return fn;
02639 }
02640
02641 QString KoTextFormatInterface::textFontFamily()const
02642 {
02643 return currentFormat()->font().family();
02644 }
02645
02646 QString KoTextFormatInterface::language() const
02647 {
02648 return currentFormat()->language();
02649 }
02650
02651 KCommand *KoTextFormatInterface::setTextColorCommand(const QColor &color)
02652 {
02653 KoTextFormat format( *currentFormat() );
02654 format.setColor( color );
02655 return setFormatCommand( &format, KoTextFormat::Color );
02656 }
02657
02658 KCommand *KoTextFormatInterface::setTextSubScriptCommand(bool on)
02659 {
02660 KoTextFormat format( *currentFormat() );
02661 if(!on)
02662 format.setVAlign(KoTextFormat::AlignNormal);
02663 else
02664 format.setVAlign(KoTextFormat::AlignSubScript);
02665 return setFormatCommand( &format, KoTextFormat::VAlign );
02666 }
02667
02668 KCommand *KoTextFormatInterface::setTextSuperScriptCommand(bool on)
02669 {
02670 KoTextFormat format( *currentFormat() );
02671 if(!on)
02672 format.setVAlign(KoTextFormat::AlignNormal);
02673 else
02674 format.setVAlign(KoTextFormat::AlignSuperScript);
02675 return setFormatCommand( &format, KoTextFormat::VAlign );
02676 }
02677
02678 KCommand *KoTextFormatInterface::setDefaultFormatCommand()
02679 {
02680 KoTextFormatCollection * coll = currentFormat()->parent();
02681 Q_ASSERT(coll);
02682 if(coll)
02683 {
02684 KoTextFormat * format = coll->defaultFormat();
02685 return setFormatCommand( format, KoTextFormat::Format );
02686 } else {
02687 kdDebug() << "useless call to setDefaultFormatCommand at: " << kdBacktrace() << endl;
02688 }
02689 return 0;
02690 }
02691
02692 KCommand *KoTextFormatInterface::setAlignCommand(int align)
02693 {
02694 KoParagLayout format( *currentParagLayoutFormat() );
02695 format.alignment=align;
02696 return setParagLayoutFormatCommand(&format,KoParagLayout::Alignment);
02697 }
02698
02699 KCommand *KoTextFormatInterface::setHyphenationCommand( bool _b )
02700 {
02701 KoTextFormat format( *currentFormat() );
02702 format.setHyphenation( _b );
02703 return setFormatCommand( &format, KoTextFormat::Hyphenation);
02704 }
02705
02706
02707 KCommand *KoTextFormatInterface::setShadowTextCommand( double shadowDistanceX, double shadowDistanceY, const QColor& shadowColor )
02708 {
02709 KoTextFormat format( *currentFormat() );
02710 format.setShadow( shadowDistanceX, shadowDistanceY, shadowColor );
02711 return setFormatCommand( &format, KoTextFormat::ShadowText );
02712 }
02713
02714 KCommand *KoTextFormatInterface::setFontAttributeCommand( KoTextFormat::AttributeStyle _att)
02715 {
02716 KoTextFormat format( *currentFormat() );
02717 format.setAttributeFont( _att );
02718 return setFormatCommand( &format, KoTextFormat::Attribute );
02719 }
02720
02721 KCommand *KoTextFormatInterface::setRelativeTextSizeCommand( double _size )
02722 {
02723 KoTextFormat format( *currentFormat() );
02724 format.setRelativeTextSize( _size );
02725 return setFormatCommand( &format, KoTextFormat::VAlign );
02726 }
02727
02728 KCommand *KoTextFormatInterface::setOffsetFromBaseLineCommand( int _offset )
02729 {
02730 KoTextFormat format( *currentFormat() );
02731 format.setOffsetFromBaseLine( _offset );
02732 return setFormatCommand( &format, KoTextFormat::OffsetFromBaseLine );
02733 }
02734
02735 KCommand *KoTextFormatInterface::setWordByWordCommand( bool _b )
02736 {
02737 KoTextFormat format( *currentFormat() );
02738 format.setWordByWord( _b );
02739 return setFormatCommand( &format, KoTextFormat::WordByWord );
02740 }
02741
02742 #if 0
02743 void KoTextFormatInterface::setAlign(int align)
02744 {
02745 KCommand *cmd = setAlignCommand( align );
02746 emitNewCommand( cmd );
02747 }
02748
02749 void KoTextFormatInterface::setMargin(QStyleSheetItem::Margin m, double margin)
02750 {
02751 KCommand *cmd = setMarginCommand( m, margin );
02752 emitNewCommand( cmd );
02753 }
02754
02755 void KoTextFormatInterface::setTabList(const KoTabulatorList & tabList )
02756 {
02757 KCommand *cmd = setTabListCommand( tabList );
02758 emitNewCommand( cmd );
02759 }
02760
02761 void KoTextFormatInterface::setCounter(const KoParagCounter & counter )
02762 {
02763 KCommand *cmd = setCounterCommand( counter );
02764 emitNewCommand( cmd );
02765 }
02766
02767 void KoTextFormatInterface::setParagLayoutFormat( KoParagLayout *newLayout, int flags, int marginIndex)
02768 {
02769 KCommand *cmd = setParagLayoutFormatCommand(newLayout, flags, marginIndex);
02770 emitNewCommand( cmd );
02771 }
02772 #endif
02773
02774 KCommand *KoTextFormatInterface::setMarginCommand(QStyleSheetItem::Margin m, double margin)
02775 {
02776 KoParagLayout format( *currentParagLayoutFormat() );
02777 format.margins[m]=margin;
02778 return setParagLayoutFormatCommand(&format,KoParagLayout::Margins,(int)m);
02779 }
02780
02781 KCommand *KoTextFormatInterface::setTabListCommand(const KoTabulatorList & tabList )
02782 {
02783 KoParagLayout format( *currentParagLayoutFormat() );
02784 format.setTabList(tabList);
02785 return setParagLayoutFormatCommand(&format,KoParagLayout::Tabulator);
02786 }
02787
02788 KCommand *KoTextFormatInterface::setCounterCommand(const KoParagCounter & counter )
02789 {
02790 KoParagLayout format( *currentParagLayoutFormat() );
02791 if(!format.counter)
02792 format.counter = new KoParagCounter;
02793 *format.counter = counter;
02794 return setParagLayoutFormatCommand(&format,KoParagLayout::BulletNumber);
02795 }
02796
02797 KCommand *KoTextFormatInterface::setLanguageCommand(const QString &_lang)
02798 {
02799 KoTextFormat format( *currentFormat() );
02800 format.setLanguage(_lang);
02801 return setFormatCommand( &format, KoTextFormat::Language );
02802 }
02803
02804 KoTextDocCommand *KoTextFormatInterface::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts )
02805 {
02806 return textdoc->deleteTextCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts );
02807 }
02808
02809 #include "KoTextObject.moc"