00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "KWTextFrameSet.h"
00022 #include "KWTableFrameSet.h"
00023 #include "KWDocument.h"
00024 #include "KWView.h"
00025 #include "KWViewMode.h"
00026 #include "KWCanvas.h"
00027 #include "KWAnchor.h"
00028 #include "KWCommand.h"
00029 #include "KWFormulaFrameSet.h"
00030 #include "KWBgSpellCheck.h"
00031 #include "KWordTextFrameSetIface.h"
00032 #include "KWordTextFrameSetEditIface.h"
00033 #include "KWordFootNoteFrameSetIface.h"
00034 #include "KWordFrameSetIface.h"
00035 #include "KWLoadingInfo.h"
00036 #include "KWInsertTOCCommand.h"
00037 #include "KWMailMergeDataBase.h"
00038 #include "KoTextBookmark.h"
00039 #include "KWVariable.h"
00040 #include "KWOasisSaver.h"
00041 #include "KWFrameList.h"
00042 #include "KWPageManager.h"
00043 #include "KWPage.h"
00044
00045 #include <KoParagCounter.h>
00046 #include <KoCustomVariablesDia.h>
00047 #include <KoAutoFormat.h>
00048 #include <KoTextObject.h>
00049 #include <KoTextCommand.h>
00050 #include <KoTextFormatter.h>
00051 #include <KoChangeCaseDia.h>
00052 #include <KoXmlNS.h>
00053 #include <KoXmlWriter.h>
00054 #include <KoOasisContext.h>
00055 #include <KoStore.h>
00056
00057 #include <klocale.h>
00058 #include <kaction.h>
00059 #include <kmessagebox.h>
00060 #include <kdebug.h>
00061
00062 #include <qclipboard.h>
00063 #include <qdragobject.h>
00064 #include <qcursor.h>
00065 #include <qfile.h>
00066 #include <qprogressdialog.h>
00067 #include <qregexp.h>
00068
00069 #include <assert.h>
00070 #include <qapplication.h>
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00087 class KWTextFormatter : public KoTextFormatter
00088 {
00089 public:
00090 KWTextFormatter( KWTextFrameSet *textfs ) : m_textfs( textfs ) {}
00091 virtual ~KWTextFormatter() {}
00092
00093 virtual int formatVertically( KoTextDocument*, KoTextParag* parag )
00094 {
00095 return m_textfs->formatVertically( parag, parag->rect() );
00096 }
00097 virtual void postFormat( KoTextParag* parag )
00098 {
00099 m_textfs->fixParagWidth( static_cast<KWTextParag *>( parag ) );
00100 }
00101 private:
00102 KWTextFrameSet *m_textfs;
00103 };
00104
00105 KWTextFrameSet::KWTextFrameSet( KWDocument *_doc, const QString & name )
00106 : KWFrameSet( _doc )
00107 {
00108
00109 if ( name.isEmpty() )
00110 m_name = _doc->generateFramesetName( i18n( "Text Frameset %1" ) );
00111 else
00112 m_name = name;
00113
00114 QObject::setName( m_name.utf8() );
00115 init();
00116 }
00117
00118 KWTextFrameSet::KWTextFrameSet( KWDocument* doc, const QDomElement& tag, KoOasisContext& )
00119 : KWFrameSet( doc )
00120 {
00121 m_name = tag.attributeNS( KoXmlNS::draw, "name", QString::null );
00122 if ( doc->frameSetByName( m_name ) )
00123 m_name = doc->generateFramesetName( m_name + " %1" );
00124 init();
00125
00126
00127 }
00128
00129
00130 KWTextFrameSet::KWTextFrameSet( const QString &name ) : KWFrameSet(0) {
00131 m_name = name;
00132
00133 QObject::setName( m_name.utf8() );
00134 m_currentViewMode = 0L;
00135 m_currentDrawnFrame = 0L;
00136 m_lastTextDocHeight = 0;
00137 m_textobj = 0;
00138 }
00139
00140 void KWTextFrameSet::init()
00141 {
00142 m_currentViewMode = 0L;
00143 m_currentDrawnFrame = 0L;
00144 m_lastTextDocHeight = 0;
00145
00146 KWTextDocument* textdoc = new KWTextDocument( this,
00147 new KoTextFormatCollection( m_doc->defaultFont(), QColor(),
00148 m_doc->globalLanguage(),
00149 m_doc->globalHyphenation() ),
00150 new KWTextFormatter( this ) );
00151 textdoc->setFlow( this );
00152 textdoc->setPageBreakEnabled( true );
00153 if ( m_doc->tabStopValue() != -1 )
00154 textdoc->setTabStops( m_doc->ptToLayoutUnitPixX( m_doc->tabStopValue() ));
00155
00156 m_textobj = new KoTextObject( textdoc, m_doc->styleCollection()->findStyle( "Standard" ),
00157 this, (m_name+"-textobj").utf8() );
00158 m_doc->backSpeller()->registerNewTextObject( m_textobj );
00159 connect( m_textobj, SIGNAL( availableHeightNeeded() ),
00160 SLOT( slotAvailableHeightNeeded() ) );
00161 connect( m_textobj, SIGNAL( afterFormatting( int, KoTextParag*, bool* ) ),
00162 SLOT( slotAfterFormatting( int, KoTextParag*, bool* ) ) );
00163
00164
00165
00166
00167 connect( m_textobj, SIGNAL( newCommand( KCommand * ) ),
00168 SLOT( slotNewCommand( KCommand * ) ) );
00169 connect( m_textobj, SIGNAL( repaintChanged( KoTextObject* ) ),
00170 SLOT( slotRepaintChanged() ) );
00171 connect( m_textobj, SIGNAL( paragraphDeleted( KoTextParag*) ),
00172 SLOT( slotParagraphDeleted(KoTextParag*) ));
00173
00174 connect( m_textobj, SIGNAL( paragraphCreated( KoTextParag*) ),
00175 SLOT( slotParagraphCreated(KoTextParag*) ));
00176 connect( m_textobj, SIGNAL( paragraphModified( KoTextParag*, int, int, int) ),
00177 SLOT( slotParagraphModified(KoTextParag*, int, int, int) ));
00178 }
00179
00180 void KWTextFrameSet::slotParagraphModified(KoTextParag* _parag, int _type, int start, int lenght)
00181 {
00182 kWordDocument()->paragraphModified(_parag, _type, start, lenght);
00183 }
00184
00185 void KWTextFrameSet::slotParagraphCreated(KoTextParag* )
00186 {
00187
00188 }
00189
00190 void KWTextFrameSet::slotParagraphDeleted(KoTextParag*_parag)
00191 {
00192 kWordDocument()->paragraphDeleted( _parag, this);
00193 }
00194
00195 KWordFrameSetIface* KWTextFrameSet::dcopObject()
00196 {
00197 if ( !m_dcop )
00198 m_dcop = new KWordTextFrameSetIface( this );
00199
00200 return m_dcop;
00201 }
00202
00203 KWFrameSetEdit * KWTextFrameSet::createFrameSetEdit( KWCanvas * canvas )
00204 {
00205 return new KWTextFrameSetEdit( this, canvas );
00206 }
00207
00208 KoTextDocument * KWTextFrameSet::textDocument() const
00209 {
00210 return m_textobj->textDocument();
00211 }
00212
00213 KWTextDocument * KWTextFrameSet::kwTextDocument() const
00214 {
00215 return static_cast<KWTextDocument *>(m_textobj->textDocument());
00216 }
00217
00218 void KWTextFrameSet::slotAvailableHeightNeeded()
00219 {
00220 Q_ASSERT( isVisible() );
00221 kdDebug() << "KWTextFrameSet::slotAvailableHeightNeeded " << name() << endl;
00222 updateFrames( 0 );
00223 }
00224
00225 KWFrame * KWTextFrameSet::documentToInternal( const KoPoint &dPoint, QPoint &iPoint ) const
00226 {
00227 #ifdef DEBUG_DTI
00228 kdDebug() << "KWTextFrameSet::documentToInternal dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
00229 #endif
00230 if ( !m_doc->layoutViewMode()->hasFrames() ) {
00231 iPoint = QPoint( m_doc->ptToLayoutUnitPixX( dPoint.x() ),
00232 m_doc->ptToLayoutUnitPixY( dPoint.y() ) );
00233 return m_frames.getFirst();
00234 }
00235
00236 int pageNum = m_doc->pageManager()->pageNumber(dPoint);
00237 QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum ) );
00238 for ( ; frameIt.current(); ++frameIt )
00239 {
00240 KWFrame *theFrame = frameIt.current();
00241 if ( theFrame->contains( dPoint ) )
00242 {
00243 iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->innerRect().x() ) );
00244 iPoint.setY( m_doc->ptToLayoutUnitPixY( dPoint.y() - theFrame->innerRect().y() + theFrame->internalY() ) );
00245 #ifdef DEBUG_DTI
00246 kdDebug() << "documentToInternal: returning " << iPoint.x() << "," << iPoint.y()
00247 << " internalY=" << theFrame->internalY() << " because frame=" << theFrame
00248 << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
00249 #endif
00250 return theFrame;
00251 }
00252 #ifdef DEBUG_DTI
00253
00254
00255
00256 #endif
00257 }
00258
00259 iPoint = m_doc->ptToLayoutUnitPix( dPoint );
00260 return 0;
00261 }
00262
00263 KWFrame * KWTextFrameSet::documentToInternalMouseSelection( const KoPoint &dPoint, QPoint &iPoint, RelativePosition& relPos, KWViewMode *viewMode ) const
00264 {
00265 #ifdef DEBUG_DTI
00266 kdDebug() << "KWTextFrameSet::documentToInternalMouseSelection dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
00267 #endif
00268 if ( !viewMode->hasFrames() ) {
00269 relPos = InsideFrame;
00270 iPoint = QPoint( m_doc->ptToLayoutUnitPixX( dPoint.x() ),
00271 m_doc->ptToLayoutUnitPixY( dPoint.y() ) );
00272 return m_frames.getFirst();
00273 }
00274
00275
00276 int pageNum = m_doc->pageManager()->pageNumber(dPoint);
00277 QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum ) );
00278 for ( ; frameIt.current(); ++frameIt )
00279 {
00280 KWFrame *theFrame = frameIt.current();
00281 if ( theFrame->contains( dPoint ) )
00282 {
00283 iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->innerRect().x() ) );
00284 iPoint.setY( m_doc->ptToLayoutUnitPixY( dPoint.y() - theFrame->innerRect().y() + theFrame->internalY() ) );
00285 #ifdef DEBUG_DTI
00286 kdDebug() << "documentToInternal: returning InsideFrame " << iPoint.x() << "," << iPoint.y()
00287 << " internalY=" << theFrame->internalY() << " because frame=" << theFrame
00288 << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
00289 #endif
00290 relPos = InsideFrame;
00291 return theFrame;
00292 }
00293 }
00294 frameIt.toFirst();
00295 for ( ; frameIt.current(); ++frameIt )
00296 {
00297 KWFrame *theFrame = frameIt.current();
00298 KoRect openLeftRect( theFrame->innerRect() );
00299 openLeftRect.setLeft( theFrame->paddingLeft() );
00300 #ifdef DEBUG_DTI
00301 kdDebug() << "documentToInternal: openLeftRect=" << openLeftRect << endl;
00302 #endif
00303 if ( openLeftRect.contains( dPoint ) )
00304 {
00305
00306 iPoint.setX( m_doc->ptToLayoutUnitPixX(theFrame->innerRect().left() ));
00307 iPoint.setY( m_doc->ptToLayoutUnitPixY( dPoint.y() - theFrame->top() + theFrame->internalY() ) );
00308 #ifdef DEBUG_DTI
00309 kdDebug() << "documentToInternal: returning LeftOfFrame " << iPoint.x() << "," << iPoint.y()
00310 << " internalY=" << theFrame->internalY() << " because openLeftRect=" << openLeftRect
00311 << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
00312 #endif
00313 relPos = LeftOfFrame;
00314 return theFrame;
00315 }
00316 KoRect openTopRect( KoPoint( 0, 0 ), theFrame->innerRect().bottomRight() );
00317 #ifdef DEBUG_DTI
00318 kdDebug() << "documentToInternal: openTopRect=" << openTopRect << endl;
00319 #endif
00320 if ( openTopRect.contains( dPoint ) )
00321 {
00322
00323 iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->innerRect().left() ) );
00324 iPoint.setY( m_doc->ptToLayoutUnitPixY( theFrame->internalY() ) );
00325 #ifdef DEBUG_DTI
00326 kdDebug() << "documentToInternal: returning " << iPoint.x() << "," << iPoint.y()
00327 << " internalY=" << theFrame->internalY() << " because openTopRect=" << openTopRect
00328 << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
00329 #endif
00330 relPos = TopOfFrame;
00331 return theFrame;
00332 }
00333 }
00334
00335
00336 if ( pageNum + 1 >= (int)m_framesInPage.size() + m_firstPage )
00337 {
00338
00339 KWFrame *theFrame = m_frames.getLast();
00340 iPoint.setX( m_doc->ptToLayoutUnitPixX( theFrame->innerWidth() ) );
00341 iPoint.setY( m_doc->ptToLayoutUnitPixY( theFrame->innerHeight() ) );
00342 #ifdef DEBUG_DTI
00343 kdDebug() << "documentToInternal: returning AtEnd " << iPoint.x() << "," << iPoint.y()
00344 << " because we are under all frames of the last page" << endl;
00345 #endif
00346 relPos = AtEnd;
00347 return theFrame;
00348 }
00349 else
00350 {
00351 QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum + 1 ) );
00352 if ( frameIt.current() )
00353 {
00354
00355 KWFrame *theFrame = frameIt.current();
00356 KoRect openTopRect( theFrame->innerRect() );
00357 openTopRect.setTop( 0 );
00358 if ( openTopRect.contains( dPoint ) )
00359 iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->left() ) );
00360 else
00361 iPoint.setX( 0 );
00362 iPoint.setY( m_doc->ptToLayoutUnitPixY( theFrame->internalY() ) );
00363 #ifdef DEBUG_DTI
00364 kdDebug() << "documentToInternal: returning TopOfFrame " << iPoint.x() << "," << iPoint.y()
00365 << " because we are under all frames of page " << pageNum << endl;
00366 #endif
00367 relPos = TopOfFrame;
00368 return theFrame;
00369 }
00370
00371 }
00372
00373 iPoint = m_doc->ptToLayoutUnitPix( dPoint );
00374 #ifdef DEBUG_DTI
00375 kdDebug() << "documentToInternal: returning not found for " << iPoint.x() << "," << iPoint.y() << endl;
00376 #endif
00377 return 0;
00378 }
00379
00380 KWFrame * KWTextFrameSet::internalToDocumentWithHint( const QPoint &iPoint, KoPoint &dPoint, const KoPoint &hintDPoint ) const
00381 {
00382 #ifdef DEBUG_ITD
00383 kdDebug() << "KWTextFrameSet::internalToDocumentWithHint hintDPoint: " << hintDPoint.x() << "," << hintDPoint.y() << endl;
00384 #endif
00385 if ( !m_doc->layoutViewMode()->hasFrames() ) {
00386 dPoint = m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) );
00387 return m_frames.getFirst();
00388 }
00389 KWFrame *lastFrame = 0L;
00390 QPtrListIterator<KWFrame> frameIt( frameIterator() );
00391 for ( ; frameIt.current(); ++frameIt )
00392 {
00393 KWFrame *theFrame = frameIt.current();
00394 QRect r( 0, m_doc->ptToLayoutUnitPixY( theFrame->internalY() ), m_doc->ptToLayoutUnitPixX( theFrame->innerWidth() )+1, m_doc->ptToLayoutUnitPixY( theFrame->innerHeight() )+1 );
00395 #ifdef DEBUG_ITD
00396 kdDebug() << "ITD: r=" << r << " iPoint=" << iPoint.x() << "," << iPoint.y() << endl;
00397 #endif
00398
00399 if ( r.contains( iPoint ) )
00400 {
00401 dPoint = internalToDocumentKnowingFrame( iPoint, theFrame );
00402 #ifdef DEBUG_ITD
00403 kdDebug() << "copy: " << theFrame->isCopy() << " hintDPoint.y()=" << hintDPoint.y() << " dPoint.y()=" << dPoint.y() << endl;
00404 #endif
00405
00406
00407 if ( hintDPoint.isNull() || hintDPoint.y() <= dPoint.y() )
00408 return theFrame;
00409
00410 lastFrame = theFrame;
00411 }
00412 else if ( lastFrame )
00413 {
00414 return lastFrame;
00415 }
00416 }
00417
00418
00419
00420 #ifdef DEBUG_ITD
00421 kdDebug(32002) << "KWTextFrameSet::internalToDocumentWithHint " << iPoint.x() << "," << iPoint.y()
00422 << " not in any frame of " << (void*)this << endl;
00423 #endif
00424 dPoint = m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) );
00425 return 0L;
00426 }
00427
00428
00429 KoPoint KWTextFrameSet::internalToDocumentKnowingFrame( const KoPoint &relPoint, KWFrame* theFrame ) const
00430 {
00431
00432 if ( m_doc->layoutViewMode()->hasFrames() )
00433 Q_ASSERT( theFrame );
00434 if ( theFrame )
00435 return KoPoint( relPoint.x() + theFrame->innerRect().x(),
00436 relPoint.y() - theFrame->internalY() + theFrame->innerRect().y() );
00437 else
00438 return relPoint;
00439 }
00440
00441 KoPoint KWTextFrameSet::internalToDocumentKnowingFrame( const QPoint &iPoint, KWFrame* theFrame ) const
00442 {
00443
00444 return internalToDocumentKnowingFrame( m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) ), theFrame );
00445 }
00446
00447 QPoint KWTextFrameSet::moveToPage( int currentPgNum, short int direction ) const
00448 {
00449 if ( !isVisible() || m_frames.isEmpty() )
00450 return QPoint();
00451
00452 int num = currentPgNum + direction;
00453 int pages = m_doc->pageCount();
00454 for ( ; num >= 0 && num < pages ; num += direction )
00455 {
00456
00457
00458 if ( num < m_firstPage || num >= (int)m_framesInPage.size() + m_firstPage )
00459 continue;
00460
00461
00462 QPtrListIterator<KWFrame> frameIt( framesInPage( num ) );
00463 return QPoint( 0, m_doc->ptToLayoutUnitPixY( frameIt.current()->internalY() ) + 2 );
00464 }
00465
00466 if ( direction < 0 )
00467 return QPoint( 0, m_doc->ptToLayoutUnitPixY( m_frames.getFirst()->internalY() ) + 2 );
00468 else
00469 {
00470 KWFrame * theFrame = m_frames.getLast();
00471 return QPoint( 0, m_doc->ptToLayoutUnitPixY( theFrame->internalY() + theFrame->innerHeight() ) );
00472 }
00473 }
00474
00475 void KWTextFrameSet::drawContents( QPainter *p, const QRect & crect, const QColorGroup &cg,
00476 bool onlyChanged, bool resetChanged,
00477 KWFrameSetEdit *edit, KWViewMode *viewMode,
00478 KWFrameViewManager *fvm)
00479 {
00480 m_currentViewMode = viewMode;
00481 KWFrameSet::drawContents( p, crect, cg, onlyChanged, resetChanged, edit, viewMode, fvm );
00482
00483
00484 if ( isMainFrameset() && viewMode->hasFrames() )
00485 {
00486
00487
00488
00489
00490 if ( m_doc->footNoteSeparatorLineWidth() ==0.0)
00491 return;
00492
00493 int pages = m_doc->pageCount();
00494 KWPage *page = m_doc->pageManager()->page(m_doc->pageManager()->startPage());
00495 double left = page->leftMargin();
00496 double pageWidth = page->width() - page->rightMargin() - left;
00497 double width = pageWidth * m_doc->footNoteSeparatorLineLength() / 100.0;
00498 int numColumns = m_doc->numColumns();
00499 for ( int pageNum = 0; pageNum < pages; pageNum++ )
00500 {
00501
00502 {
00503 uint frameNum = pageNum * numColumns ;
00504 if ( frameNum < frameCount() )
00505 {
00506 KWFrame* frame = this->frame( frameNum );
00507
00508 if ( frame->drawFootNoteLine() )
00509 {
00510 double y = frame->bottomLeft().y() + m_doc->headerFooterInfo().ptFootNoteBodySpacing / 2;
00511 KoRect rect( left, y, width, 0 );
00512 switch( m_doc->footNoteSeparatorLinePosition())
00513 {
00514 case SLP_LEFT:
00515 break;
00516 case SLP_CENTERED:
00517 rect = KoRect( pageWidth/2.0+left-width/2.0, y,width,0);
00518 break;
00519 case SLP_RIGHT:
00520 rect = KoRect( pageWidth+left-width, y,width,0);
00521 break;
00522 }
00523
00524 QRect flatRect = viewMode->normalToView( m_doc->zoomRect( rect ) );
00525
00526 flatRect.setBottom( flatRect.top() + 1 );
00527 if ( flatRect.intersects( crect ) ) {
00528 p->save();
00529 QPen pen( KoTextFormat::defaultTextColor( p ),
00530 KoBorder::zoomWidthY( m_doc->footNoteSeparatorLineWidth(), m_doc, 1 ) );
00531 switch( m_doc->footNoteSeparatorLineType())
00532 {
00533 case SLT_SOLID:
00534 pen.setStyle( SolidLine );
00535 break;
00536 case SLT_DASH:
00537 pen.setStyle( DashLine );
00538 break;
00539 case SLT_DOT:
00540 pen.setStyle( DotLine );
00541 break;
00542 case SLT_DASH_DOT:
00543 pen.setStyle( DashDotLine );
00544 break;
00545 case SLT_DASH_DOT_DOT:
00546 pen.setStyle( DashDotDotLine );
00547 break;
00548 }
00549 p->setPen( pen );
00550 p->drawLine( flatRect.left(), flatRect.top(), flatRect.right(), flatRect.top() );
00551
00552 p->restore();
00553 }
00554 }
00555 }
00556 }
00557 }
00558 }
00559 }
00560
00561 void KWTextFrameSet::drawFrame( KWFrame *theFrame, QPainter *painter, const QRect &fcrect, const QRect &crect,
00562 const QPoint& translationOffset,
00563 KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
00564 KWFrameSetEdit *edit, KWViewMode *viewMode, bool drawUnderlyingFrames )
00565 {
00566
00567
00568 if ( theFrame )
00569 {
00570 drawUnderlyingFrames &= theFrame->isTransparent();
00571 }
00572 KWFrameSet::drawFrame( theFrame, painter, fcrect, crect, translationOffset, settingsFrame, cg, onlyChanged, resetChanged, edit, viewMode, drawUnderlyingFrames );
00573 }
00574
00575 void KWTextFrameSet::drawFrameContents( KWFrame *theFrame, QPainter *painter, const QRect &r,
00576 const QColorGroup &cg, bool onlyChanged, bool resetChanged,
00577 KWFrameSetEdit *edit, KWViewMode *viewMode )
00578 {
00579 Q_ASSERT( r.isValid() );
00580
00581
00582
00583
00584 m_currentDrawnFrame = theFrame;
00585 if ( theFrame )
00586 {
00587
00588
00589 QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
00590 for ( ; cit.current() ; ++cit )
00591 {
00592 KWPgNumVariable * var = dynamic_cast<KWPgNumVariable *>( cit.current() );
00593 if ( var && !var->isDeleted() )
00594 {
00595 QSize oldSize( var->width, var->height );
00596 const int pageNumberOffset = kWordDocument()->variableCollection()->variableSetting()->startingPageNumber() - 1;
00597 switch ( var->subType() )
00598 {
00599 case KWPgNumVariable::VST_PGNUM_CURRENT:
00600
00601
00602 var->setPgNum( theFrame->pageNumber() + pageNumberOffset );
00603 break;
00604 case KWPgNumVariable::VST_CURRENT_SECTION:
00605 var->setSectionTitle( kWordDocument()->sectionTitle( theFrame->pageNumber() ) );
00606 break;
00607 case KWPgNumVariable::VST_PGNUM_PREVIOUS:
00608 var->setPgNum( QMAX(theFrame->pageNumber()-1,0) + pageNumberOffset );
00609 break;
00610 case KWPgNumVariable::VST_PGNUM_NEXT:
00611 var->setPgNum( theFrame->pageNumber() + 1 + pageNumberOffset );
00612 break;
00613 }
00614
00615 var->resize();
00616 QSize newSize( var->width, var->height );
00617 if ( oldSize != newSize )
00618 var->paragraph()->invalidate( 0 );
00619 var->paragraph()->setChanged( true );
00620 }
00621 }
00622 }
00623
00624 KoTextCursor * cursor = edit ? (dynamic_cast<KWTextFrameSetEdit *>(edit) ? static_cast<KWTextFrameSetEdit *>(edit)->cursor() : 0) : 0;
00625 uint drawingFlags = 0;
00626 if ( viewMode->drawSelections() )
00627 drawingFlags |= KoTextDocument::DrawSelections;
00628 if ( !viewMode->drawFrameBackground() )
00629 drawingFlags |= KoTextDocument::TransparentBackground;
00630 if ( m_doc->backgroundSpellCheckEnabled() )
00631 drawingFlags |= KoTextDocument::DrawMisspelledLine;
00632 if ( m_doc->viewFormattingChars() )
00633 drawingFlags |= KoTextDocument::DrawFormattingChars;
00634
00635
00636 KoTextParag * lastFormatted = textDocument()->drawWYSIWYG(
00637 painter, r.x(), r.y(), r.width(), r.height(),
00638 cg, kWordDocument(),
00639 onlyChanged, false, cursor, resetChanged, drawingFlags );
00640
00641
00642
00643
00644 if ( onlyChanged && resetChanged )
00645 {
00646
00647
00648 KoTextParag * lastDrawn = lastFormatted->prev();
00649 if ( lastFormatted == textDocument()->lastParag() && ( !lastDrawn || m_doc->layoutUnitToPixelY( lastDrawn->rect().bottom() ) < r.bottom() ) )
00650 lastDrawn = lastFormatted;
00651
00652
00653 if ( lastDrawn && m_doc->layoutUnitToPixelY( lastDrawn->rect().bottom() ) > r.bottom() )
00654 {
00655
00656 lastDrawn->setChanged( true );
00657 }
00658 }
00659
00660
00661
00662
00663
00664
00665
00666 if ( ( !lastFormatted || lastFormatted == textDocument()->lastParag() )
00667 && viewMode->drawFrameBackground() )
00668 {
00669
00670 int docHeight = textDocument()->lastParag()->pixelRect(m_doc).bottom() + 1;
00671
00672
00673 QSize availSize = viewMode->availableSizeForText( this );
00674 QRect blank( 0, docHeight, availSize.width(), availSize.height() - docHeight );
00675
00676 painter->fillRect( blank, cg.brush( QColorGroup::Base ) );
00677
00678
00679 }
00680 m_currentDrawnFrame = 0L;
00681 }
00682
00683 void KWTextFrameSet::drawCursor( QPainter *p, KoTextCursor *cursor, bool cursorVisible, KWCanvas *canvas, KWFrame *theFrame )
00684 {
00685
00686 m_currentViewMode = canvas->viewMode();
00687 bool hasFrames = m_currentViewMode->hasFrames();
00688 m_currentDrawnFrame = theFrame;
00689
00690 QRect normalFrameRect;
00691 if (hasFrames)
00692 normalFrameRect = m_doc->zoomRect( theFrame->innerRect() );
00693 else
00694 normalFrameRect = QRect( QPoint(0, 0), m_currentViewMode->contentsSize() );
00695
00696 KoTextParag* parag = cursor->parag();
00697 QPoint topLeft = parag->rect().topLeft();
00698 int lineY;
00699
00700 int cursorHeight = m_doc->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) );
00701 QPoint iPoint( topLeft.x() + cursor->x(),
00702 topLeft.y() + lineY );
00703
00704 #ifdef DEBUG_CURSOR
00705 kdDebug() << "KWTextFrameSet::drawCursor topLeft=" << topLeft.x() << "," << topLeft.y()
00706 << " x=" << cursor->x() << " y=" << lineY << endl;
00707 kdDebug() << "KWTextFrameSet::drawCursor iPoint=" << iPoint.x() << "," << iPoint.y()
00708 << " cursorHeight=" << cursorHeight << endl;
00709 #endif
00710 KoPoint dPoint;
00711 KoPoint hintDPoint = theFrame ? theFrame->innerRect().topLeft() : KoPoint();
00712 if ( internalToDocumentWithHint( iPoint, dPoint, hintDPoint ) )
00713 {
00714 #ifdef DEBUG_CURSOR
00715 kdDebug() << " dPoint(doc, pts)=" << dPoint.x() << "," << dPoint.y() << endl;
00716 QPoint debugPt = m_doc->zoomPoint( dPoint );
00717 kdDebug() << " zoomed dPoint(doc, pixels)=" << debugPt.x() << "," << debugPt.y() << endl;
00718 #endif
00719 QPoint vPoint = m_currentViewMode->normalToView( m_doc->zoomPoint( dPoint ) );
00720 #ifdef DEBUG_CURSOR
00721 kdDebug() << " vPoint(view, pixels)=" << vPoint.x() << "," << vPoint.y() << endl;
00722 #endif
00723
00724 iPoint = m_doc->layoutUnitToPixel( iPoint );
00725
00726 #ifdef DEBUG_CURSOR
00727
00728 #endif
00729
00730
00731
00732 QRect clip( vPoint.x() - 5, vPoint.y(), 10, cursorHeight );
00733
00734 #ifdef DEBUG_CURSOR
00735 kdDebug() << " clip(view, before intersect)=" << clip << endl;
00736 #endif
00737
00738 QRect viewFrameRect = m_currentViewMode->normalToView( normalFrameRect );
00739 clip &= viewFrameRect;
00740 #ifdef DEBUG_CURSOR
00741 kdDebug() << "KWTextFrameSet::drawCursor normalFrameRect=" << normalFrameRect
00742 << " clip(view, after intersect)=" << clip << endl;
00743 #endif
00744
00745 QRegion reg;
00746 if ( hasFrames ) {
00747 reg = frameClipRegion( p, theFrame, clip, m_currentViewMode );
00748 if ( !isFloating() )
00749 reg &= p->xForm( viewFrameRect );
00750 }
00751
00752 if ( !hasFrames || !reg.isEmpty() )
00753 {
00754 #ifdef DEBUG_CURSOR
00755
00756
00757 #endif
00758
00759 p->save();
00760 QColorGroup cg = QApplication::palette().active();
00761
00762 if ( hasFrames )
00763 {
00764 p->setClipRegion( reg );
00765
00766
00767 int translationX = viewFrameRect.left();
00768 int translationY = viewFrameRect.top() - m_doc->zoomItY( theFrame->internalY() );
00769 #ifdef DEBUG_CURSOR
00770 kdDebug() << " translating Y by viewFrameRect.top()-internalY in pixelY= " << viewFrameRect.top() << "-" << m_doc->zoomItY( theFrame->internalY() ) << "=" << viewFrameRect.top() - m_doc->zoomItY( theFrame->internalY() ) << endl;
00771 #endif
00772 p->translate( translationX, translationY );
00773 p->setBrushOrigin( p->brushOrigin().x() + translationX, p->brushOrigin().y() + translationY );
00774
00775
00776 KWFrame * settings = settingsFrame( theFrame );
00777
00778 QBrush bgBrush( settings->backgroundColor() );
00779 bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), p ) );
00780 cg.setBrush( QColorGroup::Base, bgBrush );
00781
00782 QColor background = bgBrush.color();
00783 cg.setColor(QColorGroup::Text, QColor( 255 - background.red(),
00784 255 - background.green(), 255 - background.blue()) );
00785 }
00786 else if(dynamic_cast<KWViewModeText *>(m_currentViewMode) != 0)
00787 p->translate( KWViewModeText::OFFSET, 0 );
00788
00789 QPixmap *pix = 0;
00790 uint drawingFlags = KoTextDocument::DrawSelections;
00791 if ( m_doc->backgroundSpellCheckEnabled() )
00792 drawingFlags |= KoTextDocument::DrawMisspelledLine;
00793 if ( m_doc->viewFormattingChars() )
00794 drawingFlags |= KoTextDocument::DrawFormattingChars;
00795
00796
00797 bool wasChanged = parag->hasChanged();
00798 int oldLineChanged = parag->lineChanged();
00799 int line;
00800 parag->lineStartOfChar( cursor->index(), 0, &line );
00801 parag->setChanged( false );
00802 parag->setLineChanged( line );
00803
00804 textDocument()->drawParagWYSIWYG(
00805 p, parag,
00806 QMAX(0, iPoint.x() - 5),
00807 iPoint.y(), clip.width(), clip.height(),
00808 pix, cg, m_doc,
00809 cursorVisible, cursor, FALSE , drawingFlags );
00810
00811 if ( wasChanged )
00812 parag->setLineChanged( oldLineChanged );
00813 else
00814 parag->setChanged( false );
00815
00816 p->restore();
00817
00818
00819 QPoint ximPoint = vPoint;
00820 canvas->setXimPosition( ximPoint.x(), ximPoint.y(),
00821 0, cursorHeight - parag->lineSpacing( line ) );
00822 }
00823 }
00824 m_currentDrawnFrame = 0L;
00825 }
00826
00827 void KWTextFrameSet::layout()
00828 {
00829 invalidate();
00830
00831 m_textobj->formatMore( 2 );
00832 }
00833
00834 void KWTextFrameSet::invalidate()
00835 {
00836
00837 m_textobj->setLastFormattedParag( textDocument()->firstParag() );
00838 textDocument()->invalidate();
00839 }
00840
00841 void KWTextFrameSet::slotRepaintChanged()
00842 {
00843 emit repaintChanged( this );
00844 }
00845
00846 int KWTextFrameSet::paragraphs()
00847 {
00848 int paragraphs = 0;
00849 KoTextParag * parag = textDocument()->firstParag();
00850 for ( ; parag ; parag = parag->next() )
00851 paragraphs++;
00852 return paragraphs;
00853 }
00854
00855 int KWTextFrameSet::paragraphsSelected()
00856 {
00857 int paragraphs = 0;
00858 KoTextParag *parag = textDocument()->firstParag();
00859 for ( ; parag ; parag = parag->next() ) {
00860 if ( parag->hasSelection( KoTextDocument::Standard ) )
00861 paragraphs++;
00862 }
00863 return paragraphs;
00864 }
00865
00866
00867 bool KWTextFrameSet::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
00868 ulong & sentences, ulong & syllables, ulong & lines, bool selected )
00869 {
00870 return m_textobj->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected );
00871 }
00872
00873
00874 #define kdDebugBody(area) if ( frameSetInfo() == FI_BODY ) kdDebug(area)
00875
00876 QValueList<KWFrame*> KWTextFrameSet::framesFromTo( int y1, int y2 ) const
00877 {
00878 QValueList<KWFrame*> framesList;
00879 KoPoint pt;
00880 KWFrame * firstFrame = internalToDocument( QPoint(0, y1), pt );
00881 if ( !firstFrame )
00882 return framesList;
00883 framesList.append( firstFrame );
00884 uint frameIndex = const_cast<KWTextFrameSet *>(this)->m_frames.findRef( firstFrame );
00885 while ( ++frameIndex < m_frames.count() ) {
00886 KWFrame* f = frame( frameIndex );
00887 if ( f->internalY() > y2 )
00888 break;
00889 framesList.append( f );
00890 }
00891 return framesList;
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901 void KWTextFrameSet::getMargins( int yp, int h, int reqMinWidth,
00902 int* marginLeft, int* marginRight, int* pageWidth,
00903 int* validHeight,
00904 int* breakBegin, int* breakEnd, KoTextParag* parag )
00905 {
00906
00907
00908
00909
00910 int paragLeftMargin = parag ? parag->leftMargin() : 0;
00911 if ( parag && !parag->string()->isRightToLeft() && parag->firstLineMargin() > 0 )
00912 paragLeftMargin += parag->firstLineMargin();
00913 #ifdef DEBUG_MARGINS
00914 kdDebugBody(32002) << " KWTextFrameSet " << this << "(" << name() << ") getMargins yp=" << yp
00915 << " h=" << h << " called by "
00916 << (marginLeft && marginRight ? "adjustMargins" : "formatVertically")
00917 << " paragLeftMargin=" << paragLeftMargin
00918 << endl;
00919
00920 if (breakBegin) assert(breakEnd);
00921 if (breakEnd) assert(breakBegin);
00922
00923 if ( marginLeft ) { assert( marginRight ); assert( pageWidth ); }
00924 #endif
00925
00926
00927
00928
00929 QValueList<KWFrame*> textFrames = framesFromTo( yp, yp + h );
00930 if (textFrames.isEmpty())
00931 {
00932 #ifdef DEBUG_MARGINS
00933 kdDebug(32002) << " getMargins: internalToDocument returned no text frames for y1=" << yp << " y2=" << yp + h << " ->aborting with 0 margins" << endl;
00934 #endif
00935
00936
00937
00938 if ( !m_frames.isEmpty() && m_frames.last()->frameBehavior() == KWFrame::AutoExtendFrame )
00939 {
00940 textFrames.append( m_frames.last() );
00941 }
00942 else
00943 {
00944
00945
00946
00947
00948 if ( validHeight )
00949 *validHeight = 0;
00950 return;
00951 }
00952 }
00953 else
00954 {
00955
00956 #ifdef DEBUG_MARGINS
00957 kdDebugBody(32002) << " getMargins: internalToDocument returned " << textFrames.count() << " frames holding this paragraph" << endl;
00958 #endif
00959 }
00960 if ( validHeight )
00961 *validHeight = h;
00962
00963
00964
00965
00966
00967 int from = 0;
00968
00969 int to = m_doc->ptToLayoutUnitPixX( textFrames.first()->innerWidth() );
00970 if ( pageWidth )
00971 *pageWidth = to;
00972 bool init = false;
00973
00974 #ifdef DEBUG_MARGINS
00975 kdDebugBody(32002) << " getMargins: looking for frames between " << yp << " and " << yp+h << " (internal coords)" << endl;
00976 #endif
00977 if ( m_doc->layoutViewMode()->shouldAdjustMargins() )
00978 {
00979
00980
00981 for ( QValueList<KWFrame*>::const_iterator txtit = textFrames.begin(), txtend = textFrames.end() ; txtit != txtend ; ++txtit ) {
00982 KWFrame* theFrame = *txtit;
00983 Q_ASSERT( theFrame->frameStack() );
00984 QValueList<KWFrame*> onTop = theFrame->frameStack()->framesOnTop();
00985 for (QValueListIterator<KWFrame*> fIt = onTop.begin(); from < to && fIt != onTop.end(); ++fIt )
00986 {
00987 if ( (*fIt)->runAround() == KWFrame::RA_BOUNDINGRECT )
00988 {
00989 KoRect rectOnTop = theFrame->intersect( (*fIt)->runAroundRect() );
00990 #ifdef DEBUG_MARGINS
00991 kdDebugBody(32002) << " getMargins found frame on top " << (*fIt)->frameSet()->name() << " with rect-on-top at (normal coords) " << rectOnTop << endl;
00992 #endif
00993 QPoint iTop, iBottom;
00994
00995 if ( documentToInternal( rectOnTop.topLeft(), iTop ) &&
00996 iTop.y() <= yp + h &&
00997 documentToInternal( rectOnTop.bottomRight(), iBottom ) )
00998 {
00999 #ifdef DEBUG_MARGINS
01000 kdDebugBody(32002) << " in internal coords: " << QRect(iTop,iBottom) << endl;
01001 #endif
01002
01003 if ( QMAX( yp, iTop.y() ) <= QMIN( yp+h, iBottom.y() ) )
01004 {
01005 #ifdef DEBUG_MARGINS
01006 kdDebugBody(32002) << " getMargins iTop=" << iTop.x() << "," << iTop.y()
01007 << " iBottom=" << iBottom.x() << "," << iBottom.y() << endl;
01008 #endif
01009 int availLeft = QMAX( 0, iTop.x() - from );
01010 int availRight = QMAX( 0, to - iBottom.x() );
01011 #ifdef DEBUG_MARGINS
01012 kdDebugBody(32002) << " getMargins availLeft=" << availLeft
01013 << " availRight=" << availRight << endl;
01014 #endif
01015 bool chooseLeft = false;
01016 switch ( (*fIt)->runAroundSide() ) {
01017 case KWFrame::RA_LEFT:
01018 chooseLeft = true;
01019 break;
01020 case KWFrame::RA_RIGHT:
01021 break;
01022 case KWFrame::RA_BIGGEST:
01023 chooseLeft = ( availLeft > availRight );
01024 };
01025
01026 if ( chooseLeft )
01027
01028 to = QMIN( to, from + availLeft - 1 );
01029 else
01030
01031 from = QMAX( from, to - availRight + 1 );
01032
01033 #ifdef DEBUG_MARGINS
01034 kdDebugBody(32002) << " getMargins from=" << from << " to=" << to << endl;
01035 #endif
01036
01037 if ( to - from < reqMinWidth + paragLeftMargin )
01038 {
01039 #ifdef DEBUG_MARGINS
01040 kdDebugBody(32002) << " smaller than minimum=" << m_doc->ptToLayoutUnitPixX( 15 ) + paragLeftMargin << endl;
01041 #endif
01042 from = to;
01043 }
01044
01045 if ( breakEnd && from == to )
01046 {
01047 if ( !init )
01048 {
01049 init = true;
01050 *breakBegin = iTop.y();
01051 *breakEnd = iBottom.y();
01052 }
01053 else
01054 {
01055 *breakBegin = QMIN( *breakBegin, iTop.y() );
01056 *breakEnd = QMAX( *breakEnd, iBottom.y() );
01057 }
01058 #ifdef DEBUG_MARGINS
01059 kdDebugBody(32002) << " getMargins iBottom.y=" << iBottom.y()
01060 << " breakBegin=" << *breakBegin
01061 << " breakEnd=" << *breakEnd << endl;
01062 #endif
01063 }
01064 }
01065 }
01066
01067 }
01068 }
01069 }
01070 }
01071 if ( marginLeft )
01072 {
01073 #ifdef DEBUG_MARGINS
01074 kdDebugBody(32002) << " getMargins done. from=" << from << " to=" << to << endl;
01075 #endif
01076 if ( from == to ) {
01077 from = 0;
01078 to = *pageWidth;
01079 }
01080
01081 if ( marginLeft )
01082 *marginLeft += from;
01083 if ( marginRight )
01084 {
01085 #ifdef DEBUG_MARGINS
01086 kdDebug(32002) << " getMargins " << name()
01087 << " page width=" << *pageWidth
01088 << " to=" << to << endl;
01089 #endif
01090 *marginRight += *pageWidth - to;
01091 }
01092 }
01093 }
01094
01095 void KWTextFrameSet::adjustMargins( int yp, int h, int reqMinWidth, int& leftMargin, int& rightMargin, int& pageWidth, KoTextParag* parag )
01096 {
01097 #ifdef DEBUG_MARGINS
01098 kdDebugBody(32002) << "KWTextFrameSet::adjustMargins called for paragraph " << (parag?parag->paragId():-1) << endl;
01099 #endif
01100 int validHeight;
01101 getMargins( yp, h, reqMinWidth, &leftMargin, &rightMargin, &pageWidth, &validHeight, 0L, 0L, parag );
01102 #ifdef DEBUG_MARGINS
01103 kdDebugBody(32002) << "KWTextFrameSet::adjustMargins(yp=" << yp << " h=" << h << " reqMinWidth=" << reqMinWidth << " returning"
01104 << " leftMargin=" << leftMargin << " rightMargin=" << rightMargin
01105 << " valid from " << yp << " to " << yp+validHeight << endl;
01106 #endif
01107 }
01108
01109
01110 bool KWTextFrameSet::checkVerticalBreak( int & yp, int & hp, KoTextParag * parag, bool linesTogether, int breakBegin, int breakEnd )
01111 {
01112
01113
01114
01115
01116 if ( QMAX( yp, breakBegin ) <= QMIN( yp+hp, breakEnd ) )
01117 {
01118 if ( !parag || linesTogether )
01119 {
01120 #ifdef DEBUG_FORMATVERTICALLY
01121 kdDebug(32002) << "checkVerticalBreak ADJUSTING yp=" << yp << " hp=" << hp
01122 << " breakEnd+2 [new value for yp]=" << breakEnd+2 << endl;
01123 #endif
01124 yp = breakEnd + 1;
01125 return true;
01126 }
01127 else
01128 {
01129 QMap<int, KoTextParagLineStart*>& lineStarts = parag->lineStartList();
01130 #ifdef DEBUG_FORMATVERTICALLY
01131 kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
01132 << ". lineStarts has " << lineStarts.count()
01133 << " items" << endl;
01134 #endif
01135 int dy = 0;
01136 int line = 0;
01137 QMap<int, KoTextParagLineStart*>::Iterator it = lineStarts.begin();
01138 for ( ; it != lineStarts.end() ; ++it, ++line )
01139 {
01140 KoTextParagLineStart * ls = it.data();
01141 Q_ASSERT( ls );
01142 int y = parag->rect().y() + ls->y;
01143 #ifdef DEBUG_FORMATVERTICALLY
01144 kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
01145 << " line " << line << " ls->y=" << ls->y
01146 << " ls->h=" << ls->h << " y=" << y
01147 << " breakBegin=" << breakBegin
01148 << " breakEnd=" << breakEnd << endl;
01149 #endif
01150 if ( !dy )
01151 {
01152 if ( QMAX( y, breakBegin ) <= QMIN( y + ls->h, breakEnd ) )
01153 {
01154 if ( line == 0 )
01155 {
01156 #ifdef DEBUG_FORMATVERTICALLY
01157 kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
01158 << " BREAKING first line -> parag break" << endl;
01159 #endif
01160 yp = breakEnd + 1;
01161 return true;
01162 }
01163 dy = breakEnd + 1 - y;
01164 ls->y = breakEnd + 1 - parag->rect().y();
01165 #ifdef DEBUG_FORMATVERTICALLY
01166 kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
01167 << " BREAKING at line " << line << " dy=" << dy << " Setting ls->y to " << ls->y << ", y=" << breakEnd << endl;
01168 #endif
01169 }
01170 }
01171 else
01172 {
01173 ls->y += dy;
01174 #ifdef DEBUG_FORMATVERTICALLY
01175 if ( dy )
01176 kdDebug(32002) << " moving down to position ls->y=" << ls->y << endl;
01177 #endif
01178 }
01179 }
01180 parag->setMovedDown( true );
01181 parag->setHeight( hp + dy );
01182 #ifdef DEBUG_FORMATVERTICALLY
01183 kdDebug(32002) << "Paragraph height set to " << hp+dy << endl;
01184 #endif
01185 hp += dy;
01186 return true;
01187 }
01188 }
01189 return false;
01190 }
01191
01192 int KWTextFrameSet::formatVertically( KoTextParag * _parag, const QRect& paragRect )
01193 {
01194
01195 KWTextParag *parag = static_cast<KWTextParag *>( _parag );
01196 if ( !m_doc->layoutViewMode()->shouldFormatVertically() )
01197 {
01198 return 0;
01199 }
01200
01201 #ifdef DEBUG_FORMATVERTICALLY
01202 kdDebugBody(32002) << "KWTextFrameSet::formatVertically called for paragraph " << (parag?parag->paragId():-1) << endl;
01203 #endif
01204
01205 int yp = paragRect.y();
01206 int hp = paragRect.height();
01207 int oldHeight = hp;
01208 int oldY = yp;
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 bool linesTogether = parag ? parag->linesTogether() : true;
01220 bool hardFrameBreak = parag ? parag->hardFrameBreakBefore() : false;
01221 if ( !hardFrameBreak && parag && parag->prev() )
01222 hardFrameBreak = static_cast<KWTextParag *>(parag->prev())->hardFrameBreakAfter();
01223
01224 #ifdef DEBUG_FORMATVERTICALLY
01225 kdDebugBody(32002) << "KWTextFrameSet::formatVertically parag=" << parag
01226 << " linesTogether=" << linesTogether << " hardFrameBreak=" << hardFrameBreak
01227 << " yp=" << yp
01228 << " hp=" << hp << endl;
01229 #endif
01230
01231 int totalHeight = 0;
01232 QPtrListIterator<KWFrame> frameIt( frameIterator() );
01233 for ( ; frameIt.current(); ++frameIt )
01234 {
01235 int frameHeight = kWordDocument()->ptToLayoutUnitPixY( frameIt.current()->innerHeight() );
01236 int bottom = totalHeight + frameHeight;
01237
01238
01239 bool check = frameIt.atLast() && frameIt.current()->frameBehavior() == KWFrame::AutoCreateNewFrame;
01240 if ( !check )
01241 {
01242
01243
01244 QPtrListIterator<KWFrame> nextFrame( frameIt );
01245 while ( !check && !nextFrame.atLast() )
01246 {
01247 ++nextFrame;
01248 if ( !nextFrame.current()->isCopy() )
01249 check = true;
01250 }
01251 }
01252
01253 if ( check )
01254 {
01255 if ( hardFrameBreak && yp > totalHeight && yp < bottom && !parag->wasMovedDown() )
01256 {
01257
01258
01259
01260 yp = bottom ;
01261 #ifdef DEBUG_FORMATVERTICALLY
01262 kdDebug(32002) << "KWTextFrameSet::formatVertically -> HARD FRAME BREAK" << endl;
01263 kdDebug(32002) << "KWTextFrameSet::formatVertically yp now " << yp << endl;
01264 #endif
01265 break;
01266 }
01267
01268 #ifdef DEBUG_FORMATVERTICALLY
01269 kdDebug(32002) << " formatVertically: frameHeight=" << frameHeight << " bottom=" << bottom << endl;
01270 #endif
01271
01272 if ( hp < frameHeight || ( parag && parag->lineStartList().count() > 1 ) )
01273 {
01274
01275 (void) checkVerticalBreak( yp, hp, parag, linesTogether, bottom, bottom );
01276
01277 }
01278
01279 }
01280 if ( yp+hp < bottom )
01281 break;
01282 totalHeight = bottom;
01283 }
01284
01285 #ifdef DEBUG_FORMATVERTICALLY
01286 kdDebug(32002) << " formatVertically: now looking at RA_SKIP" << endl;
01287 #endif
01288
01289
01290
01291
01292 frameIt.toFirst();
01293 for ( ; frameIt.current(); ++frameIt )
01294 {
01295 Q_ASSERT( frameIt.current()->frameStack() );
01296 QValueList<KWFrame*> onTop = frameIt.current()->frameStack()->framesOnTop();
01297 for (QValueListIterator<KWFrame*> fIt = onTop.begin(); fIt != onTop.end(); ++fIt )
01298 {
01299 if ( (*fIt)->runAround() == KWFrame::RA_SKIP )
01300 {
01301 KoRect rectOnTop = frameIt.current()->intersect( (*fIt)->runAroundRect() );
01302 QPoint iTop, iBottom;
01303 if ( documentToInternal( rectOnTop.topLeft(), iTop ) &&
01304 iTop.y() <= yp + hp &&
01305 documentToInternal( rectOnTop.bottomLeft(), iBottom ) &&
01306 checkVerticalBreak( yp, hp, parag, linesTogether,
01307 iTop.y(), iBottom.y() ) )
01308 {
01309 kdDebug(32002) << "KWTextFrameSet::formatVertically breaking around RA_SKIP frame yp="<<yp<<" hp=" << hp << endl;
01310
01311
01312
01313 }
01314 }
01315 }
01316 }
01317
01318
01319
01320 int breakBegin = 0;
01321 int breakEnd = 0;
01322 int reqMinWidth = parag ? parag->string()->at( 0 ).width : 0;
01323 getMargins( yp, hp, reqMinWidth, 0L, 0L, 0L, 0L, &breakBegin, &breakEnd, parag );
01324 if ( breakEnd )
01325 {
01326 kdDebug(32002) << "KWTextFrameSet("<<name()<<")::formatVertically no-space case. breakBegin=" << breakBegin
01327 << " breakEnd=" << breakEnd << " hp=" << hp << endl;
01328 Q_ASSERT( breakBegin <= breakEnd );
01329 if ( checkVerticalBreak( yp, hp, parag, linesTogether, breakBegin, breakEnd ) )
01330 ;
01331 else
01332 kdWarning(32002) << "checkVerticalBreak didn't find it" << endl;
01333 }
01334
01335
01336
01337 if ( parag )
01338 {
01339 if ( hp != oldHeight )
01340 parag->setHeight( hp );
01341 if ( yp != oldY ) {
01342 QRect r = parag->rect();
01343 r.moveBy( 0, yp - oldY );
01344 parag->setRect( r );
01345 parag->setMovedDown( true );
01346 }
01347 }
01348 #ifdef DEBUG_FORMATVERTICALLY
01349 kdDebug() << "KWTextFrameSet::formatVertically returning " << ( yp + hp ) - ( oldY + oldHeight ) << endl;
01350 #endif
01351 return ( yp + hp ) - ( oldY + oldHeight );
01352 }
01353
01354
01355
01356 int KWTextFrameSet::adjustFlow( int y, int w, int h )
01357 {
01358 QRect r( 0, y, w, h );
01359 return formatVertically( 0L, r );
01360 }
01361
01362 void KWTextFrameSet::fixParagWidth( KWTextParag* parag )
01363 {
01364
01365 if ( parag && m_doc->viewFormattingChars() && parag->rect().width() < textDocument()->width() )
01366 {
01367 if ( parag->hardFrameBreakAfter() )
01368 {
01369 KoTextFormat * lastFormat = parag->at( parag->length() - 1 )->format();
01370 const QFontMetrics& refFontMetrics = lastFormat->refFontMetrics();
01371
01372 QString str = i18n( "--- Frame Break ---" );
01373 int width = refFontMetrics.width( str );
01374 parag->setWidth( QMIN( parag->rect().width() + width, textDocument()->width() ) );
01375 }
01376 else
01377 parag->fixParagWidth( true );
01378 }
01379 }
01380
01381 KWTextFrameSet::~KWTextFrameSet()
01382 {
01383 textDocument()->takeFlow();
01384
01385 m_doc = 0L;
01386 delete m_textobj;
01387 }
01388
01389
01390
01391 struct FrameStruct
01392 {
01393 KWFrame * frame;
01394 bool operator < ( const FrameStruct & t ) const {
01395 return compare(frame, t.frame) < 0;
01396 }
01397 bool operator <= ( const FrameStruct & t ) const {
01398 return compare(frame, t.frame) <= 0;
01399 }
01400 bool operator > ( const FrameStruct & t ) const {
01401 return compare(frame, t.frame) > 0;
01402 }
01403
01404
01405
01406
01407
01408
01409 int compare (const KWFrame *frameOne, const KWFrame *frameTwo) const {
01410
01411 int pageOne = frameOne->pageNumber();
01412 int pageTwo = frameTwo->pageNumber();
01413 if( (pageOne == -1) ^ (pageTwo == -1)) {
01414 if( pageOne == -1 )
01415 return 5;
01416 return -5;
01417 }
01418 if ( pageOne > pageTwo ) return 4;
01419 if ( pageOne < pageTwo ) return -4;
01420
01421 double centerX = frameOne->left() + (frameOne->width() /2);
01422
01423 if ( centerX > frameTwo->right()) return 3;
01424 if ( centerX < frameTwo->left()) return -3;
01425
01426
01427 double centerY = frameOne->top() + (frameOne->height() /2);
01428 if ( centerY > frameTwo->bottom() ) return 2;
01429 if ( centerY < frameTwo->top() ) return -2;
01430
01431
01432 if (frameOne->top() > frameTwo->top()) return 1;
01433 return -1;
01434 }
01435 };
01436
01437 void KWTextFrameSet::updateFrames( int flags )
01438 {
01439
01440 if ( !isVisible() ) {
01441
01442 m_textobj->setVisible(false);
01443 return;
01444 }
01445 m_textobj->setVisible(true);
01446
01447
01448
01449
01450
01451
01452
01453 QValueList<FrameStruct> sortedFrames;
01454
01455 int width = 0;
01456 QPtrListIterator<KWFrame> frameIter( frameIterator() );
01457 for ( ; frameIter.current(); ++frameIter )
01458 {
01459
01460
01461 width = QMAX( width, m_doc->ptToLayoutUnitPixX( frameIter.current()->innerWidth()));
01462 if ( flags & SortFrames )
01463 {
01464 FrameStruct str;
01465 str.frame = frameIter.current();
01466 sortedFrames.append( str );
01467 }
01468 }
01469 if ( width != textDocument()->width() )
01470 {
01471
01472
01473 textDocument()->setWidth( width + 1 );
01474 }
01475
01476 if ( flags & SortFrames )
01477 {
01478 qHeapSort( sortedFrames );
01479
01480
01481 m_frames.setAutoDelete( false );
01482 m_frames.clear();
01483
01484 QValueList<FrameStruct>::Iterator it = sortedFrames.begin();
01485 for ( ; it != sortedFrames.end() ; ++it )
01486 m_frames.append( (*it).frame );
01487 }
01488
01489 double availHeight = 0;
01490 double internalYpt = 0;
01491 double lastRealFrameHeight = 0;
01492 bool firstFrame = true;
01493
01494 QPtrListIterator<KWFrame> frameIt( m_frames );
01495 for ( ; frameIt.current(); ++frameIt )
01496 {
01497 KWFrame* theFrame = frameIt.current();
01498
01499 if ( !theFrame->isCopy() )
01500 internalYpt += lastRealFrameHeight;
01501
01502 theFrame->setInternalY( internalYpt );
01503
01504
01505 if ( !theFrame->isCopy() || firstFrame )
01506 {
01507 lastRealFrameHeight = theFrame->innerHeight();
01508 availHeight += lastRealFrameHeight;
01509 }
01510 firstFrame = false;
01511 }
01512
01513 m_textobj->setAvailableHeight( m_doc->ptToLayoutUnitPixY( availHeight ) );
01514
01515
01516 m_frames.setAutoDelete( true );
01517
01518 KWFrameSet::updateFrames( flags );
01519 }
01520
01521 int KWTextFrameSet::availableHeight() const
01522 {
01523 return m_textobj->availableHeight();
01524 }
01525
01526 KWFrame * KWTextFrameSet::internalToDocument( const KoPoint &relPoint, KoPoint &dPoint ) const
01527 {
01528 #ifdef DEBUG_ITD
01529 kdDebug() << name() << " ITD called for relPoint=" << relPoint.x() << "," << relPoint.y() << endl;
01530 #endif
01531 if ( !m_doc->layoutViewMode()->hasFrames() ) {
01532 dPoint = relPoint;
01533 return m_frames.getFirst();
01534 }
01535
01536
01537 Q_ASSERT( !m_framesInPage.isEmpty() );
01538 int len = m_framesInPage.count();
01539 int n1 = 0;
01540 int n2 = len - 1;
01541 double internalY = 0.0;
01542 int mid = 0;
01543 bool found = FALSE;
01544 while ( n1 <= n2 ) {
01545 double res;
01546 mid = (n1 + n2)/2;
01547 #ifdef DEBUG_ITD
01548 kdDebug() << "ITD: begin. mid=" << mid << endl;
01549 #endif
01550 Q_ASSERT( m_framesInPage[mid] );
01551 if ( m_framesInPage[mid]->isEmpty() )
01552 res = -1;
01553 else
01554 {
01555 KWFrame * theFrame = m_framesInPage[mid]->first();
01556 internalY = theFrame->internalY();
01557 #ifdef DEBUG_ITD
01558 kdDebug() << "ITD: relPoint.y=" << relPoint.y() << " internalY=" << internalY << endl;
01559 #endif
01560 res = relPoint.y() - internalY;
01561 #ifdef DEBUG_ITD
01562 kdDebug() << "ITD: res=" << res << endl;
01563 #endif
01564
01565
01566 if ( res >= 0 )
01567 {
01568 double height = theFrame->innerHeight();
01569 #ifdef DEBUG_ITD
01570 kdDebug() << "ITD: height=" << height << " -> the bottom is at " << internalY+height << endl;
01571 #endif
01572 if ( relPoint.y() < internalY + height )
01573 {
01574 #ifdef DEBUG_ITD
01575 kdDebug() << "ITD: found a match " << mid << endl;
01576 #endif
01577 found = true;
01578 break;
01579 }
01580 }
01581 }
01582
01583
01584 if ( res < 0 )
01585 n2 = mid - 1;
01586 else
01587 n1 = mid + 1;
01588 #ifdef DEBUG_ITD
01589 kdDebug() << "ITD: End of loop. n1=" << n1 << " n2=" << n2 << endl;
01590 #endif
01591 }
01592 if ( !found )
01593 {
01594
01595
01596
01597 mid = n2;
01598 #ifdef DEBUG_ITD
01599 kdDebug() << "ITD: Setting mid to n2=" << mid << endl;
01600 #endif
01601 if ( mid < 0 )
01602 {
01603 #ifdef DEBUG_ITD
01604 kdDebug(32002) << "KWTextFrameSet::internalToDocument " << relPoint.x() << "," << relPoint.y()
01605 << " before any frame of " << (void*)this << endl;
01606 #endif
01607 dPoint = relPoint;
01608 return 0L;
01609 }
01610 }
01611
01612
01613 int result = mid;
01614 while ( mid - 1 >= 0 )
01615 {
01616 mid--;
01617 if ( !m_framesInPage[mid]->isEmpty() )
01618 {
01619 KWFrame * theFrame = m_framesInPage[mid]->first();
01620 #ifdef DEBUG_ITD
01621 kdDebug() << "KWTextFrameSet::internalToDocument going back to page " << mid << " - frame: " << theFrame->internalY() << endl;
01622 #endif
01623 if ( theFrame->internalY() == internalY )
01624 result = mid;
01625 else
01626 break;
01627 }
01628 }
01629
01630
01631 QPtrListIterator<KWFrame> frameIt( *m_framesInPage[result] );
01632 for ( ; frameIt.current(); ++frameIt )
01633 {
01634 KWFrame *theFrame = frameIt.current();
01635 KoRect relRect( 0, theFrame->internalY(), theFrame->innerWidth(), theFrame->innerHeight() );
01636 #ifdef DEBUG_ITD
01637 kdDebug() << "KWTextFrameSet::internalToDocument frame's relative rect:" << relRect << endl;
01638 #endif
01639 if ( relRect.contains( relPoint ) )
01640 {
01641 dPoint = internalToDocumentKnowingFrame( relPoint, theFrame );
01642 return theFrame;
01643 }
01644 }
01645 #ifdef DEBUG_ITD
01646 kdDebug(32002) << "KWTextFrameSet::internalToDocument " << relPoint.x() << "," << relPoint.y()
01647 << " not in any frame of " << (void*)this << " (looked on page " << result << ")" << endl;
01648 #endif
01649 dPoint = relPoint;
01650 return 0L;
01651 }
01652
01653
01654 KWFrame * KWTextFrameSet::internalToDocument( const QPoint &iPoint, KoPoint &dPoint ) const
01655 {
01656 KoPoint relPoint = m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) );
01657 return internalToDocument( relPoint, dPoint );
01658 }
01659
01660 #ifndef NDEBUG
01661 void KWTextFrameSet::printDebug()
01662 {
01663 KWFrameSet::printDebug();
01664 if ( !isDeleted() )
01665 {
01666 kdDebug() << "KoTextDocument width = " << textDocument()->width() << " height = " << textDocument()->height() << endl;
01667 }
01668
01669 QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
01670 for ( ; cit.current() ; ++cit )
01671 {
01672 KWAnchor *anc = dynamic_cast<KWAnchor *>( cit.current() );
01673 if (anc)
01674 kdDebug() << "Inline framesets: " << anc->frameSet()->name() << endl;
01675 }
01676 }
01677 #endif
01678
01679 QDomElement KWTextFrameSet::saveInternal( QDomElement &parentElem, bool saveFrames, bool saveAnchorsFramesets )
01680 {
01681 if ( m_frames.isEmpty() )
01682 return QDomElement();
01683
01684 QDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
01685 parentElem.appendChild( framesetElem );
01686
01687 if ( m_groupmanager ) {
01688 framesetElem.setAttribute( "grpMgr", m_groupmanager->name() );
01689
01690 KWTableFrameSet::Cell *cell = (KWTableFrameSet::Cell *)this;
01691 framesetElem.setAttribute( "row", cell->firstRow() );
01692 framesetElem.setAttribute( "col", cell->firstColumn() );
01693 framesetElem.setAttribute( "rows", cell->rowSpan() );
01694 framesetElem.setAttribute( "cols", cell->columnSpan() );
01695 }
01696 if ( protectContent() )
01697 framesetElem.setAttribute( "protectContent", static_cast<int>(protectContent()));
01698
01699 KWFrameSet::saveCommon( framesetElem, saveFrames );
01700
01701
01702 KWTextParag *start = static_cast<KWTextParag *>( textDocument()->firstParag() );
01703 while ( start ) {
01704 start->save( framesetElem, saveAnchorsFramesets );
01705 start = static_cast<KWTextParag *>( start->next() );
01706 }
01707
01708 return framesetElem;
01709 }
01710
01711 KWFrame* KWTextFrameSet::loadOasisTextFrame( const QDomElement& frameTag, const QDomElement &tag, KoOasisContext& context )
01712 {
01713 context.styleStack().save();
01714 context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" );
01715
01716 KWFrame* frame = loadOasisFrame( frameTag, context );
01717
01718
01719 bool hasMinHeight = tag.hasAttributeNS( KoXmlNS::fo, "min-height" );
01720 if ( hasMinHeight ) {
01721 double height = KoUnit::parseValue( tag.attributeNS( KoXmlNS::fo, "min-height", QString::null ) );
01722 frame->setMinimumFrameHeight( height );
01723 if ( height > frame->height() || !tag.hasAttributeNS( KoXmlNS::fo, "height" ) )
01724 frame->setHeight( height );
01725 }
01726
01727
01728 const QString overflowBehavior = context.styleStack().attributeNS( KoXmlNS::style, "overflow-behavior" );
01729 if ( frame->minimumFrameHeight() > 0 )
01730 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
01731 else if ( overflowBehavior == "auto-create-new-frame" )
01732 {
01733 frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
01734 frame->setNewFrameBehavior( KWFrame::Reconnect );
01735 }
01736 else if ( overflowBehavior.isEmpty() || overflowBehavior == "clip" )
01737 frame->setFrameBehavior( KWFrame::Ignore );
01738 else
01739 kdWarning(32001) << "Unknown value for style:overflow-behavior: " << overflowBehavior << endl;
01740
01741 context.styleStack().restore();
01742
01743 return frame;
01744 }
01745
01746 void KWTextFrameSet::loadOasisContent( const QDomElement &bodyElem, KoOasisContext& context )
01747 {
01748 return m_textobj->loadOasisContent( bodyElem, context, m_doc->styleCollection() );
01749 }
01750
01751 KWFrame* KWTextFrameSet::loadOasis( const QDomElement& frameTag, const QDomElement &tag, KoOasisContext& context )
01752 {
01753 KWFrame* frame = loadOasisTextFrame( frameTag, tag, context );
01754 loadOasisContent( tag, context );
01755 return frame;
01756 }
01757
01758 static void finishTOC( KoXmlWriter& writer )
01759 {
01760 writer.endElement();
01761 writer.endElement();
01762 }
01763
01764 void KWTextFrameSet::saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const
01765 {
01766
01767
01768 QMap<const KoTextParag*, KoTextBookmarkList> bookmarksPerParagraph;
01769 if ( m_doc->bookmarkList() )
01770 bookmarksPerParagraph = m_doc->bookmarkList()->bookmarksPerParagraph();
01771
01772
01773
01774
01775 KoTextParag* parag = textDocument()->firstParag();
01776 bool inTOC = false;
01777 while ( parag ) {
01778 bool tocParag = parag->partOfTableOfContents();
01779 if ( tocParag != inTOC ) {
01780 if ( tocParag ) {
01781 writer.startElement( "text:table-of-content" );
01782 writer.addAttribute( "text:name", "Table Of Contents" );
01783 writer.addAttribute( "text:protected", "false" );
01784 writer.startElement( "text:table-of-content-source" );
01785
01786
01787
01788 writer.endElement();
01789 writer.startElement( "text:index-body" );
01790 writer.startElement( "text:index-title" );
01791 writer.addAttribute( "text:name", "Table Of Contents Heading" );
01792 } else {
01793 finishTOC( writer );
01794 }
01795 }
01796
01797
01798
01799 KoSavingContext::BookmarkPositions bookmarkStarts, bookmarkEnds;
01800 QMap<const KoTextParag*, KoTextBookmarkList>::const_iterator bkit = bookmarksPerParagraph.find( parag );
01801 if ( bkit != bookmarksPerParagraph.end() ) {
01802
01803 const KoTextBookmarkList& bookmarks = *bkit;
01804 for ( KoTextBookmarkList::const_iterator it = bookmarks.begin(); it != bookmarks.end(); ++it )
01805 {
01806 const KoTextBookmark& bk = *it;
01807 if ( bk.startParag() == parag )
01808 bookmarkStarts.append( KoSavingContext::BookmarkPosition(
01809 bk.bookmarkName(), bk.bookmarkStartIndex(),
01810 bk.isSimple() ) );
01811 if ( bk.endParag() == parag && !bk.isSimple() )
01812 bookmarkEnds.append( KoSavingContext::BookmarkPosition( bk.bookmarkName(),
01813 bk.bookmarkEndIndex(), false ) );
01814 }
01815 qHeapSort( bookmarkStarts );
01816 qHeapSort( bookmarkEnds );
01817 }
01818
01819 context.setBookmarkPositions( bookmarkStarts, bookmarkEnds );
01820
01821
01822 parag->saveOasis( writer, context, 0, parag->lastCharPos() );
01823
01824 if ( tocParag && !inTOC )
01825 writer.endElement();
01826 inTOC = tocParag;
01827
01828 parag = parag->next();
01829 }
01830 if ( inTOC )
01831 finishTOC( writer );
01832 }
01833
01834 void KWTextFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const
01835 {
01836
01837 KWFrame* frame = m_frames.getFirst();
01838 QString lastFrameName = name();
01839 frame->startOasisFrame( writer, context.mainStyles(), lastFrameName );
01840
01841 QString nextFrameName = name() + "-";
01842
01843 writer.startElement( "draw:text-box" );
01844 if ( frame->frameBehavior() == KWFrame::AutoExtendFrame )
01845 writer.addAttributePt( "fo:min-height", frame->minimumFrameHeight() );
01846 if ( m_frames.count() > 1 && saveFrames )
01847 writer.addAttribute( "draw:chain-next-name", nextFrameName + "2" );
01848 saveOasisContent( writer, context );
01849 writer.endElement();
01850 writer.endElement();
01851
01852
01853 if ( saveFrames )
01854 {
01855 int frameNumber = 2;
01856 QPtrListIterator<KWFrame> frameIter( frameIterator() );
01857 ++frameIter;
01858 for ( ; frameIter.current(); ++frameIter, ++frameNumber )
01859 {
01860 const QString frameName = nextFrameName + QString::number( frameNumber );
01861 frameIter.current()->startOasisFrame( writer, context.mainStyles(), frameName, lastFrameName );
01862 lastFrameName = frameName;
01863 writer.startElement( "draw:text-box" );
01864 if ( frame->frameBehavior() == KWFrame::AutoExtendFrame )
01865 writer.addAttributePt( "fo:min-height", frame->minimumFrameHeight() );
01866 if ( frameNumber < (int)m_frames.count() )
01867 writer.addAttribute( "draw:chain-next-name", nextFrameName + QString::number( frameNumber+1 ) );
01868
01869 writer.endElement();
01870 writer.endElement();
01871 }
01872 }
01873 }
01874
01875 void KWTextFrameSet::load( QDomElement &attributes, bool loadFrames )
01876 {
01877 KWFrameSet::load( attributes, loadFrames );
01878 if ( attributes.hasAttribute( "protectContent"))
01879 setProtectContent((bool)attributes.attribute( "protectContent" ).toInt());
01880
01881 textDocument()->clear(false);
01882 m_textobj->setLastFormattedParag( 0L );
01883 KWTextParag *lastParagraph = 0L;
01884
01885
01886 QDomElement paragraph = attributes.firstChild().toElement();
01887 for ( ; !paragraph.isNull() ; paragraph = paragraph.nextSibling().toElement() )
01888 {
01889 if ( paragraph.tagName() == "PARAGRAPH" )
01890 {
01891 KWTextParag *parag = new KWTextParag( textDocument(), lastParagraph );
01892 parag->load( paragraph );
01893 if ( !lastParagraph )
01894 textDocument()->setFirstParag( parag );
01895 lastParagraph = parag;
01896 m_doc->progressItemLoaded();
01897 }
01898 }
01899
01900 if ( !lastParagraph )
01901 {
01902
01903 textDocument()->clear( true );
01904 static_cast<KWTextParag *>( textDocument()->firstParag() )->setStyle( m_doc->styleCollection()->findStyle( "Standard" ) );
01905 }
01906 else
01907 textDocument()->setLastParag( lastParagraph );
01908
01909 m_textobj->setLastFormattedParag( textDocument()->firstParag() );
01910
01911 }
01912
01913 void KWTextFrameSet::finalize()
01914 {
01915 KWFrameSet::finalize();
01916 m_textobj->formatMore( 0 );
01917
01918
01919
01920
01921 }
01922
01923 void KWTextFrameSet::setVisible(bool visible)
01924 {
01925 setInlineFramesVisible( visible );
01926 KWFrameSet::setVisible( visible );
01927 }
01928
01929 void KWTextFrameSet::setInlineFramesVisible(bool visible)
01930 {
01931 QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
01932 for ( ; cit.current() ; ++cit )
01933 {
01934 KWAnchor *anc = dynamic_cast<KWAnchor *>( cit.current() );
01935 if (anc)
01936 anc->frameSet()->setVisible( visible );
01937 }
01938 }
01939
01940 void KWTextFrameSet::addTextFrameSets( QPtrList<KWTextFrameSet> & lst, bool onlyReadWrite )
01941 {
01942 if (!textObject()->protectContent() || !onlyReadWrite)
01943 lst.append(this);
01944 }
01945
01946 void KWTextFrameSet::slotNewCommand( KCommand *cmd )
01947 {
01948 m_doc->addCommand( cmd );
01949 }
01950
01951 void KWTextFrameSet::ensureFormatted( KoTextParag * parag, bool emitAfterFormatting )
01952 {
01953 if (!isVisible())
01954 return;
01955 m_textobj->ensureFormatted( parag, emitAfterFormatting );
01956 }
01957
01958 bool KWTextFrameSet::slotAfterFormattingNeedMoreSpace( int bottom, KoTextParag *lastFormatted )
01959 {
01960 int availHeight = availableHeight();
01961 #ifdef DEBUG_FORMAT_MORE
01962 if(lastFormatted)
01963 kdDebug(32002) << "slotAfterFormatting We need more space in " << name()
01964 << " bottom=" << bottom + lastFormatted->rect().height()
01965 << " availHeight=" << availHeight << endl;
01966 else
01967 kdDebug(32002) << "slotAfterFormatting We need more space in " << name()
01968 << " bottom2=" << bottom << " availHeight=" << availHeight << endl;
01969 #endif
01970 if ( m_frames.isEmpty() )
01971 {
01972 kdWarning(32002) << "slotAfterFormatting no more space, but no frame !" << endl;
01973 return true;
01974 }
01975
01976 KWFrame::FrameBehavior frmBehavior = m_frames.last()->frameBehavior();
01977 if ( frmBehavior == KWFrame::AutoExtendFrame && isProtectSize())
01978 frmBehavior = KWFrame::Ignore;
01979 if ( frmBehavior == KWFrame::AutoCreateNewFrame )
01980 {
01981 KWFrame *theFrame = settingsFrame( m_frames.last() );
01982 double minHeight = s_minFrameHeight + theFrame->paddingTop() + theFrame->paddingBottom() + 5;
01983 if ( availHeight < minHeight )
01984 frmBehavior = KWFrame::Ignore;
01985 }
01986
01987 int difference = ( bottom + 2 ) - availHeight;
01988 #ifdef DEBUG_FORMAT_MORE
01989 kdDebug(32002) << "AutoExtendFrame bottom=" << bottom << " availHeight=" << availHeight
01990 << " => difference = " << difference << endl;
01991 #endif
01992 if( lastFormatted && bottom + lastFormatted->rect().height() > availHeight ) {
01993 #ifdef DEBUG_FORMAT_MORE
01994 kdDebug(32002) << " next will be off -> adding " << lastFormatted->rect().height() << endl;
01995 #endif
01996 difference += lastFormatted->rect().height();
01997 }
01998
01999 switch ( frmBehavior ) {
02000 case KWFrame::AutoExtendFrame:
02001 {
02002 if(difference > 0) {
02003
02004 KWFrame *theFrame = settingsFrame( m_frames.last() );
02005 double wantedPosition = 0;
02006
02007
02008 if ( theFrame->frameSet()->isAFooter() || theFrame->frameSet()->isFootNote() )
02009 {
02010
02011
02012 double maxFooterSize = footerHeaderSizeMax( theFrame );
02013 double diffPt = m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
02014 wantedPosition = theFrame->top() - diffPt;
02015 #ifdef DEBUG_FORMAT_MORE
02016 kdDebug() << " diffPt=" << diffPt << " -> wantedPosition=" << wantedPosition << endl;
02017 #endif
02018 if ( wantedPosition < 0 )
02019 {
02020 m_textobj->setLastFormattedParag( 0 );
02021 return true;
02022 }
02023
02024 if ( wantedPosition != theFrame->top() &&
02025 ( theFrame->frameSet()->isFootEndNote() ||
02026 theFrame->bottom() - maxFooterSize <= wantedPosition ) )
02027 {
02028 theFrame->setTop( wantedPosition );
02029 #ifdef DEBUG_FORMAT_MORE
02030 kdDebug() << " ok: frame=" << *theFrame << " bottom=" << theFrame->bottom() << " height=" << theFrame->height() << endl;
02031 #endif
02032 frameResized( theFrame, true );
02033
02034 return false;
02035 }
02036 kdDebug() << "slotAfterFormatting didn't manage to get more space for footer/footnote, aborting" << endl;
02037 return true;
02038 }
02039
02040
02041 wantedPosition = m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) ) + theFrame->bottom();
02042 KWPage *page = m_doc->pageManager()->page( theFrame );
02043 double pageBottom;
02044 if(page)
02045 pageBottom = page->offsetInDocument() + page->height() - page->bottomMargin();
02046 else
02047 pageBottom = theFrame->bottom();
02048 double newPosition = QMIN( wantedPosition, pageBottom );
02049 kdDebug(32002) << "wantedPosition=" << wantedPosition << " pageBottom=" << pageBottom
02050 << " -> newPosition=" << newPosition << endl;
02051
02052 if ( theFrame->frameSet()->isAHeader() )
02053 {
02054 double maxHeaderSize=footerHeaderSizeMax( theFrame );
02055 newPosition = QMIN( newPosition, maxHeaderSize + theFrame->top() );
02056 }
02057
02058 newPosition = QMAX( newPosition, theFrame->top() );
02059 kdDebug(32002) << "newPosition=" << newPosition << endl;
02060
02061 bool resized = false;
02062 if(theFrame->frameSet()->groupmanager()) {
02063 KWTableFrameSet *table = theFrame->frameSet()->groupmanager();
02064 #ifdef DEBUG_FORMAT_MORE
02065 kdDebug(32002) << "is table cell; just setting new minFrameHeight, to " << newPosition - theFrame->top() << endl;
02066 #endif
02067 double newMinFrameHeight = newPosition - theFrame->top();
02068 resized = QABS( newMinFrameHeight - theFrame->minimumFrameHeight() ) > 1E-10;
02069 if ( resized ) {
02070 theFrame->setMinimumFrameHeight( newMinFrameHeight );
02071 KWTableFrameSet::Cell *cell = (KWTableFrameSet::Cell *)theFrame->frameSet();
02072 table->recalcCols(cell->firstColumn(), cell->firstRow());
02073 table->recalcRows(cell->firstColumn(), cell->firstRow());
02074
02075 if (! table->anchorFrameset() )
02076 ;
02077 else if ( table->anchorFrameset() && table->anchorFrameset()->isAHeader() )
02078 {
02079 theFrame = table->anchorFrameset()->frameIterator().getLast();
02080 theFrame->setBottom(newPosition);
02081 frameResized( theFrame, false );
02082 }
02083 else if ( table->anchorFrameset()->isAFooter() || table->anchorFrameset()->isFootNote() )
02084 {
02085 theFrame = table->anchorFrameset()->frameIterator().getLast();
02086
02087
02088 double maxFooterSize = footerHeaderSizeMax( theFrame );
02089 double diffPt = m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
02090 wantedPosition = theFrame->top() - diffPt;
02091 if ( wantedPosition < 0 )
02092 {
02093 m_textobj->setLastFormattedParag( 0 );
02094 return true;
02095 }
02096
02097 if ( wantedPosition != theFrame->top() &&
02098 ( theFrame->frameSet()->isFootEndNote() ||
02099 theFrame->bottom() - maxFooterSize <= wantedPosition ) )
02100 {
02101 theFrame->setTop( wantedPosition );
02102 frameResized( theFrame, true );
02103
02104 }
02105 }
02106
02107 m_doc->delayedRepaintAllViews();
02108 }
02109 return true;
02110 } else {
02111 resized = QABS( theFrame->bottom() - newPosition ) > 1E-10;
02112 #ifdef DEBUG_FORMAT_MORE
02113 kdDebug() << " bottom=" << theFrame->bottom() << " new position:" << newPosition << " wantedPosition=" << wantedPosition << " resized=" << resized << endl;
02114 #endif
02115
02116 if ( resized )
02117 {
02118 #ifdef DEBUG_FORMAT_MORE
02119 kdDebug(32002) << "slotAfterFormatting changing bottom from " << theFrame->bottom() << " to " << newPosition << endl;
02120 #endif
02121 theFrame->setBottom(newPosition);
02122 frameResized( theFrame, false );
02123 }
02124 }
02125
02126 if(newPosition < wantedPosition &&
02127 (theFrame->newFrameBehavior() == KWFrame::Reconnect
02128 && !theFrame->frameSet()->isEndNote()))
02129 {
02130 wantedPosition = wantedPosition - newPosition + theFrame->top() + page->height();
02131 #ifdef DEBUG_FORMAT_MORE
02132 kdDebug(32002) << "Not enough room in this page -> creating new one, with a reconnect frame" << endl;
02133 kdDebug(32002) << "new wantedPosition=" << wantedPosition << endl;
02134 #endif
02135
02136
02137 }
02138 else if(newPosition < wantedPosition && (theFrame->newFrameBehavior() == KWFrame::NoFollowup)) {
02139 if ( theFrame->frameSet()->isEndNote() )
02140 m_doc->delayedRecalcFrames( theFrame->pageNumber() );
02141
02142 m_textobj->setLastFormattedParag( 0 );
02143 return true;
02144 } else {
02145 if ( resized )
02146 return false;
02147 return true;
02148 }
02149 }
02150 }
02151
02152 case KWFrame::AutoCreateNewFrame:
02153 {
02154
02155 return createNewPageAndNewFrame( lastFormatted, difference );
02156 }
02157
02158 case KWFrame::Ignore:
02159 #ifdef DEBUG_FORMAT_MORE
02160 kdDebug(32002) << "slotAfterFormatting frame behaviour is Ignore" << endl;
02161 #endif
02162 m_textobj->setLastFormattedParag( 0 );
02163 return true;
02164 }
02165 kdWarning() << "NEVERREACHED" << endl;
02166
02167 return true;
02168 }
02169
02170 void KWTextFrameSet::slotAfterFormattingTooMuchSpace( int bottom )
02171 {
02172 int availHeight = availableHeight();
02173
02174
02175 int difference = availHeight - ( bottom + 2 );
02176 #ifdef DEBUG_FORMAT_MORE
02177 kdDebug(32002) << "slotAfterFormatting less text than space (AutoExtendFrame). Frameset " << name() << " availHeight=" << availHeight << " bottom=" << bottom << " ->difference=" << difference << endl;
02178 #endif
02179
02180 KWFrame *theFrame = settingsFrame( m_frames.last() );
02181 #ifdef DEBUG_FORMAT_MORE
02182 kdDebug(32002) << " frame is " << *theFrame << " footer:" << ( theFrame->frameSet()->isAFooter() || theFrame->frameSet()->isFootEndNote() ) << endl;
02183 #endif
02184 if ( theFrame->frameSet()->isAFooter() || theFrame->frameSet()->isFootEndNote() )
02185 {
02186 double wantedPosition = theFrame->top() + m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
02187 Q_ASSERT( wantedPosition < theFrame->bottom() );
02188 if ( wantedPosition != theFrame->top() )
02189 {
02190 #ifdef DEBUG_FORMAT_MORE
02191 kdDebug() << " top= " << theFrame->top() << " setTop " << wantedPosition << endl;
02192 #endif
02193 theFrame->setTop( wantedPosition );
02194 #ifdef DEBUG_FORMAT_MORE
02195 kdDebug() << " -> the frame is now " << *theFrame << endl;
02196 #endif
02197 frameResized( theFrame, true );
02198 }
02199 }
02200 else
02201 {
02202 double wantedPosition = theFrame->bottom() - m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
02203 #ifdef DEBUG_FORMAT_MORE
02204 kdDebug() << "slotAfterFormatting wantedPosition=" << wantedPosition << " top+minheight=" << theFrame->top() + s_minFrameHeight << endl;
02205 #endif
02206 wantedPosition = QMAX( wantedPosition, theFrame->top() + s_minFrameHeight );
02207 if( theFrame->frameSet()->groupmanager() ) {
02208 if ( wantedPosition != theFrame->bottom()) {
02209 KWTableFrameSet *table = theFrame->frameSet()->groupmanager();
02210
02211
02212
02213
02214 if(wantedPosition != theFrame->top() + theFrame->minimumFrameHeight()) {
02215 theFrame->setMinimumFrameHeight(wantedPosition - theFrame->top());
02216 #ifdef DEBUG_FORMAT_MORE
02217 kdDebug(32002) << "is table cell; only setting new minFrameHeight to " << theFrame->minimumFrameHeight() << ", recalcrows will do the rest" << endl;
02218 #endif
02219 KWTableFrameSet::Cell *cell = (KWTableFrameSet::Cell *)theFrame->frameSet();
02220 table->recalcCols(cell->firstColumn(), cell->firstRow());
02221 table->recalcRows(cell->firstColumn(), cell->firstRow());
02222
02223 if (! table->anchorFrameset() )
02224 ;
02225 else if ( table->anchorFrameset() && table->anchorFrameset()->isAHeader() )
02226 {
02227 theFrame = table->anchorFrameset()->frameIterator().getLast();
02228 theFrame->setBottom(wantedPosition);
02229 frameResized( theFrame, false );
02230 }
02231 else if ( table->anchorFrameset()->isAFooter() || table->anchorFrameset()->isFootEndNote() )
02232 {
02233 theFrame = table->anchorFrameset()->frameIterator().getLast();
02234 double wantedPosition = theFrame->top() + m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
02235 Q_ASSERT( wantedPosition < theFrame->bottom() );
02236 if ( wantedPosition != theFrame->top() )
02237 {
02238 theFrame->setTop( wantedPosition );
02239 frameResized( theFrame, true );
02240 }
02241 }
02242 m_doc->delayedRepaintAllViews();
02243 }
02244 }
02245 } else {
02246
02247 wantedPosition = QMAX( wantedPosition, theFrame->top() + theFrame->minimumFrameHeight() );
02248 if ( wantedPosition != theFrame->bottom()) {
02249 #ifdef DEBUG_FORMAT_MORE
02250 kdDebug() << " the frame was " << *theFrame << endl;
02251 kdDebug() << "setBottom " << wantedPosition << endl;
02252 #endif
02253 theFrame->setBottom( wantedPosition );
02254 #ifdef DEBUG_FORMAT_MORE
02255 kdDebug() << " -> the frame is now " << *theFrame << endl;
02256 #endif
02257 frameResized( theFrame, true );
02258 }
02259 }
02260 }
02261 }
02262
02263 void KWTextFrameSet::slotAfterFormatting( int bottom, KoTextParag *lastFormatted, bool* abort )
02264 {
02265 int availHeight = availableHeight();
02266 if ( ( bottom > availHeight ) ||
02267 ( lastFormatted && bottom + lastFormatted->rect().height() > availHeight ) )
02268 {
02269 *abort = slotAfterFormattingNeedMoreSpace( bottom, lastFormatted );
02270 }
02271
02272
02273 else if ( m_frames.count() > 1 && !lastFormatted && frameSetInfo() == KWFrameSet::FI_BODY
02274 && bottom < availHeight - m_doc->ptToLayoutUnitPixY( m_frames.last()->innerHeight() ) )
02275 {
02276 #ifdef DEBUG_FORMAT_MORE
02277 kdDebug(32002) << "slotAfterFormatting too much space (bottom=" << bottom << ", availHeight=" << availHeight << ") , trying to remove last frame" << endl;
02278 #endif
02279
02280
02281 if(m_frames.last()->frameBehavior() == KWFrame::AutoExtendFrame
02282 && m_frames.last()->minimumFrameHeight() < 1E-10 ) {
02283 deleteFrame(m_frames.last(), true);
02284 m_doc->frameChanged( 0L );
02285 }
02286 if ( m_doc->processingType() == KWDocument::WP ) {
02287 bool removed = m_doc->tryRemovingPages();
02288
02289 if ( removed )
02290 m_doc->afterRemovePages();
02291 }
02292 }
02293
02294
02295 else if ( !lastFormatted && bottom + 2 < availHeight &&
02296 (m_frames.last()->frameBehavior() == KWFrame::AutoExtendFrame&& !isProtectSize()) )
02297 {
02298 slotAfterFormattingTooMuchSpace( bottom );
02299 *abort = false;
02300 }
02301
02302 if ( m_doc->processingType() == KWDocument::WP
02303 && this == m_doc->frameSet( 0 ) )
02304 {
02305 if ( m_lastTextDocHeight != textDocument()->height() )
02306 {
02307 m_lastTextDocHeight = textDocument()->height();
02308 emit mainTextHeightChanged();
02309 }
02310 }
02311 }
02312
02313
02314
02315
02316 bool KWTextFrameSet::createNewPageAndNewFrame( KoTextParag* lastFormatted, int )
02317 {
02318 KWFrame* lastFrame = m_frames.last();
02319
02320 if ( !lastFrame || lastFrame->newFrameBehavior() != KWFrame::Reconnect ) {
02321 kdDebug(32002) << name() << " : frame is AutoCreateNewFrame but not Reconnect !?!? Aborting." << endl;
02322 m_textobj->setLastFormattedParag( 0 );
02323 return true;
02324 }
02325
02326
02327 kdDebug(32002) << "createNewPageAndNewFrame creating new frame in frameset " << name() << endl;
02328
02329 uint oldCount = m_frames.count();
02330 int lastPageNumber = m_doc->pageManager()->lastPageNumber();
02331 kdDebug(32002) << " last frame=" << lastFrame << " pagenum=" << lastFrame->pageNumber() << " lastPageNumber=" << lastPageNumber << " m_frames count=" << oldCount << endl;
02332
02333
02334 if ( lastFrame->pageNumber() == lastPageNumber )
02335 {
02336
02337
02338
02339 int heightWeWillGet = 0;
02340 if(isMainFrameset())
02341 heightWeWillGet += m_doc->ptToLayoutUnitPixY( m_frames.last()->height() );
02342 else {
02343 QPtrList<KWFrame> framesToCopy = m_doc->framesToCopyOnNewPage( lastPageNumber );
02344 QPtrListIterator<KWFrame> frameIt( framesToCopy );
02345 for ( ; frameIt.current(); ++frameIt )
02346 if (frameIt.current()->frameSet() == this &&
02347 frameIt.current()->newFrameBehavior()==KWFrame::Reconnect)
02348 heightWeWillGet += m_doc->ptToLayoutUnitPixY( frameIt.current()->height() );
02349 }
02350
02351
02352
02353
02354
02355
02356 KoTextParag* parag = lastFormatted ? lastFormatted : textDocument()->lastParag();
02357
02358
02359
02360 int paragHeight = parag->rect().height();
02361 kdDebug(32002) << "height we will get in the new page:" << heightWeWillGet << " parag " << parag << " height:" << paragHeight << endl;
02362 if ( heightWeWillGet < paragHeight && !m_groupmanager )
02363 {
02364 kdDebug(32002) << "not enough height on the new page, not worth it" << endl;
02365 m_textobj->setLastFormattedParag( 0 );
02366 return true;
02367 }
02368
02369 KWPage *page = m_doc->appendPage();
02370 if ( !m_doc->isLoading() )
02371 m_doc->afterInsertPage( page->pageNumber() );
02372 kdDebug(32002) << "now frames count=" << m_frames.count() << endl;
02373 }
02374
02375
02376
02377 if ( m_frames.count() == oldCount )
02378 {
02379 Q_ASSERT( !isMainFrameset() );
02380
02381 kdDebug(32002) << "createNewPageAndNewFrame creating frame on page " << lastFrame->pageNumber()+1 << endl;
02382 KWFrame *frm = lastFrame->getCopy();
02383 frm->moveBy( 0, m_doc->pageManager()->page(frm)->height() );
02384 addFrame( frm );
02385 }
02386
02387 updateFrames();
02388 Q_ASSERT(frame(0) && frame(0)->frameStack());
02389 frame(0)->frameStack()->update();
02392
02393
02394
02395 if ( lastFormatted )
02396 lastFormatted = lastFormatted->prev();
02397 else
02398 lastFormatted = textDocument()->lastParag();
02399
02400 if ( lastFormatted )
02401 {
02402 m_textobj->setLastFormattedParag( lastFormatted );
02403 lastFormatted->invalidate( 0 );
02404
02405
02406
02407 return false;
02408 }
02409 m_doc->delayedRepaintAllViews();
02410 return false;
02411 }
02412
02413 double KWTextFrameSet::footNoteSize( KWFrame *theFrame )
02414 {
02415 double tmp =0.0;
02416 int page = theFrame->pageNumber();
02417 QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
02418 for ( ; fit.current() ; ++fit )
02419 {
02420 if((fit.current()->isFootNote() || fit.current()->isEndNote()) &&
02421 fit.current()->isVisible())
02422 {
02423 KWFrame * frm=fit.current()->frame( 0 );
02424 if(frm->pageNumber()==page )
02425 tmp += frm->innerHeight()+m_doc->ptFootnoteBodySpacing();
02426 }
02427 }
02428 return tmp;
02429 }
02430
02431
02432 double KWTextFrameSet::footerHeaderSizeMax( KWFrame *theFrame )
02433 {
02434 KWPage *page = m_doc->pageManager()->page(theFrame);
02435 Q_ASSERT( page );
02436 if ( !page )
02437 return 0;
02438 double tmp = page->height() - page->bottomMargin() - page->topMargin() - 40;
02439 bool header=theFrame->frameSet()->isAHeader();
02440 if( header ? m_doc->isHeaderVisible():m_doc->isFooterVisible() )
02441 {
02442 QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
02443 for ( ; fit.current() ; ++fit )
02444 {
02445 bool state = header ? fit.current()->isAFooter():fit.current()->isAHeader();
02446 if(fit.current()->isVisible() && state)
02447 {
02448 KWFrame * frm=fit.current()->frame( 0 );
02449 if(frm->pageNumber()==page->pageNumber() )
02450 {
02451 return (tmp-frm->innerHeight()-footNoteSize( theFrame ));
02452 }
02453 }
02454 }
02455 }
02456 if (theFrame->frameSet()->isHeaderOrFooter())
02457 return (tmp-footNoteSize( theFrame ));
02458
02459 return tmp;
02460 }
02461
02462 void KWTextFrameSet::frameResized( KWFrame *theFrame, bool invalidateLayout )
02463 {
02464 kdDebug(32002) << "KWTextFrameSet::frameResized " << theFrame << " " << *theFrame << " invalidateLayout=" << invalidateLayout << endl;
02465 if ( theFrame->height() < 0 )
02466 return;
02467
02468 KWFrameSet * fs = theFrame->frameSet();
02469 Q_ASSERT( fs == this );
02470 fs->updateFrames();
02471 Q_ASSERT(frame(0) && frame(0)->frameStack());
02472 frame(0)->frameStack()->update();
02473
02474 theFrame->updateRulerHandles();
02475
02476
02477
02478
02479
02480 if ( fs->isMainFrameset() || fs->isEndNote() )
02481 m_doc->delayedRecalcFrames( theFrame->pageNumber() );
02482
02483 else if ( fs->frameSetInfo() != KWFrameSet::FI_BODY )
02484 m_doc->recalcFrames( theFrame->pageNumber(), -1 );
02485
02486
02487
02488
02489 if ( invalidateLayout )
02490 m_doc->invalidate(this);
02491
02492
02493 m_doc->delayedRepaintAllViews();
02494 }
02495
02496 bool KWTextFrameSet::isFrameEmpty( KWFrame * theFrame )
02497 {
02498 KoTextParag * lastParag = textDocument()->lastParag();
02499
02500
02501
02502
02503 if ( !lastParag->isValid() )
02504 return false;
02505 int bottom = lastParag->rect().top() + lastParag->rect().height();
02506
02507 if ( theFrame->frameSet() == this )
02508 {
02509 kdDebug() << "KWTextFrameSet::isFrameEmpty text bottom=(LU) " << bottom << " theFrame=" << theFrame << " " << *theFrame << " its internalY(LU)=" << m_doc->ptToLayoutUnitPixY( theFrame->internalY() ) << endl;
02510 return bottom < m_doc->ptToLayoutUnitPixY( theFrame->internalY() );
02511 }
02512
02513 kdWarning() << "KWTextFrameSet::isFrameEmpty called for frame " << theFrame << " which isn't a child of ours!" << endl;
02514 if ( theFrame->frameSet()!=0L && theFrame->frameSet()->name()!=0L)
02515 kdDebug() << "(this is " << name() << " and the frame belongs to " << theFrame->frameSet()->name() << ")" << endl;
02516 return false;
02517 }
02518
02519 bool KWTextFrameSet::canRemovePage( int num )
02520 {
02521 kdDebug() << "KWTextFrameSet(" << name() << ")::canRemovePage " << num << endl;
02522
02523
02524 if ( num < m_firstPage || num >= (int)m_framesInPage.size() + m_firstPage ) {
02525 kdDebug() << "No frame on that page. Number of frames: " << frameCount() << endl;
02526 return true;
02527 }
02528
02529 QPtrListIterator<KWFrame> frameIt( framesInPage( num ) );
02530 for ( ; frameIt.current(); ++frameIt )
02531 {
02532 KWFrame * theFrame = frameIt.current();
02533 kdDebug() << "canRemovePage: looking at " << theFrame << " pageNum=" << theFrame->pageNumber() << endl;
02534 Q_ASSERT( theFrame->pageNumber() == num );
02535 Q_ASSERT( theFrame->frameSet() == this );
02536 bool isEmpty = isFrameEmpty( theFrame );
02537 kdDebug() << "KWTextFrameSet(" << name() << ")::canRemovePage"
02538 << " found a frame on page " << num << " empty:" << isEmpty << endl;
02539
02540 bool isCopy = theFrame->isCopy() && frameIt.current() != m_frames.first();
02541 if ( !isCopy && !isEmpty )
02542 return false;
02543 }
02544 return true;
02545 }
02546
02547 void KWTextFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
02548 {
02549 KWFrame *frm = m_frames.at( num );
02550 kdDebug() << "KWTextFrameSet(" << name() << ")::deleteFrame " << frm << " (" << num << ")" << endl;
02551 if ( frm )
02552 emit frameDeleted( frm );
02553 KWFrameSet::deleteFrame( num, remove, recalc );
02554 }
02555
02556 void KWTextFrameSet::updateViewArea( QWidget * w, KWViewMode* viewMode, const QPoint & nPointBottom )
02557 {
02558 if (!isVisible(viewMode))
02559 return;
02560 int ah = availableHeight();
02561 #ifdef DEBUG_VIEWAREA
02562 kdDebug(32002) << "KWTextFrameSet::updateViewArea " << (void*)w << " " << w->name()
02563 << " nPointBottom=" << nPointBottom.x() << "," << nPointBottom.y()
02564 << " availHeight=" << ah << " textDocument()->height()=" << textDocument()->height() << endl;
02565 #endif
02566
02567
02568 int maxPage = m_doc->pageManager()->pageNumber(m_doc->unzoomItY( nPointBottom.y() ));
02569 int maxY = 0;
02570 if ( maxPage < m_firstPage || maxPage >= (int)m_framesInPage.size() + m_firstPage )
02571 maxY = ah;
02572 else
02573 {
02574
02575 QPtrListIterator<KWFrame> frameIt( framesInPage( maxPage ) );
02576 for ( ; frameIt.current(); ++frameIt )
02577 {
02578 maxY = QMAX( maxY, m_doc->ptToLayoutUnitPixY( frameIt.current()->internalY() + frameIt.current()->innerHeight() ) );
02579 }
02580 }
02581 #ifdef DEBUG_VIEWAREA
02582 kdDebug(32002) << "KWTextFrameSet (" << name() << ")::updateViewArea maxY now " << maxY << endl;
02583 #endif
02584 m_textobj->setViewArea( w, maxY );
02585 m_textobj->formatMore( 2 );
02586 }
02587
02588 KCommand * KWTextFrameSet::setPageBreakingCommand( KoTextCursor * cursor, int pageBreaking )
02589 {
02590 if ( !textDocument()->hasSelection( KoTextDocument::Standard ) &&
02591 static_cast<KWTextParag *>(cursor->parag())->pageBreaking() == pageBreaking )
02592 return 0L;
02593
02594 m_textobj->emitHideCursor();
02595
02596 m_textobj->storeParagUndoRedoInfo( cursor );
02597
02598 if ( !textDocument()->hasSelection( KoTextDocument::Standard ) ) {
02599 KWTextParag *parag = static_cast<KWTextParag *>( cursor->parag() );
02600 parag->setPageBreaking( pageBreaking );
02601 m_textobj->setLastFormattedParag( cursor->parag() );
02602 }
02603 else
02604 {
02605 KoTextParag *start = textDocument()->selectionStart( KoTextDocument::Standard );
02606 KoTextParag *end = textDocument()->selectionEnd( KoTextDocument::Standard );
02607 m_textobj->setLastFormattedParag( start );
02608 for ( ; start && start != end->next() ; start = start->next() )
02609 static_cast<KWTextParag *>(start)->setPageBreaking( pageBreaking );
02610 }
02611
02612 m_textobj->formatMore( 2 );
02613 emit repaintChanged( this );
02614 KoTextObject::UndoRedoInfo & undoRedoInfo = m_textobj->undoRedoInfoStruct();
02615 undoRedoInfo.newParagLayout.pageBreaking = pageBreaking;
02616 KoTextParagCommand *cmd = new KoTextParagCommand(
02617 textDocument(), undoRedoInfo.id, undoRedoInfo.eid,
02618 undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
02619 KoParagLayout::PageBreaking );
02620 textDocument()->addCommand( cmd );
02621 undoRedoInfo.clear();
02622 m_textobj->emitShowCursor();
02623 m_textobj->emitUpdateUI( true );
02624 m_textobj->emitEnsureCursorVisible();
02625
02626 return new KoTextCommand( m_textobj, i18n("Change Paragraph Attribute") );
02627 }
02628
02629 KCommand * KWTextFrameSet::pasteOasis( KoTextCursor * cursor, const QByteArray & data, bool removeSelected )
02630 {
02631 if (protectContent() )
02632 return 0;
02633
02634 kdDebug(32001) << "KWTextFrameSet::pasteOasis data:" << data.size() << " bytes" << endl;
02635 KMacroCommand * macroCmd = new KMacroCommand( i18n("Paste") );
02636 if ( removeSelected && textDocument()->hasSelection( KoTextDocument::Standard ) )
02637 macroCmd->addCommand( m_textobj->removeSelectedTextCommand( cursor, KoTextDocument::Standard ) );
02638 m_textobj->emitHideCursor();
02639 m_textobj->setLastFormattedParag( cursor->parag()->prev() ?
02640 cursor->parag()->prev() : cursor->parag() );
02641
02642 KWOasisPasteCommand * cmd = new KWOasisPasteCommand( textDocument(), cursor->parag()->paragId(), cursor->index(), data );
02643 textDocument()->addCommand( cmd );
02644
02645 macroCmd->addCommand( new KoTextCommand( m_textobj, QString::null ) );
02646
02647 *cursor = *( cmd->execute( cursor ) );
02648
02649
02650
02651 ensureFormatted( cursor->parag() );
02652
02653 emit repaintChanged( this );
02654 m_textobj->emitEnsureCursorVisible();
02655 m_textobj->emitUpdateUI( true );
02656 m_textobj->emitShowCursor();
02657 m_textobj->selectionChangedNotify();
02658 return macroCmd;
02659 }
02660
02661 void KWTextFrameSet::insertTOC( KoTextCursor * cursor )
02662 {
02663 m_textobj->emitHideCursor();
02664 KMacroCommand * macroCmd = new KMacroCommand( i18n("Insert Table of Contents") );
02665
02666
02667
02668 KoTextCursor *cur= KWInsertTOCCommand::removeTOC( this, cursor, macroCmd );
02669
02670
02671
02672 KoTextDocCommand * cmd = new KWInsertTOCCommand( this,cur ? cur->parag(): cursor->parag() );
02673 textDocument()->addCommand( cmd );
02674 macroCmd->addCommand( new KoTextCommand( m_textobj, QString::null ) );
02675 *cursor = *( cmd->execute( cursor ) );
02676
02677 m_textobj->setLastFormattedParag( textDocument()->firstParag() );
02678 m_textobj->formatMore( 2 );
02679 emit repaintChanged( this );
02680 m_textobj->emitEnsureCursorVisible();
02681 m_textobj->emitUpdateUI( true );
02682 m_textobj->emitShowCursor();
02683
02684 m_doc->addCommand( macroCmd );
02685 }
02686
02687 KNamedCommand* KWTextFrameSet::insertFrameBreakCommand( KoTextCursor *cursor )
02688 {
02689 KMacroCommand* macroCmd = new KMacroCommand( QString::null );
02690 macroCmd->addCommand( m_textobj->insertParagraphCommand( cursor ) );
02691 KWTextParag *parag = static_cast<KWTextParag *>( cursor->parag() );
02692 if(parag->prev()) {
02693 parag=static_cast<KWTextParag *> (parag->prev());
02694 cursor->setParag( parag );
02695 cursor->setIndex( parag->length() - 1 );
02696 }
02697 macroCmd->addCommand( setPageBreakingCommand( cursor, parag->pageBreaking() | KoParagLayout::HardFrameBreakAfter ) );
02698 Q_ASSERT( parag->next() );
02699 if ( parag->next() ) {
02700 cursor->setParag( parag->next() );
02701 cursor->setIndex( 0 );
02702 }
02703 return macroCmd;
02704 }
02705
02706 void KWTextFrameSet::insertFrameBreak( KoTextCursor *cursor )
02707 {
02708 clearUndoRedoInfo();
02709 m_textobj->emitHideCursor();
02710 KNamedCommand* cmd = insertFrameBreakCommand( cursor );
02711 cmd->setName( i18n( "Insert Break After Paragraph" ) );
02712 m_doc->addCommand( cmd );
02713
02714 m_textobj->setLastFormattedParag( cursor->parag() );
02715 m_textobj->formatMore( 2 );
02716 emit repaintChanged( this );
02717 m_textobj->emitEnsureCursorVisible();
02718 m_textobj->emitUpdateUI( true );
02719 m_textobj->emitShowCursor();
02720 }
02721
02722 QRect KWTextFrameSet::paragRect( KoTextParag * parag ) const
02723 {
02724
02725
02726
02727
02728
02729 KoPoint p;
02730 (void)internalToDocument( parag->rect().topLeft(), p );
02731 QPoint topLeft = m_doc->zoomPoint( p );
02732 (void)internalToDocument( parag->rect().bottomRight(), p );
02733 QPoint bottomRight = m_doc->zoomPoint( p );
02734 return QRect( topLeft, bottomRight );
02735 }
02736
02737 void KWTextFrameSet::findPosition( const KoPoint &dPoint, KoTextParag * & parag, int & index )
02738 {
02739 KoTextCursor cursor( textDocument() );
02740
02741 QPoint iPoint;
02742 if ( documentToInternal( dPoint, iPoint ) )
02743 {
02744 cursor.place( iPoint, textDocument()->firstParag() );
02745 parag = cursor.parag();
02746 index = cursor.index();
02747 }
02748 else
02749 {
02750
02751 parag = textDocument()->lastParag();
02752 if ( parag )
02753 index = parag->length() - 1;
02754 }
02755 }
02756
02757 bool KWTextFrameSet::minMaxInternalOnPage( int pageNum, int& topLU, int& bottomLU ) const
02758 {
02759 QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum ) );
02760 if ( !frameIt.current() )
02761 return false;
02762
02763
02764 double topPt = frameIt.current()->internalY();
02765 double bottomPt = topPt + frameIt.current()->height();
02766
02767 for ( ; frameIt.current(); ++frameIt )
02768 {
02769 double y = frameIt.current()->internalY();
02770 topPt = QMIN( topPt, y );
02771 bottomPt = QMAX( bottomPt, y + frameIt.current()->height() );
02772 }
02773
02774 topLU = m_doc->ptToLayoutUnitPixY( topPt );
02775 bottomLU = m_doc->ptToLayoutUnitPixY( bottomPt );
02776 return true;
02777 }
02778
02779 KoTextParag* KWTextFrameSet::paragAtLUPos( int yLU ) const
02780 {
02781 KoTextParag* parag = textDocument()->firstParag();
02782 for ( ; parag ; parag = parag->next() )
02783 {
02784 if ( parag->rect().bottom() >= yLU )
02785 return parag;
02786 }
02787 return 0L;
02788 }
02789
02790 KCommand * KWTextFrameSet::deleteAnchoredFrame( KWAnchor * anchor )
02791 {
02792 kdDebug() << "KWTextFrameSet::deleteAnchoredFrame anchor->index=" << anchor->index() << endl;
02793 Q_ASSERT( anchor );
02794 KoTextCursor c( textDocument() );
02795 c.setParag( anchor->paragraph() );
02796 c.setIndex( anchor->index() );
02797
02798 textDocument()->setSelectionStart( KoTextDocument::Temp, &c );
02799 c.setIndex( anchor->index() + 1 );
02800 textDocument()->setSelectionEnd( KoTextDocument::Temp, &c );
02801 KCommand *cmd = m_textobj->removeSelectedTextCommand( &c, KoTextDocument::Temp );
02802
02803 m_doc->repaintAllViews();
02804 return cmd;
02805 }
02806
02807 bool KWTextFrameSet::hasSelection() const
02808 {
02809 return m_textobj->hasSelection();
02810 }
02811
02812 QString KWTextFrameSet::selectedText() const
02813 {
02814 return m_textobj->selectedText();
02815 }
02816
02817 QString KWTextFrameSet::toPlainText() const
02818 {
02819 return m_textobj->textDocument()->plainText();
02820 }
02821
02822 void KWTextFrameSet::highlightPortion( KoTextParag * parag, int index, int length, KWCanvas * canvas, bool repaint, KDialogBase* dialog )
02823 {
02824 Q_ASSERT( isVisible() );
02825 Q_ASSERT( m_textobj->isVisible() );
02826
02827 m_textobj->highlightPortion( parag, index, length, repaint );
02828 if ( repaint ) {
02829
02830 canvas->editTextFrameSet( this, parag, index );
02831
02832 QRect expose = canvas->viewMode()->normalToView( paragRect( parag ) );
02833 canvas->ensureVisible( (expose.left()+expose.right()) / 2,
02834 (expose.top()+expose.bottom()) / 2,
02835 (expose.right()-expose.left()) / 2,
02836 (expose.bottom()-expose.top()) / 2);
02837 if ( dialog ) {
02838
02839 QRect globalRect( expose );
02840 globalRect.moveTopLeft( canvas->mapToGlobal( globalRect.topLeft() ) );
02841 KDialog::avoidArea( dialog, globalRect );
02842 }
02843 }
02844 }
02845
02846 void KWTextFrameSet::removeHighlight( bool repaint )
02847 {
02848 m_textobj->removeHighlight( repaint );
02849 }
02850
02851 void KWTextFrameSet::clearUndoRedoInfo()
02852 {
02853 m_textobj->clearUndoRedoInfo();
02854 }
02855
02856 void KWTextFrameSet::applyStyleChange( KoStyleChangeDefMap changed )
02857 {
02858 m_textobj->applyStyleChange( changed );
02859 }
02860
02861
02862 KoTextFormat *KWTextFrameSet::currentFormat() const
02863 {
02864 return m_textobj->currentFormat();
02865 }
02866
02867 KCommand *KWTextFrameSet::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type)
02868 {
02869 KoTextDocument *textdoc = m_textobj->textDocument();
02870 textdoc->selectAll( KoTextDocument::Standard );
02871 KoTextCursor *cursor = new KoTextCursor( textDocument() );
02872 KCommand* cmd = m_textobj->changeCaseOfText(cursor, _type);
02873 textdoc->removeSelection( KoTextDocument::Standard );
02874 delete cursor;
02875 return cmd;
02876 }
02877
02878
02879 KCommand *KWTextFrameSet::setFormatCommand( const KoTextFormat * newFormat, int flags, bool zoomFont )
02880 {
02881 m_textobj->textDocument()->selectAll( KoTextDocument::Temp );
02882 KCommand *cmd = m_textobj->setFormatCommand( 0L, 0L, newFormat, flags, zoomFont, KoTextDocument::Temp );
02883 m_textobj->textDocument()->removeSelection( KoTextDocument::Temp );
02884 return cmd;
02885 }
02886
02887 const KoParagLayout * KWTextFrameSet::currentParagLayoutFormat() const
02888 {
02889 return m_textobj->currentParagLayoutFormat();
02890 }
02891
02892 bool KWTextFrameSet::rtl() const
02893 {
02894 return m_textobj->rtl();
02895 }
02896
02897
02898 KCommand *KWTextFrameSet::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags, int marginIndex)
02899 {
02900 return m_textobj->setParagLayoutFormatCommand(newLayout, flags, marginIndex);
02901 }
02902
02903 class KWFootNoteVarList : public QPtrList< KWFootNoteVariable >
02904 {
02905 protected:
02906 virtual int compareItems(QPtrCollection::Item a, QPtrCollection::Item b)
02907 {
02908 KWFootNoteVariable* vara = ((KWFootNoteVariable *)a);
02909 KWFootNoteVariable* varb = ((KWFootNoteVariable *)b);
02910 if ( vara->paragraph() == varb->paragraph() ) {
02911
02912
02913 int indexa = vara->index();
02914 int indexb = varb->index();
02915 return indexa < indexb ? -1 : indexa == indexb ? 0 : 1;
02916 }
02917 if ( vara->paragraph()->paragId() < varb->paragraph()->paragId() )
02918 return -1;
02919 return 1;
02920 }
02921 };
02922
02923 void KWTextFrameSet::renumberFootNotes( bool repaint )
02924 {
02925 KWFootNoteVarList lst;
02926 QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
02927 for ( ; cit.current() ; ++cit )
02928 {
02929 KWFootNoteVariable *fnv = dynamic_cast<KWFootNoteVariable *>( cit.current() );
02930 if (fnv && !fnv->isDeleted() && (fnv->frameSet() && !fnv->frameSet()->isDeleted()))
02931 lst.append( fnv );
02932 }
02933 lst.sort();
02934 short int footNoteVarNumber = 0;
02935 short int endNoteVarNumber = 0;
02936 short int footNoteNumDisplay = 1;
02937 short int endNoteNumDisplay = 1;
02938 bool needRepaint = false;
02939 QPtrListIterator< KWFootNoteVariable > vit( lst );
02940
02941
02942 QValueList<int> addedNums;
02943 for ( ; vit.current() ; ++vit )
02944 {
02945 KWFootNoteVariable* var = vit.current();
02946 if ( var->numberingType()==KWFootNoteVariable::Manual )
02947 {
02948 uint const num = var->text().toUInt();
02949 if ( num != 0 )
02950 addedNums.append( num );
02951 }
02952 }
02953
02954 for ( vit.toFirst() ; vit.current() ; )
02955 {
02956 KWFootNoteVariable* var = vit.current();
02957 bool endNote = var->noteType() == EndNote;
02958 short int & varNumber = endNote ? endNoteVarNumber : footNoteVarNumber;
02959 short int & numDisplay = endNote ? endNoteNumDisplay : footNoteNumDisplay;
02960 ++varNumber;
02961 bool changed = false;
02962 if ( varNumber != var->num() || var->numberingType()==KWFootNoteVariable::Manual )
02963 {
02964 changed = true;
02965 var->setNum( varNumber );
02966 }
02967 if ( var->numberingType()==KWFootNoteVariable::Auto )
02968 {
02969 if ( addedNums.contains( numDisplay ) != 0 )
02970 {
02971 numDisplay++;
02972 continue;
02973 }
02974 if ( numDisplay != var->numDisplay() )
02975 {
02976 changed = true;
02977 var->setNumDisplay( numDisplay );
02978 }
02979 numDisplay++;
02980 }
02981 if ( changed )
02982 {
02983 if ( var->frameSet() )
02984 {
02985 QString fsName = endNote ? i18n("Endnote %1") : i18n("Footnote %1");
02986 if ( var->numberingType()== KWFootNoteVariable::Manual)
02987 var->frameSet()->setName( m_doc->generateFramesetName(fsName));
02988 else
02989 var->frameSet()->setName( fsName.arg( var->text() ) );
02990 var->frameSet()->setCounterText( var->text() );
02991 }
02992 var->resize();
02993 var->paragraph()->invalidate(0);
02994 var->paragraph()->setChanged( true );
02995 needRepaint = true;
02996 }
02997 ++vit;
02998 }
02999 if ( needRepaint && repaint )
03000 m_doc->slotRepaintChanged( this );
03001 }
03002
03003 KoTextDocCommand *KWTextFrameSet::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts )
03004 {
03005 return new KWTextDeleteCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts );
03006 }
03007
03008 QByteArray KWTextFrameSet::sortText(SortType type) const
03009 {
03010 const KoTextCursor c1 = textDocument()->selectionStartCursor(KoTextDocument::Standard );
03011 const KoTextCursor c2 = textDocument()->selectionEndCursor( KoTextDocument::Standard );
03012 if ( c1.parag() == c2.parag() )
03013 return QByteArray();
03014 else
03015 {
03016
03017 QMap<QString, const KoTextParag*> sortMap;
03018 sortMap.insert( c1.parag()->toString(0), c1.parag() );
03019
03020 const KoTextParag *p = c1.parag()->next();
03021 while ( p && p != c2.parag() ) {
03022 sortMap.insert( p->toString(0), p );
03023 p = p->next();
03024 }
03025 sortMap.insert( c2.parag()->toString(0), c2.parag());
03026
03027 typedef QValueList<const KoTextParag *> ParagList;
03028 ParagList sortedParags = sortMap.values();
03029 if ( type == KW_SORTDECREASE )
03030 {
03031
03032 ParagList newList;
03033 for ( ParagList::const_iterator it = sortedParags.begin(),
03034 end = sortedParags.end();
03035 it != end ; ++it ) {
03036 newList.prepend( *it );
03037 }
03038 sortedParags = newList;
03039 }
03040
03041 KWOasisSaver oasisSaver( m_doc );
03042 oasisSaver.saveParagraphs( sortedParags );
03043 if ( !oasisSaver.finish() )
03044 return QByteArray();
03045 return oasisSaver.data();
03046 }
03047 }
03048
03049
03050
03051
03052 KWFootNoteFrameSet * KWTextFrameSet::insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const QString &manualString )
03053 {
03054 kdDebug() << "KWTextFrameSetEdit::insertFootNote " << endl;
03055 KWDocument * doc = m_doc;
03056 KWFootNoteVariable * var = new KWFootNoteVariable( textDocument(), doc->variableFormatCollection()->format( "NUMBER" ), doc->variableCollection(), doc );
03057 var->setNoteType( noteType );
03058 var->setNumberingType( numType );
03059 if ( numType == KWFootNoteVariable::Manual )
03060 var->setManualString( manualString );
03061
03062
03063 KWFootNoteFrameSet *fs = new KWFootNoteFrameSet( doc, i18n( "Footnotes" ) );
03064 fs->setFrameSetInfo( KWFrameSet::FI_FOOTNOTE );
03065
03066 doc->addFrameSet( fs );
03067
03068
03069 var->setFrameSet( fs );
03070 fs->setFootNoteVariable( var );
03071
03072 return fs;
03073 }
03074
03075 KoVariable* KWTextFrameSet::variableUnderMouse( const KoPoint& dPoint )
03076 {
03077 QPoint iPoint;
03078 if ( documentToInternal( dPoint, iPoint ) )
03079 return textObject()->variableAtPoint( iPoint );
03080 return 0;
03081 }
03082
03083 KoLinkVariable* KWTextFrameSet::linkVariableUnderMouse( const KoPoint& dPoint )
03084 {
03085 QPoint iPoint;
03086 if ( documentToInternal( dPoint, iPoint ) )
03087 {
03088 KoLinkVariable* linkVariable = dynamic_cast<KoLinkVariable *>( textObject()->variableAtPoint( iPoint ) );
03089 return linkVariable;
03090 }
03091 return 0;
03092 }
03093
03095
03096 KWTextFrameSetEdit::KWTextFrameSetEdit( KWTextFrameSet * fs, KWCanvas * canvas )
03097 : KoTextView( fs->textObject() ), KWFrameSetEdit( fs, canvas ), m_rtl( false )
03098 {
03099 setBackSpeller( fs->kWordDocument()->backSpeller() );
03100
03101 KoTextView::setReadWrite( fs->kWordDocument()->isReadWrite() );
03102 KoTextObject* textobj = fs->textObject();
03103 connect( textobj, SIGNAL( selectionChanged(bool) ), canvas, SIGNAL( selectionChanged(bool) ) );
03104 connect( fs, SIGNAL( frameDeleted(KWFrame *) ), this, SLOT( slotFrameDeleted(KWFrame *) ) );
03105 connect( textView(), SIGNAL( cut() ), SLOT( cut() ) );
03106 connect( textView(), SIGNAL( copy() ), SLOT( copy() ) );
03107 connect( textView(), SIGNAL( paste() ), SLOT( paste() ) );
03108 updateUI( true, true );
03109
03110 if( canvas->gui() && canvas->gui()->getHorzRuler())
03111 {
03112 if ( !textobj->protectContent() )
03113 canvas->gui()->getHorzRuler()->changeFlags(KoRuler::F_INDENTS | KoRuler::F_TABS);
03114 else
03115 canvas->gui()->getHorzRuler()->changeFlags(0);
03116 }
03117
03118 setOverwriteMode( canvas->overwriteMode() );
03119 }
03120
03121 KWTextFrameSetEdit::~KWTextFrameSetEdit()
03122 {
03123
03124
03125 }
03126
03127 KoTextViewIface* KWTextFrameSetEdit::dcopObject()
03128 {
03129 if ( !dcop )
03130 dcop = new KWordTextFrameSetEditIface( this );
03131
03132 return dcop;
03133 }
03134
03135 void KWTextFrameSetEdit::terminate(bool removeSelection)
03136 {
03137 disconnect( textView()->textObject(), SIGNAL( selectionChanged(bool) ), m_canvas, SIGNAL( selectionChanged(bool) ) );
03138 textView()->terminate(removeSelection);
03139 }
03140
03141 void KWTextFrameSetEdit::slotFrameDeleted( KWFrame *frm )
03142 {
03143 if ( m_currentFrame == frm )
03144 m_currentFrame = 0L;
03145 }
03146
03147 void KWTextFrameSetEdit::paste()
03148 {
03149 QMimeSource *data = QApplication::clipboard()->data();
03150 int provides = KWView::checkClipboard( data );
03151 pasteData( data, provides, false );
03152 }
03153
03154 void KWTextFrameSetEdit::pasteData( QMimeSource* data, int provides, bool drop )
03155 {
03156 if ( provides & KWView::ProvidesOasis )
03157 {
03158 KCommand* cmd = pasteOasisCommand( data );
03159 if ( cmd )
03160 frameSet()->kWordDocument()->addCommand(cmd);
03161 }
03162 else if ( provides & KWView::ProvidesPlainText )
03163 {
03164
03165
03166 const QString text = QApplication::clipboard()->text();
03167 const bool removeSelected = !drop;
03168 if ( !text.isEmpty() )
03169 textObject()->pasteText( cursor(), text, currentFormat(), removeSelected );
03170 }
03171 else {
03172 kdWarning(32002) << "Unhandled case in KWTextFrameSetEdit::pasteData: provides=" << provides << endl;
03173 }
03174
03175 KWFootNoteFrameSet *footNote = dynamic_cast<KWFootNoteFrameSet *>(textFrameSet());
03176 if ( footNote )
03177 {
03178 KoParagCounter *counter = footNote->textDocument()->firstParag()->counter();
03179 if ( !counter || ( counter->numbering() != KoParagCounter::NUM_FOOTNOTE ) )
03180 footNote->setCounterText( footNote->footNoteVariable()->text() );
03181 frameSet()->kWordDocument()->slotRepaintChanged( frameSet() );
03182 }
03183 }
03184
03185 KCommand* KWTextFrameSetEdit::pasteOasisCommand( QMimeSource* data )
03186 {
03187
03188 QCString returnedTypeMime = KoTextObject::providesOasis( data );
03189 if ( !returnedTypeMime.isEmpty() )
03190 {
03191 QByteArray arr = data->encodedData( returnedTypeMime );
03192 Q_ASSERT( !arr.isEmpty() );
03193 if ( arr.size() )
03194 return textFrameSet()->pasteOasis( cursor(), arr, true );
03195 }
03196 return 0;
03197 }
03198
03199 void KWTextFrameSetEdit::cut()
03200 {
03201 if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) {
03202 copy();
03203 textObject()->removeSelectedText( cursor() );
03204 }
03205 }
03206
03207 void KWTextFrameSetEdit::copy()
03208 {
03209 if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) {
03210 QDragObject *drag = newDrag( 0 );
03211 QApplication::clipboard()->setData( drag );
03212 }
03213 }
03214
03215 bool KWTextFrameSetEdit::doIgnoreDoubleSpace(KoTextParag * parag,
03216 int index,QChar ch )
03217 {
03218 if( textFrameSet()->kWordDocument()->allowAutoFormat())
03219 {
03220 KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
03221 if( autoFormat )
03222 {
03223 return autoFormat->doIgnoreDoubleSpace( parag, index,ch );
03224 }
03225 }
03226 return false;
03227
03228 }
03229
03230
03231 void KWTextFrameSetEdit::doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, QChar ch )
03232 {
03233 if( textFrameSet()->kWordDocument()->allowAutoFormat() )
03234 {
03235 KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
03236 if( autoFormat )
03237 autoFormat->doAutoFormat( cursor, parag, index, ch, textObject());
03238 }
03239 }
03240
03241 bool KWTextFrameSetEdit::doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index )
03242 {
03243 if( textFrameSet()->kWordDocument()->allowAutoFormat() )
03244 {
03245 KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
03246 if( autoFormat )
03247 return autoFormat->doCompletion( cursor, parag, index, textObject());
03248 }
03249 return false;
03250 }
03251
03252 bool KWTextFrameSetEdit::doToolTipCompletion( KoTextCursor* cursor, KoTextParag *parag, int index, int keyPressed )
03253 {
03254 if( textFrameSet()->kWordDocument()->allowAutoFormat() )
03255 {
03256 KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
03257 if( autoFormat )
03258 return autoFormat->doToolTipCompletion( cursor, parag, index, textObject(), keyPressed);
03259 }
03260 return false;
03261 }
03262
03263 void KWTextFrameSetEdit::showToolTipBox(KoTextParag *parag, int index, QWidget *widget, const QPoint &pos)
03264 {
03265 if( textFrameSet()->kWordDocument()->allowAutoFormat() )
03266 {
03267 KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
03268 if( autoFormat )
03269 autoFormat->showToolTipBox(parag, index, widget, pos);
03270 }
03271 }
03272
03273 void KWTextFrameSetEdit::removeToolTipCompletion()
03274 {
03275 if( textFrameSet()->kWordDocument()->allowAutoFormat() )
03276 {
03277 KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
03278 if( autoFormat )
03279 autoFormat->removeToolTipCompletion();
03280 }
03281 }
03282
03283 void KWTextFrameSetEdit::textIncreaseIndent()
03284 {
03285 kdDebug(32001) << "Increasing list" << endl;
03286 m_canvas->gui()->getView()->textIncreaseIndent();
03287 }
03288
03289 bool KWTextFrameSetEdit::textDecreaseIndent()
03290 {
03291 if (currentLeftMargin()>0)
03292 {
03293 kdDebug(32001) << "Decreasing list" << endl;
03294 m_canvas->gui()->getView()->textDecreaseIndent();
03295 return true;
03296 }
03297 else
03298 return false;
03299 }
03300
03301 void KWTextFrameSetEdit::startDrag()
03302 {
03303 textView()->dragStarted();
03304 m_canvas->dragStarted();
03305 QDragObject *drag = newDrag( m_canvas->viewport() );
03306 if ( !frameSet()->kWordDocument()->isReadWrite() )
03307 drag->dragCopy();
03308 else {
03309 bool move = ( drag->drag() );
03310 if ( move )
03311 {
03312 #if 0
03313 if ( QDragObject::target() != m_canvas && QDragObject::target() != m_canvas->viewport() ) {
03314
03315
03316
03317
03318
03319 textObject()->removeSelectedText( cursor() );
03320 }
03321 #endif
03322 }
03323 }
03324 }
03325
03326 QDragObject * KWTextFrameSetEdit::newDrag( QWidget * parent )
03327 {
03328 KWTextFrameSet* fs = textFrameSet();
03329 return fs->kWordDocument()->dragSelected( parent, fs );
03330 }
03331
03332 void KWTextFrameSetEdit::ensureCursorVisible()
03333 {
03334
03335 KoTextParag * parag = cursor()->parag();
03336 int idx = cursor()->index();
03337 textFrameSet()->ensureFormatted( parag );
03338 KoTextStringChar *chr = parag->at( idx );
03339 int cursorHeight = parag->lineHeightOfChar( idx );
03340 int x = parag->rect().x() + cursor()->x();
03341
03342 int y = 0; int dummy;
03343 parag->lineHeightOfChar( idx, &dummy, &y );
03344 y += parag->rect().y();
03345
03346
03347 KoTextStringChar *chrLeft = idx > 0 ? chr-1 : chr;
03348
03349 int areaLeft = chr->rightToLeft ? chr->width : chrLeft->width;
03350 int areaRight = chr->rightToLeft ? chrLeft->width : chr->width;
03351 KoPoint pt;
03352 KoPoint hintDPoint;
03353 if ( m_currentFrame )
03354 hintDPoint = m_currentFrame->topLeft();
03355 KWFrame * theFrame = textFrameSet()->internalToDocumentWithHint( QPoint(x, y), pt, hintDPoint );
03356
03357 if ( theFrame && m_currentFrame != theFrame )
03358 {
03359 m_currentFrame = theFrame;
03360 m_canvas->gui()->getView()->updatePageInfo();
03361 }
03362 QPoint cursorPos = textFrameSet()->kWordDocument()->zoomPoint( pt );
03363 cursorPos = m_canvas->viewMode()->normalToView( cursorPos );
03364 areaLeft = textFrameSet()->kWordDocument()->layoutUnitToPixelX( areaLeft ) + 1;
03365 areaRight = textFrameSet()->kWordDocument()->layoutUnitToPixelX( areaRight ) + 1;
03366 cursorHeight = textFrameSet()->kWordDocument()->layoutUnitToPixelY( cursorHeight );
03367
03368
03369 m_canvas->ensureVisible( cursorPos.x() - areaLeft, cursorPos.y() + cursorHeight / 2, areaLeft + areaRight, cursorHeight / 2 + 2 );
03370 }
03371
03372 bool KWTextFrameSetEdit::enterCustomItem( KoTextCustomItem* customItem, bool fromRight )
03373 {
03374 KWAnchor* anchor = dynamic_cast<KWAnchor*>( customItem );
03375 if ( anchor ) {
03376 KWFrameSet* frameSet = anchor->frameSet();
03377 if ( frameSet->type() == FT_FORMULA || frameSet->type() == FT_TEXT ) {
03378
03379
03380 KWCanvas* canvas = m_canvas;
03381
03382
03383 m_canvas->editFrameSet( frameSet );
03384
03385
03386 if ( fromRight ) {
03387 KWFrameSetEdit* edit = canvas->currentFrameSetEdit();
03388 if ( frameSet->type() == FT_FORMULA )
03389 static_cast<KWFormulaFrameSetEdit*>( edit )->moveEnd();
03390 else
03391 static_cast<KWTextFrameSetEdit*>( edit )->moveCursor( MoveEnd );
03392 }
03393
03394 if ( frameSet->type() == FT_FORMULA )
03395 {
03396
03397
03398 static_cast<KWFormulaFrameSet*>( frameSet )->setChanged();
03399 canvas->repaintChanged( frameSet, true );
03400 }
03401 return true;
03402 }
03403 }
03404 return false;
03405 }
03406
03407 void KWTextFrameSetEdit::keyPressEvent( QKeyEvent* e )
03408 {
03409
03410 if ( !( e->state() & ControlButton ) && !( e->state() & ShiftButton ) )
03411 {
03412 if (e->state() != Qt::NoButton)
03413 removeToolTipCompletion();
03414 switch ( e->key() ) {
03415 case Key_Left: {
03416 KoTextCursor* cursor = textView()->cursor();
03417 KoTextParag* parag = cursor->parag();
03418 int index = cursor->index();
03419 if ( index > 0 ) {
03420 KoTextStringChar* ch = parag->at( index-1 );
03421 if ( ch->isCustom() ) {
03422 KoTextCustomItem* customItem = ch->customItem();
03423 if ( enterCustomItem( customItem, true ) ) {
03424
03425 return;
03426 }
03427 }
03428 }
03429 if ( index == 0 && !parag->prev() )
03430 if ( exitLeft() )
03431 return;
03432 break;
03433 }
03434 case Key_Right: {
03435 KoTextCursor* cursor = textView()->cursor();
03436 KoTextParag* parag = cursor->parag();
03437 int index = cursor->index();
03438 if ( index < parag->length() - 1 ) {
03439 KoTextStringChar* ch = parag->at( index );
03440 if ( ch->isCustom() ) {
03441 KoTextCustomItem* customItem = ch->customItem();
03442 if ( enterCustomItem( customItem, false ) ) {
03443
03444 return;
03445 }
03446 }
03447 } else if ( !parag->next() )
03448 if ( exitRight() )
03449 return;
03450 break;
03451 }
03452 }
03453 }
03454
03455 QPoint pos = textFrameSet()->cursorPos( cursor(), m_canvas, m_currentFrame );
03456 textView()->handleKeyPressEvent( e, m_canvas, pos );
03457 }
03458
03459 void KWTextFrameSetEdit::keyReleaseEvent( QKeyEvent* e )
03460 {
03461 textView()->handleKeyReleaseEvent( e );
03462 }
03463
03464 void KWTextFrameSetEdit::imStartEvent( QIMEvent* e )
03465 {
03466 textView()->handleImStartEvent( e );
03467 }
03468
03469 void KWTextFrameSetEdit::imComposeEvent( QIMEvent* e )
03470 {
03471 textView()->handleImComposeEvent( e );
03472 }
03473
03474 void KWTextFrameSetEdit::imEndEvent( QIMEvent* e )
03475 {
03476 textView()->handleImEndEvent( e );
03477 }
03478
03479 void KWTextFrameSetEdit::mousePressEvent( QMouseEvent *e, const QPoint &, const KoPoint & dPoint )
03480 {
03481 if ( dPoint.x() < 0 || dPoint.y() < 0 )
03482 return;
03483
03484 textFrameSet()->textObject()->clearUndoRedoInfo();
03485 if ( m_currentFrame )
03486 hideCursor();
03487
03488 QPoint iPoint;
03489 KWTextFrameSet::RelativePosition relPos;
03490 KWFrame * theFrame = textFrameSet()->documentToInternalMouseSelection( dPoint, iPoint, relPos, m_canvas->viewMode() );
03491 if ( theFrame && m_currentFrame != theFrame )
03492 {
03493 m_currentFrame = theFrame;
03494 m_canvas->gui()->getView()->updatePageInfo();
03495 }
03496
03497 if ( m_currentFrame )
03498 {
03499
03500
03501 bool addParag = textView()->handleMousePressEvent( e, iPoint, relPos != KWTextFrameSet::LeftOfFrame, frameSet()->kWordDocument()->insertDirectCursor() );
03502
03503
03504
03505 if ( relPos == KWTextFrameSet::LeftOfFrame )
03506 textView()->selectParagUnderCursor( *textView()->cursor() );
03507 if ( addParag )
03508 frameSet()->kWordDocument()->setModified(true );
03509 }
03510
03511
03512 if ( e->button() != LeftButton )
03513 return;
03514 KoVariable* var = variable();
03515 if ( var )
03516 {
03517 KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
03518 if ( footNoteVar )
03519 {
03520 footNoteVar->frameSet()->startEditing( m_canvas );
03521
03522 }
03523 }
03524 }
03525
03526 void KWTextFrameSetEdit::mouseMoveEvent( QMouseEvent * e, const QPoint & nPoint, const KoPoint & )
03527 {
03528 if ( textView()->maybeStartDrag( e ) )
03529 return;
03530 if ( nPoint.x() < 0 || nPoint.y() < 0 )
03531 return;
03532
03533 QPoint iPoint;
03534 KoPoint dPoint = frameSet()->kWordDocument()->unzoomPoint( nPoint );
03535 KWTextFrameSet::RelativePosition relPos;
03536 if ( nPoint.y() > 0 && textFrameSet()->documentToInternalMouseSelection( dPoint, iPoint, relPos , m_canvas->viewMode()) )
03537 {
03538 if ( relPos == KWTextFrameSet::LeftOfFrame )
03539 textView()->extendParagraphSelection( iPoint );
03540 else
03541 textView()->handleMouseMoveEvent( e, iPoint );
03542 }
03543
03544 }
03545
03546 bool KWTextFrameSetEdit::openLink( KoLinkVariable* variable )
03547 {
03548 KWTextFrameSet* fs = textFrameSet();
03549 KWDocument* doc = fs->kWordDocument();
03550 if ( doc->variableCollection()->variableSetting()->displayLink() ) {
03551
03552 const QString url = variable->url();
03553 if( url.startsWith("bkm://") )
03554 {
03555 const KoTextBookmark* bookmark = doc->bookmarkByName(url.mid(6) );
03556 if ( bookmark )
03557 {
03558 cursor()->setParag( bookmark->startParag() );
03559 ensureCursorVisible();
03560 return true;
03561 }
03562 }
03563 KoTextView::openLink( variable );
03564 return true;
03565 }
03566 return false;
03567 }
03568
03569 void KWTextFrameSetEdit::openLink()
03570 {
03571 KoLinkVariable* v = linkVariable();
03572 if ( v )
03573 openLink( v );
03574 }
03575
03576 void KWTextFrameSetEdit::mouseReleaseEvent( QMouseEvent *, const QPoint &, const KoPoint & )
03577 {
03578 textView()->handleMouseReleaseEvent();
03579 }
03580
03581 void KWTextFrameSetEdit::mouseDoubleClickEvent( QMouseEvent *e, const QPoint &, const KoPoint & )
03582 {
03583 textView()->handleMouseDoubleClickEvent( e, QPoint() );
03584 }
03585
03586 void KWTextFrameSetEdit::dragEnterEvent( QDragEnterEvent * e )
03587 {
03588 int provides = KWView::checkClipboard( e );
03589 if ( !frameSet()->kWordDocument()->isReadWrite() || provides == 0 )
03590 {
03591 e->ignore();
03592 return;
03593 }
03594 e->acceptAction();
03595 }
03596
03597 void KWTextFrameSetEdit::dragMoveEvent( QDragMoveEvent * e, const QPoint &nPoint, const KoPoint & )
03598 {
03599 int provides = KWView::checkClipboard( e );
03600 if ( !frameSet()->kWordDocument()->isReadWrite() || provides == 0 )
03601 {
03602 e->ignore();
03603 return;
03604 }
03605
03606
03607 if ( provides & ( KWView::ProvidesOasis | KWView::ProvidesPlainText | KWView::ProvidesFormula ) )
03608 {
03609 QPoint iPoint;
03610 KoPoint dPoint = frameSet()->kWordDocument()->unzoomPoint( nPoint );
03611 if ( textFrameSet()->documentToInternal( dPoint, iPoint ) )
03612 {
03613 textObject()->emitHideCursor();
03614 placeCursor( iPoint );
03615 textObject()->emitShowCursor();
03616 }
03617 }
03618 e->acceptAction();
03619 }
03620
03621 void KWTextFrameSetEdit::dragLeaveEvent( QDragLeaveEvent * )
03622 {
03623 }
03624
03625 void KWTextFrameSetEdit::dropEvent( QDropEvent * e, const QPoint & nPoint, const KoPoint &, KWView* view )
03626 {
03627 int provides = KWView::checkClipboard( e );
03628 if ( frameSet()->kWordDocument()->isReadWrite() && provides )
03629 {
03630 e->acceptAction();
03631 KoTextCursor dropCursor( textDocument() );
03632 QPoint dropPoint;
03633 KoPoint dPoint = frameSet()->kWordDocument()->unzoomPoint( nPoint );
03634 if ( !textFrameSet()->documentToInternal( dPoint, dropPoint ) )
03635 return;
03636
03637 dropCursor.place( dropPoint, textDocument()->firstParag() );
03638 kdDebug(32001) << "KWTextFrameSetEdit::dropEvent dropCursor at parag=" << dropCursor.parag()->paragId() << " index=" << dropCursor.index() << endl;
03639
03640 if ( ( e->source() == m_canvas ||
03641 e->source() == m_canvas->viewport() ) &&
03642 e->action() == QDropEvent::Move &&
03643
03644 textDocument()->hasSelection( KoTextDocument::Standard ) ) {
03645
03646 KCommand *cmd = textView()->prepareDropMove( dropCursor );
03647 if(cmd)
03648 {
03649 KMacroCommand* macroCmd = new KMacroCommand( i18n( "Move Text" ) );
03650 macroCmd->addCommand(cmd);
03651
03652 cmd = pasteOasisCommand( e );
03653 if ( cmd )
03654 macroCmd->addCommand(cmd);
03655
03656
03657 textFrameSet()->layout();
03658 frameSet()->kWordDocument()->addCommand( macroCmd );
03659 }
03660 return;
03661 }
03662 else
03663 {
03664 textDocument()->removeSelection( KoTextDocument::Standard );
03665 textObject()->selectionChangedNotify();
03666 }
03667
03668
03669 view->pasteData( e, true );
03670 }
03671 }
03672
03673 void KWTextFrameSetEdit::focusInEvent()
03674 {
03675 textView()->focusInEvent();
03676 }
03677
03678 void KWTextFrameSetEdit::focusOutEvent()
03679 {
03680 textView()->focusOutEvent();
03681 }
03682
03683 void KWTextFrameSetEdit::selectAll()
03684 {
03685 textObject()->selectAll( true );
03686 }
03687
03688 void KWTextFrameSetEdit::drawCursor( bool visible )
03689 {
03690 #ifdef DEBUG_CURSOR
03691 kdDebug() << "KWTextFrameSetEdit::drawCursor " << visible << endl;
03692 #endif
03693 KoTextView::drawCursor( visible );
03694 if ( !cursor()->parag() )
03695 return;
03696
03697 if ( !cursor()->parag()->isValid() )
03698 textFrameSet()->ensureFormatted( cursor()->parag() );
03699
03700 if ( !frameSet()->kWordDocument()->isReadWrite() )
03701 return;
03702 if ( m_canvas->viewMode()->hasFrames() && !m_currentFrame )
03703 return;
03704
03705 QPainter p( m_canvas->viewport() );
03706 p.translate( -m_canvas->contentsX(), -m_canvas->contentsY() );
03707 p.setBrushOrigin( -m_canvas->contentsX(), -m_canvas->contentsY() );
03708
03709 textFrameSet()->drawCursor( &p, cursor(), visible, m_canvas, m_currentFrame );
03710 }
03711
03712 bool KWTextFrameSetEdit::pgUpKeyPressed()
03713 {
03714 QRect crect( m_canvas->contentsX(), m_canvas->contentsY(),
03715 m_canvas->visibleWidth(), m_canvas->visibleHeight() );
03716 crect = m_canvas->viewMode()->viewToNormal( crect );
03717
03718
03719 int h = frameSet()->kWordDocument()->pixelToLayoutUnitY( (int)( (double)crect.height() * 0.9 ) );
03720 KoTextParag *s = textView()->cursor()->parag();
03721 KoTextParag* oldParag = s;
03722 int y = s->rect().y();
03723 while ( s ) {
03724 if ( y - s->rect().y() >= h )
03725 break;
03726 s = s->prev();
03727 }
03728
03729 if ( !s )
03730 s = textDocument()->firstParag();
03731
03732 textView()->cursor()->setParag( s );
03733 textView()->cursor()->setIndex( 0 );
03734 if ( s == oldParag )
03735 {
03736 m_canvas->viewportScroll( true );
03737 return false;
03738 }
03739 return true;
03740 }
03741
03742 bool KWTextFrameSetEdit::pgDownKeyPressed()
03743 {
03744 QRect crect( m_canvas->contentsX(), m_canvas->contentsY(),
03745 m_canvas->visibleWidth(), m_canvas->visibleHeight() );
03746 crect = m_canvas->viewMode()->viewToNormal( crect );
03747
03748 int h = frameSet()->kWordDocument()->pixelToLayoutUnitY( (int)( (double)crect.height() * 0.9 ) );
03749
03750 KoTextCursor *cursor = textView()->cursor();
03751 KoTextParag *s = cursor->parag();
03752 KoTextParag* oldParag = s;
03753 int y = s->rect().y();
03754 while ( s ) {
03755 if ( s->rect().y() - y >= h )
03756 break;
03757 s = s->next();
03758 }
03759
03760 if ( !s ) {
03761 s = textDocument()->lastParag();
03762 cursor->setParag( s );
03763 cursor->setIndex( s->length() - 1 );
03764 } else {
03765 cursor->setParag( s );
03766 cursor->setIndex( 0 );
03767 }
03768 if ( s == oldParag )
03769 {
03770 m_canvas->viewportScroll( false );
03771 return false;
03772 }
03773 return true;
03774 }
03775
03776 void KWTextFrameSetEdit::ctrlPgUpKeyPressed()
03777 {
03778 if ( m_currentFrame )
03779 {
03780 QPoint iPoint = textFrameSet()->moveToPage( m_currentFrame->pageNumber(), -1 );
03781 if ( !iPoint.isNull() )
03782 placeCursor( iPoint );
03783 }
03784 }
03785
03786 void KWTextFrameSetEdit::ctrlPgDownKeyPressed()
03787 {
03788 if ( m_currentFrame )
03789 {
03790 QPoint iPoint = textFrameSet()->moveToPage( m_currentFrame->pageNumber(), +1 );
03791 if ( !iPoint.isNull() )
03792 placeCursor( iPoint );
03793 }
03794 }
03795
03796 void KWTextFrameSetEdit::setCursor( KoTextParag* parag, int index )
03797 {
03798 cursor()->setParag( parag );
03799 cursor()->setIndex( index );
03800 }
03801
03802 void KWTextFrameSetEdit::insertExpression(const QString &_c)
03803 {
03804 if(textObject()->hasSelection() )
03805 frameSet()->kWordDocument()->addCommand(textObject()->replaceSelectionCommand(
03806 cursor(), _c, i18n("Insert Expression")));
03807 else
03808 textObject()->insert( cursor(), currentFormat(), _c, i18n("Insert Expression") );
03809 }
03810
03811 void KWTextFrameSetEdit::insertFloatingFrameSet( KWFrameSet * fs, const QString & commandName )
03812 {
03813 textObject()->clearUndoRedoInfo();
03814 CustomItemsMap customItemsMap;
03815 QString placeHolders;
03816
03817 int frameNumber = 0;
03818 int index = 0;
03819 int insertFlags = KoTextObject::DoNotRemoveSelected;
03820 {
03821 KWAnchor * anchor = fs->createAnchor( textFrameSet()->textDocument(), frameNumber );
03822 if ( frameNumber == 0 && anchor->ownLine() && cursor()->index() > 0 )
03823 {
03824 kdDebug() << "ownline -> prepending \\n" << endl;
03825 placeHolders += QChar('\n');
03826 index++;
03827 insertFlags |= KoTextObject::CheckNewLine;
03828 }
03829 placeHolders += KoTextObject::customItemChar();
03830 customItemsMap.insert( index, anchor );
03831 }
03832 fs->setAnchored( textFrameSet() );
03833 textObject()->insert( cursor(), currentFormat(), placeHolders,
03834 commandName, KoTextDocument::Standard, insertFlags,
03835 customItemsMap );
03836 }
03837
03838 void KWTextFrameSetEdit::insertLink(const QString &_linkName, const QString & hrefName)
03839 {
03840 KWDocument * doc = frameSet()->kWordDocument();
03841 KoVariable * var = new KoLinkVariable( textFrameSet()->textDocument(), _linkName, hrefName, doc->variableFormatCollection()->format( "STRING" ), doc->variableCollection() );
03842 insertVariable( var );
03843 }
03844
03845 void KWTextFrameSetEdit::insertComment(const QString &_comment)
03846 {
03847 KWDocument * doc = frameSet()->kWordDocument();
03848 KoVariable * var = new KoNoteVariable( textFrameSet()->textDocument(), _comment, doc->variableFormatCollection()->format( "STRING" ), doc->variableCollection() );
03849 insertVariable( var );
03850 }
03851
03852
03853 void KWTextFrameSetEdit::insertCustomVariable( const QString &name)
03854 {
03855 KWDocument * doc = frameSet()->kWordDocument();
03856 KoVariable * var = new KoCustomVariable( textFrameSet()->textDocument(), name, doc->variableFormatCollection()->format( "STRING" ), doc->variableCollection());
03857 insertVariable( var );
03858 }
03859
03860 void KWTextFrameSetEdit::insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const QString &manualString )
03861 {
03862 KWFootNoteFrameSet *fs = textFrameSet()->insertFootNote( noteType, numType, manualString );
03863 KWFootNoteVariable * var = fs->footNoteVariable();
03864
03865
03866
03867 int pageNum = m_currentFrame->pageNumber();
03868 fs->createInitialFrame( pageNum );
03869
03870 insertVariable( var );
03871
03872
03873 textFrameSet()->renumberFootNotes();
03874
03875
03876 textFrameSet()->kWordDocument()->recalcFrames( pageNum, -1 );
03877
03878
03879
03880
03881
03882 fs->startEditing( m_canvas );
03883
03884 }
03885
03886 void KWTextFrameSetEdit::insertVariable( int type, int subtype )
03887 {
03888 kdDebug() << "KWTextFrameSetEdit::insertVariable " << type << endl;
03889 KWDocument * doc = frameSet()->kWordDocument();
03890
03891 KoVariable * var = 0L;
03892 bool refreshCustomMenu = false;
03893 if ( type == VT_CUSTOM )
03894 {
03895 KoCustomVarDialog dia( m_canvas );
03896 if ( dia.exec() == QDialog::Accepted )
03897 {
03898 KoCustomVariable *v = new KoCustomVariable( textFrameSet()->textDocument(), dia.name(), doc->variableFormatCollection()->format( "STRING" ),doc->variableCollection() );
03899 v->setValue( dia.value() );
03900 var = v;
03901 refreshCustomMenu = true;
03902 }
03903 }
03904 else if ( type == VT_MAILMERGE )
03905 {
03906 KWMailMergeVariableInsertDia dia( m_canvas, doc->mailMergeDataBase() );
03907 if ( dia.exec() == QDialog::Accepted )
03908 {
03909 var = new KWMailMergeVariable( textFrameSet()->textDocument(), dia.getName(), doc->variableFormatCollection()->format( "STRING" ),doc->variableCollection(),doc );
03910 }
03911 }
03912 else
03913 var = doc->variableCollection()->createVariable( type, subtype, doc->variableFormatCollection(), 0L, textFrameSet()->textDocument(), doc, 0);
03914 if ( var)
03915 insertVariable( var, 0L , refreshCustomMenu);
03916 }
03917
03918 void KWTextFrameSetEdit::insertVariable( KoVariable *var, KoTextFormat *format , bool refreshCustomMenu )
03919 {
03920 if ( var )
03921 {
03922 CustomItemsMap customItemsMap;
03923 customItemsMap.insert( 0, var );
03924 if (!format)
03925 format = currentFormat();
03926 kdDebug() << "KWTextFrameSetEdit::insertVariable inserting into paragraph" << endl;
03927 #ifdef DEBUG_FORMATS
03928 kdDebug() << "KWTextFrameSetEdit::insertVariable format=" << format << endl;
03929 #endif
03930 textObject()->insert( cursor(), format, KoTextObject::customItemChar(),
03931 i18n("Insert Variable"),
03932 KoTextDocument::Standard,
03933 KoTextObject::DoNotRemoveSelected,
03934 customItemsMap );
03935 frameSet()->kWordDocument()->slotRepaintChanged( frameSet() );
03936 if ( var->type()==VT_CUSTOM && refreshCustomMenu)
03937 frameSet()->kWordDocument()->refreshMenuCustomVariable();
03938 }
03939 }
03940
03941 void KWTextFrameSetEdit::insertWPPage()
03942 {
03943 KWTextFrameSet* textfs = textFrameSet();
03944 textfs->clearUndoRedoInfo();
03945 KoTextObject* textobj = textObject();
03946 KWDocument * doc = frameSet()->kWordDocument();
03947 int pages = doc->pageCount();
03948 int columns = doc->numColumns();
03949
03950 int inserted = 0;
03951 KMacroCommand* macroCmd = new KMacroCommand( i18n("Insert Page") );
03952 do {
03953 macroCmd->addCommand( textfs->insertFrameBreakCommand( cursor() ) );
03954 textobj->setLastFormattedParag( cursor()->parag() );
03955 textobj->formatMore( 2 );
03956 } while ( pages == doc->pageCount() && ++inserted <= columns );
03957 if ( pages == doc->pageCount() )
03958 kdWarning(32002) << k_funcinfo << " didn't manage to insert a new page! inserted=" << inserted << " columns=" << columns << " pages=" << pages << endl;
03959
03960 doc->addCommand( macroCmd );
03961
03962 textfs->slotRepaintChanged();
03963 textobj->emitEnsureCursorVisible();
03964 textobj->emitUpdateUI( true );
03965 textobj->emitShowCursor();
03966 }
03967
03968 KoBorder KWTextFrameSetEdit::border(KoBorder::BorderType type) {
03969 if(type == KoBorder::LeftBorder)
03970 return m_paragLayout.leftBorder;
03971 if(type == KoBorder::RightBorder)
03972 return m_paragLayout.rightBorder;
03973 if(type == KoBorder::TopBorder)
03974 return m_paragLayout.topBorder;
03975 return m_paragLayout.bottomBorder;
03976 }
03977
03978
03979 void KWTextFrameSetEdit::updateUI( bool updateFormat, bool force )
03980 {
03981
03982 KoTextView::updateUI( updateFormat, force );
03983
03984
03985 KWTextParag * parag = static_cast<KWTextParag *>(cursor()->parag());
03986
03987 if ( m_paragLayout.alignment != parag->resolveAlignment() || force ) {
03988 m_paragLayout.alignment = parag->resolveAlignment();
03989 m_canvas->gui()->getView()->showAlign( m_paragLayout.alignment );
03990 }
03991
03992
03993 if ( !m_paragLayout.counter )
03994 m_paragLayout.counter = new KoParagCounter;
03995 KoParagCounter::Style cstyle = m_paragLayout.counter->style();
03996 if ( parag->counter() )
03997 *m_paragLayout.counter = *parag->counter();
03998 else
03999 {
04000 m_paragLayout.counter->setNumbering( KoParagCounter::NUM_NONE );
04001 m_paragLayout.counter->setStyle( KoParagCounter::STYLE_NONE );
04002 }
04003 if ( m_paragLayout.counter->style() != cstyle || force )
04004 m_canvas->gui()->getView()->showCounter( * m_paragLayout.counter );
04005
04006 if(m_paragLayout.leftBorder!=parag->leftBorder() ||
04007 m_paragLayout.rightBorder!=parag->rightBorder() ||
04008 m_paragLayout.topBorder!=parag->topBorder() ||
04009 m_paragLayout.bottomBorder!=parag->bottomBorder() || force )
04010 {
04011 m_paragLayout.leftBorder = parag->leftBorder();
04012 m_paragLayout.rightBorder = parag->rightBorder();
04013 m_paragLayout.topBorder = parag->topBorder();
04014 m_paragLayout.bottomBorder = parag->bottomBorder();
04015 m_canvas->gui()->getView()->updateBorderButtons( m_paragLayout.leftBorder, m_paragLayout.rightBorder, m_paragLayout.topBorder, m_paragLayout.bottomBorder );
04016 }
04017
04018 if ( !parag->style() )
04019 kdWarning() << "Paragraph " << parag->paragId() << " has no style" << endl;
04020 else if ( m_paragLayout.style != parag->style() || force )
04021 {
04022 m_paragLayout.style = parag->style();
04023 m_canvas->gui()->getView()->showStyle( m_paragLayout.style->name() );
04024 }
04025
04026 if( m_paragLayout.margins[QStyleSheetItem::MarginLeft] != parag->margin(QStyleSheetItem::MarginLeft)
04027 || m_paragLayout.margins[QStyleSheetItem::MarginFirstLine] != parag->margin(QStyleSheetItem::MarginFirstLine)
04028 || m_paragLayout.margins[QStyleSheetItem::MarginRight] != parag->margin(QStyleSheetItem::MarginRight)
04029 || parag->string()->isRightToLeft() != m_rtl
04030 || force )
04031 {
04032 m_paragLayout.margins[QStyleSheetItem::MarginFirstLine] = parag->margin(QStyleSheetItem::MarginFirstLine);
04033 m_paragLayout.margins[QStyleSheetItem::MarginLeft] = parag->margin(QStyleSheetItem::MarginLeft);
04034 m_paragLayout.margins[QStyleSheetItem::MarginRight] = parag->margin(QStyleSheetItem::MarginRight);
04035 if ( m_rtl != parag->string()->isRightToLeft() && parag->counter() )
04036 {
04037 parag->counter()->invalidate();
04038 parag->setChanged( true );
04039 }
04040 m_rtl = parag->string()->isRightToLeft();
04041 m_canvas->gui()->getView()->showRulerIndent( m_paragLayout.margins[QStyleSheetItem::MarginLeft], m_paragLayout.margins[QStyleSheetItem::MarginFirstLine], m_paragLayout.margins[QStyleSheetItem::MarginRight], m_rtl );
04042 }
04043 if( m_paragLayout.tabList() != parag->tabList() || force)
04044 {
04045 m_paragLayout.setTabList( parag->tabList() );
04046 KoRuler * hr = m_canvas->gui()->getHorzRuler();
04047 if ( hr )
04048 hr->setTabList( parag->tabList() );
04049 }
04050 if( m_paragLayout.lineSpacingType != parag->paragLayout().lineSpacingType || force)
04051 {
04052 m_paragLayout.lineSpacingType = parag->paragLayout().lineSpacingType;
04053 m_canvas->gui()->getView()->showSpacing( m_paragLayout.lineSpacingType );
04054 }
04055
04056
04057
04058 }
04059
04060 void KWTextFrameSetEdit::showFormat( KoTextFormat *format )
04061 {
04062 m_canvas->gui()->getView()->showFormat( *format );
04063 }
04064
04065 QPoint KWTextFrameSet::cursorPos( KoTextCursor *cursor, KWCanvas* canvas, KWFrame* currentFrame )
04066 {
04067 KWViewMode *viewMode = canvas->viewMode();
04068
04069 KoTextParag* parag = cursor->parag();
04070 const QPoint topLeft = parag->rect().topLeft();
04071 int lineY;
04072 parag->lineHeightOfChar( cursor->index(), 0, &lineY );
04073
04074 QPoint iPoint( topLeft.x() + cursor->x() + parag->at( cursor->index() )->width, topLeft.y() + lineY );
04075
04076 KoPoint dPoint;
04077 QPoint vPoint;
04078 KoPoint hintDPoint = currentFrame ? currentFrame->innerRect().topLeft() : KoPoint();
04079 if ( internalToDocumentWithHint( iPoint, dPoint, hintDPoint ) )
04080 {
04081 vPoint = viewMode->normalToView( m_doc->zoomPoint( dPoint ) );
04082 vPoint.rx() -= canvas->contentsX();
04083 vPoint.ry() -= canvas->contentsY();
04084 }
04085 return vPoint;
04086 }
04087
04089
04090 bool KWFootNoteFrameSet::isFootNote() const
04091 {
04092 if ( !m_footNoteVar ) {
04093 kdWarning() << k_funcinfo << " called too early? No footnote var." << endl;
04094 return false;
04095 }
04096 return ( m_footNoteVar->noteType() == FootNote );
04097 }
04098
04099 bool KWFootNoteFrameSet::isEndNote() const
04100 {
04101 if ( !m_footNoteVar ) {
04102 kdWarning() << k_funcinfo << " called too early? No footnote var." << endl;
04103 return false;
04104 }
04105 return ( m_footNoteVar->noteType() == EndNote );
04106 }
04107
04108
04109
04110 void KWFootNoteFrameSet::createInitialFrame( int pageNum )
04111 {
04112 KWFrame *frame = new KWFrame(this, 0, m_doc->pageManager()->topOfPage(pageNum) + 1, 20, 20 );
04113 frame->setFrameBehavior(KWFrame::AutoExtendFrame);
04114 frame->setNewFrameBehavior(KWFrame::NoFollowup);
04115 addFrame( frame );
04116 }
04117
04118 void KWFootNoteFrameSet::startEditing( KWCanvas* canvas )
04119 {
04120 canvas->editFrameSet( this );
04121
04122
04123 KWTextFrameSetEdit *textedit = dynamic_cast<KWTextFrameSetEdit *>(canvas->currentFrameSetEdit()->currentTextEdit());
04124 if ( textedit )
04125 textedit->ensureCursorVisible();
04126 }
04127
04128 void KWFootNoteFrameSet::setFootNoteVariable( KWFootNoteVariable* var )
04129 {
04130 m_footNoteVar = var;
04131 }
04132
04133 void KWFootNoteFrameSet::setCounterText( const QString& text )
04134 {
04135 KoTextParag* parag = textDocument()->firstParag();
04136 Q_ASSERT( parag );
04137 if ( parag ) {
04138 KoParagCounter counter;
04139 counter.setNumbering( KoParagCounter::NUM_FOOTNOTE );
04140 counter.setPrefix( text );
04141 counter.setSuffix( QString::null );
04142 parag->setCounter( counter );
04143 }
04144 }
04145
04146 KWordFrameSetIface* KWFootNoteFrameSet::dcopObject()
04147 {
04148 if ( !m_dcop )
04149 m_dcop = new KWFootNoteFrameSetIface( this );
04150
04151 return m_dcop;
04152 }
04153
04154 #include "KWTextFrameSet.moc"