lib Library API Documentation

kotextobject.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
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 //#define DEBUG_FORMATS
00036 //#define DEBUG_FORMAT_MORE
00037 
00038 const char KoTextObject::s_customItemChar = '#'; // Has to be transparent to kspell but still be saved (not space)
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     // Apply default style to initial paragraph
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     // Avoid crash in KoTextString::clear -> accessing deleted format collection,
00111     // if ~UndoRedoInfo still has a string to clear.
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 /*ParagModifyType*/ _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 * /*parag*/)
00142 {
00143     // ### TODO: remove from kwbgspellcheck
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 // A visitor that looks for custom items in e.g. a selection
00160 class KoHasCustomItemVisitor : public KoParagVisitor // see kotextdocument.h
00161 {
00162 public:
00163     KoHasCustomItemVisitor() : KoParagVisitor() { }
00164     // returns false when cancelled, i.e. an item was _found_, and true if it proceeded to the end(!)
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; // found one -> stop here
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 ); // Kindof a dummy cursor
00213     KoTextCursor *c = textdoc->undo( cursor );
00214     if ( !c ) {
00215         delete cursor;
00216         emit showCursor();
00217         return;
00218     }
00219     // We have to set this new cursor position in all views :(
00220     // It sucks a bit for useability, but otherwise one view might still have
00221     // a cursor inside a deleted paragraph -> crash.
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 ); // Kindof a dummy cursor
00233     KoTextCursor *c = textdoc->redo( cursor );
00234     if ( !c ) {
00235         delete cursor;
00236         emit showCursor();
00237         return;
00238     }
00239     emit setCursor( c ); // see undo
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                 // Inserting any custom items -> macro command, to let custom items add their command
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, /*cmd, */QString::null ) );
00282                 }
00283                 else
00284                 {
00285                     placeHolderCmd->addCommand( new KoTextCommand( textobj, /*cmd, */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, /*cmd, */QString::null ) );
00295                 // Deleting any custom items -> let them add their command
00296                 if ( !customItemsMap.isEmpty() )
00297                 {
00298                     customItemsMap.deleteAll( placeHolderCmd );
00299                 }
00300            } break;
00301             case Invalid:
00302                 break;
00303         }
00304     }
00305     type = Invalid;
00306     // Before Qt-3.2.0, this called KoTextString::clear(), which called resize(0) on the array, which _detached_. Tricky.
00307     // Since Qt-3.2.0, resize(0) doesn't detach anymore -> KoTextDocDeleteCommand calls copy() itself.
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 /*in text*/, 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         // We copy the custom item to customItemsMap in all cases (see setFormat)
00328         // We only remove from 'ch' if moveCustomItems was specified
00329         if ( moveCustomItems )
00330             parag->removeCustomItem(position);
00331         //ch->loseCustomItem();
00332     }
00333 }
00334 
00335 // Based on QTextView::readFormats - with all code duplication moved to copyCharFormatting
00336 void KoTextObject::readFormats( KoTextCursor &c1, KoTextCursor &c2, bool copyParagLayouts, bool moveCustomItems )
00337 {
00338     //kdDebug(32500) << "KoTextObject::readFormats moveCustomItems=" << moveCustomItems << endl;
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         //kdDebug(32500) << "KoTextObject::readFormats copying from " << c1.index() << " to " << c1.parag()->length()-1 << " into lastIndex=" << lastIndex << endl;
00350         // Replace the trailing spaces with '\n'. That char carries the formatting for the trailing space.
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         //++lastIndex; // skip the '\n'.
00355         KoTextParag *p = c1.parag()->next();
00356         while ( p && p != c2.parag() ) {
00357             undoRedoInfo.text += p->string()->toString().left( p->length() - 1 ) + '\n';
00358             //kdDebug(32500) << "KoTextObject::readFormats (mid) copying from 0 to "  << p->length()-1 << " into i+" << lastIndex << endl;
00359             for ( i = 0; i < p->length(); ++i )
00360                 copyCharFormatting( p, i, i + lastIndex, moveCustomItems );
00361             lastIndex += p->length(); // + 1; // skip the '\n'
00362             //kdDebug(32500) << "KoTextObject::readFormats lastIndex now " << lastIndex << " - text is now " << undoRedoInfo.text.toString() << endl;
00363             p = p->next();
00364         }
00365         //kdDebug(32500) << "KoTextObject::readFormats copying [last] from 0 to " << c2.index() << " into i+" << lastIndex << endl;
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             //kdDebug(32500) << "KoTextObject:storeParagUndoRedoInfo storing counter " << start->paragLayout().counter.counterType << endl;
00412         }
00413     }
00414 }
00415 
00416 void KoTextObject::doKeyboardAction( KoTextCursor * cursor, KoTextFormat * & /*currentFormat*/, 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 ) // 'old' has been deleted
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         // Remove counter
00453         if ( parag->counter() && parag->counter()->style() != KoParagCounter::STYLE_NONE && cursor->index() == 0 ) {
00454             // parag->decDepth(); // We don't have support for nested lists at the moment
00455                                   // (only in titles, but you don't want Backspace to move it up)
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         // Nothing to do if at the beginning of the very first parag
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             //KoParagLayout paragLayout = cursor->parag()->paragLayout();
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() ) { // joining paragraphs
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 ) // different "following style" applied
00532             {
00533                 doUpdateCurrentFormat = true;
00534                 //currentFormat = textdoc->formatCollection()->format( cursor->parag()->paragFormat() );
00535                 //kdDebug(32500) << "KoTextFrameSet::doKeyboardAction currentFormat=" << currentFormat << " " << currentFormat->key() << endl;
00536             }
00537         }
00538         emit paragraphCreated( cursor->parag() );
00539 
00540     } break;
00541     case ActionKill:
00542         // Nothing to kill if at end of very last paragraph
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                 // Get paraglayout from next parag (next can't be 0 here)
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     //kdDebug(32500) << "KoTextObject::insert txt=" << txt << endl;
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() ) // see replace-selection
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; // the line the cursor was on before the insert
00623     oldCursor.parag()->lineStartOfChar( oldCursor.index(), 0, &origLine );
00624 
00625     cursor->insert( txt, checkNewLine );  // insert the text
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     //kdDebug(32500) << "KoTextObject::insert setting format " << currentFormat << endl;
00637     textdoc->setFormat( KoTextDocument::Temp, currentFormat, KoTextFormat::Format );
00638     textdoc->removeSelection( KoTextDocument::Temp );
00639 
00640     // Speed optimization: if we only type a char, and it doesn't
00641     // invalidate the next parag, only format the current one
00642     // ### This idea is wrong. E.g. when the last parag grows and must create a new page.
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     // Call formatMore until necessary. This will create new pages if needed.
00652     // Doing this here means callers don't have to do it, and cursor can be positionned correctly.
00653     ensureFormatted( cursor->parag() );
00654 
00655     // Speed optimization: if we only type a char, only repaint from current line
00656     // (In fact the one before. When typing a space, a word could move up to the
00657     // line before, we need to repaint it too...)
00658     if ( !checkNewLine && tinyRepaint && !wasChanged )
00659     {
00660         // insert() called format() which called setChanged().
00661         // We're reverting that, and calling setLineChanged() only.
00662         Q_ASSERT( cursor->parag() == oldCursor.parag() ); // no newline!
00663         KoTextParag* parag = cursor->parag();
00664     // If the new char led to a new line,
00665     // the wordwrap could have changed on the line above
00666     // This is why we use origLine and not calling lineStartOfChar here.
00667         parag->setChanged( false );
00668         parag->setLineChanged( origLine - 1 ); // if origLine=0, it'll pass -1, which is 'all'
00669     }
00670 
00671     if ( repaint ) {
00672         emit repaintChanged( this );
00673         emit ensureCursorVisible();
00674         emit showCursor();
00675         // we typed the first char of a paragraph in AlignAuto mode -> show correct alignment in UI
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         // ## not sure why we do this. I'd prefer leaving the selection unchanged...
00689         // but then it'd need adjustements in the offsets etc.
00690         if ( textdoc->removeSelection( selectionId ) && repaint )
00691             selectionChangedNotify(); // does the repaint
00692     }
00693     if ( !customItemsMap.isEmpty() )
00694         clearUndoRedoInfo();
00695 
00696     // Notifications
00697     emit paragraphModified( oldCursor.parag(), AddChar, cursor->index(), txt.length() );
00698     // TODO
00699     // if (checkNewLine)
00700     //     emit paragraphCreated for every paragraph from oldCursor->parag()->next() until cursor->parag()
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     // Need to convert CRLF to NL
00710     QRegExp crlf( QString::fromLatin1("\r\n") );
00711     t.replace( crlf, QChar('\n') );
00712     // Convert non-printable chars
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 /*checkNewLine*/, 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 ); // mem leak, if applyStyleCommand created a command despite createUndoRedo==false!
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     // 1
00760     //kdDebug(32500) << "KoTextObject::applyStyle setParagLayout" << endl;
00761     storeParagUndoRedoInfo( cursor, selectionId );
00762     undoRedoInfo.type = UndoRedoInfo::Invalid; // tricky, we don't want clear() to create a command
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             //kdDebug(32500) << "KoTextObject::applyStyle KoTextParagCommand" << endl;
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, /*cmd, */"related to KoTextParagCommand" ) );
00782         }
00783     }
00784 
00785     // 2
00786     //kdDebug(32500) << "KoTextObject::applyStyle gathering text and formatting" << endl;
00787     KoTextParag * firstParag;
00788     KoTextParag * lastParag;
00789     if ( !textdoc->hasSelection( selectionId, true ) ) {
00790         // No selection -> apply style formatting to the whole paragraph
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             //QString str;
00808             for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() )
00809             {
00810                 //str += parag->string()->toString() + '\n';
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; // same trick
00821             readFormats( c1, c2 ); // gather char-format info but not paraglayouts nor customitems
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, /*cmd, */"related to KoTextFormatCommand" ) );
00829 
00830             // sub-command for '3' (paragFormat)
00831             cmd = new KoParagFormatCommand( textdoc, firstParag->paragId(), lastParag->paragId(),
00832                                             lstFormats, newFormat );
00833             textdoc->addCommand( cmd );
00834             macroCmd->addCommand( new KoTextCommand( this, /*cmd, */"related to KoParagFormatCommand" ) );
00835         }
00836 
00837         // apply '2' and '3' (format)
00838         for ( KoTextParag * parag = firstParag ; parag && parag != lastParag->next() ; parag = parag->next() )
00839         {
00840             //kdDebug(32500) << "KoTextObject::applyStyle parag:" << parag->paragId()
00841             //               << ", from 0 to " << parag->string()->length() << ", format=" << newFormat << endl;
00842             parag->setFormat( 0, parag->string()->length(), newFormat, true, formatFlags );
00843             parag->setFormat( newFormat );
00844         }
00845         //currentFormat = textdoc->formatCollection()->format( newFormat );
00846         //kdDebug(32500) << "KoTextObject::applyStyle currentFormat=" << currentFormat << " " << currentFormat->key() << endl;
00847     }
00848 
00849     //resize all variables after applying the style
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     /*kdDebug(32500) << "KoTextObject::applyStyleChange " << changedStyle->name()
00872                      << " paragLayoutChanged=" << paragLayoutChanged
00873                      << " formatChanged=" << formatChanged
00874                      << endl;*/
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 ) // Style has been deleted
00882             {
00883                 p->setStyle( m_defaultStyle ); // keeps current formatting
00884                 // TODO, make this undoable somehow
00885             }
00886             else
00887             {
00888                 // Apply this style again, to get the changes
00889                 KoTextCursor cursor( textdoc );
00890                 cursor.setParag( p );
00891                 cursor.setIndex( 0 );
00892                 //kdDebug(32500) << "KoTextObject::applyStyleChange applying to paragraph " << p << " " << p->paragId() << endl;
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, // A selection we can't possibly have
00930                             (*it).paragLayoutChanged, (*it).formatChanged,
00931                             false, false ); // don't create undo/redo, not interactive
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 /*zoomFont*/, int selectionId )
00952 {
00953     KCommand *ret = 0;
00954     if ( protectContent() )
00955         return ret;
00956 
00957     KoTextFormat* newFormat = 0;
00958     // Get new format from collection if
00959     // - caller has notion of a "current format" and new format is different
00960     // - caller has no notion of "current format", e.g. whole textobjects
00961     bool isNewFormat = ( pCurrentFormat && *pCurrentFormat && (*pCurrentFormat)->key() != format->key() );
00962     if ( isNewFormat || !pCurrentFormat )
00963     {
00964 #if 0
00965         int origFontSize = 0;
00966         if ( zoomFont ) // The format has a user-specified font (e.g. setting a style, or a new font size)
00967         {
00968             origFontSize = format->pointSize();
00969             format->setPointSize( zoomedFontSize( origFontSize ) );
00970             //kdDebug(32500) << "KoTextObject::setFormatCommand format " << format->key() << " zoomed from " << origFontSize << " to " << format->font().pointSizeFloat() << endl;
00971         }
00972 #endif
00973         // Remove ref to current format, if caller wanted that
00974         if ( pCurrentFormat )
00975             (*pCurrentFormat)->removeRef();
00976         // Find format in collection
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 ); // read previous formatting info
00998         //kdDebug(32500) << "KoTextObject::setFormatCommand undoredo info done" << endl;
00999         textdoc->setFormat( selectionId, format, flags );
01000         if ( !undoRedoInfo.customItemsMap.isEmpty() )
01001         {
01002             // Some custom items (e.g. variables) depend on the format
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, /*cmd, */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         //kdDebug(32500) << "KoTextObject::setFormatCommand index=" << cursor->index() << " length-1=" << cursor->parag()->length() - 1 << endl;
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         // Special hack for BR25742, don't apply bullet to last empty parag of the selection
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 )  // don't apply to empty paragraphs (#25742, #34062)
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(); // type is still Invalid -> no command created
01096     emit showCursor();
01097     emit updateUI( true );
01098     return new KoTextCommand( this, /*cmd, */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; // No change needed.
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(); // type is still Invalid -> no command created
01132     emit showCursor();
01133     emit updateUI( true );
01134     return new KoTextCommand( this, /*cmd, */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     //kdDebug(32500) << "KoTextObject::setMargin " << m << " to value " << margin << endl;
01142     //kdDebug(32500) << "Current margin is " << cursor->parag()->margin(m) << endl;
01143     if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01144          cursor->parag()->margin(m) == margin )
01145         return 0L; // No change needed.
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, /*cmd, */name );
01180 }
01181 
01182 KCommand * KoTextObject::setLineSpacingCommand( KoTextCursor * cursor, double spacing, KoParagLayout::SpacingType _type, int selectionId )
01183 {
01184     if ( protectContent() )
01185         return 0L;
01186     //kdDebug(32500) << "KoTextObject::setLineSpacing to value " << spacing << endl;
01187     //kdDebug(32500) << "Current spacing is " << cursor->parag()->kwLineSpacing() << endl;
01188     //kdDebug(32500) << "Comparison says " << ( cursor->parag()->kwLineSpacing() == spacing ) << endl;
01189     //kdDebug(32500) << "hasSelection " << textdoc->hasSelection( selectionId ) << endl;
01190     if ( !textdoc->hasSelection( selectionId, true ) && cursor &&
01191          cursor->parag()->kwLineSpacing() == spacing
01192         && cursor->parag()->kwLineSpacingType() == _type)
01193         return 0L; // No change needed.
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, /*cmd, */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; // No change needed.
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             //remove border
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, /*cmd, */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; // No change needed.
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, /*cmd, */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; // No change needed.
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, /*cmd, */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     //kdDebug(32500) << "KoTextObject::removeSelectedText text=" << undoRedoInfo.text.toString() << endl;
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, /*cmd, */QString::null ));
01430 
01431     if(!undoRedoInfo.customItemsMap.isEmpty())
01432         undoRedoInfo.customItemsMap.deleteAll( macroCmd );
01433 
01434     undoRedoInfo.type = UndoRedoInfo::Invalid; // we don't want clear() to create a command
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     // Remember formatting
01451     KoTextCursor c1 = textdoc->selectionStartCursor( selectionId );
01452     KoTextFormat * format = c1.parag()->at( c1.index() )->format();
01453     format->addRef();
01454 
01455     // Remove selected text, if any
01456     KCommand* removeSelCmd = removeSelectedTextCommand( cursor, selectionId, repaint );
01457     if ( removeSelCmd )
01458         macroCmd->addCommand( removeSelCmd );
01459 
01460     // Insert replacement
01461     insert( cursor, format,
01462             replacement, true, false, QString::null /* no place holder command */,
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, /*cmd, */QString::null ) );
01470 
01471     undoRedoInfo.type = UndoRedoInfo::Invalid; // we don't want clear() to create a command
01472     undoRedoInfo.clear();
01473 
01474     format->removeRef();
01475 
01476     setLastFormattedParag( c1.parag() );
01477     if ( repaint ) // false during search/replace
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); // remove previous highlighted selection
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 /* = true */)
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 /* = true */ )
01562 {
01563     if ( !textdoc->lastParag() )
01564         return; // safety test
01565     //kdDebug(32500) << name() << " ensureFormatted " << parag->paragId() << endl;
01566     if ( !parag->isValid() && m_lastFormatted == 0 )
01567         m_lastFormatted = parag; // bootstrap
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         // The paragid diff is "a good guess". The >=1 is a safety measure ;)
01576         bool ret = formatMore( QMAX( 1, parag->paragId() - m_lastFormatted->paragId() ), emitAfterFormatting );
01577         if ( !ret ) { // aborted
01578             //kdDebug(32500) << "ensureFormatted aborted!" << endl;
01579             break;
01580         }
01581     }
01582     //kdDebug(32500) << name() << " ensureFormatted " << parag->paragId() << " done" << endl;
01583 }
01584 
01585 bool KoTextObject::formatMore( int count /* = 10 */, bool emitAfterFormatting /* = true */ )
01586 {
01587     if ( ( !m_lastFormatted && d->afterFormattingEmitted )
01588          || !m_visible || m_availableHeight == -1 )
01589         return false;
01590 
01591     if ( !textdoc->lastParag() )
01592         return false; // safety test
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         // Stop if we have formatted everything or if we need more space
01633         // Otherwise, stop formatting after "to" paragraphs,
01634         // but make sure we format everything the views need
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             // Check for Head 1 (i.e. section) titles, and emit them - for the Section variable
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 // formatting was done previously, but not emit afterFormatting
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         // Check if we need more space - for proper default value of 'abort'
01693         if ( ( bottom > m_availableHeight ) ||   // this parag is already off page
01694              ( m_lastFormatted && bottom + m_lastFormatted->rect().height() > m_availableHeight ) ) // or next parag will be off page
01695             abort = true;
01696         emit afterFormatting( bottom, m_lastFormatted, &abort );
01697         if ( abort )
01698             return false;
01699         else if ( m_lastFormatted ) // we got more space, keep formatting then
01700             return formatMore( 2 );
01701     }
01702 
01703     // Now let's see when we'll need to get back here.
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         //if ( frameSetInfo() == FI_BODY )
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     //kdDebug(32500) << "KoTextObject::doChangeInterval back to interval=0" << endl;
01734     interval = 0;
01735 }
01736 
01737 void KoTextObject::typingStarted()
01738 {
01739     //kdDebug(32500) << "KoTextObject::typingStarted" << endl;
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     //change last word
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 // Warning, this doesn't ref the format!
01909 KoTextFormat * KoTextObject::currentFormat() const
01910 {
01911     // We use the formatting of the very first character
01912     // Should we use a style instead, maybe ?
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     // This version of setFormat works on the whole textobject - we use the Temp selection for that
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     //format.setPointSize( docFontSize( currentFormat() ) ); // "unzoom" the font size
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 /* zoom the font size */ );
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     // "unzoom" the font size
02196     //fn.setPointSize( static_cast<int>( KoTextZoomHandler::layoutUnitPtToPt( fn.pointSize() ) ) );
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"
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Mar 11 11:47:44 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003