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