/* This file is part of the KDE project
Copyright ( C ) 1998 , 1999 , 2000 Reginald Stadlbauer < reggie @ kde . org >
Copyright ( C ) 2001 - 2006 David Faure < faure @ kde . org >
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Library General Public License for more details .
You should have received a copy of the GNU Library General Public License
along with this library ; see the file COPYING . LIB . If not , write to
the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
* Boston , MA 02110 - 1301 , USA .
*/
# include "KWTextFrameSet.h"
# include "KWTableFrameSet.h"
# include "KWDocument.h"
# include "KWView.h"
# include "KWViewMode.h"
# include "KWCanvas.h"
# include "KWAnchor.h"
# include "KWCommand.h"
# include "KWFormulaFrameSet.h"
# include "KWBgSpellCheck.h"
# include "KWordTextFrameSetIface.h"
# include "KWordTextFrameSetEditIface.h"
# include "KWordFootNoteFrameSetIface.h"
# include "KWordFrameSetIface.h"
# include "KWLoadingInfo.h"
# include "KWInsertTOCCommand.h"
# include "KWMailMergeDataBase.h"
# include "KoTextBookmark.h"
# include "KWVariable.h"
# include "KWOasisSaver.h"
# include "KWFrameList.h"
# include "KWPageManager.h"
# include "KWPage.h"
# include <KoParagCounter.h>
# include <KoCustomVariablesDia.h>
# include <KoAutoFormat.h>
# include <KoTextObject.h>
# include <KoTextCommand.h>
# include <KoTextFormatter.h>
# include <KoChangeCaseDia.h>
# include <KoXmlNS.h>
# include <KoXmlWriter.h>
# include <KoOasisContext.h>
# include <KoStore.h>
# include <tdelocale.h>
# include <tdeaction.h>
# include <tdemessagebox.h>
# include <kdebug.h>
# include <tqclipboard.h>
# include <tqdragobject.h>
# include <tqcursor.h>
# include <tqfile.h>
# include <tqprogressdialog.h>
# include <tqregexp.h>
# include <assert.h>
# include <tqapplication.h>
//#define DEBUG_MARGINS
//#define DEBUG_FORMATVERTICALLY
//#define DEBUG_FORMATS
//#define DEBUG_FORMAT_MORE
//#define DEBUG_VIEWAREA
//#define DEBUG_CURSOR
//#define DEBUG_DTI
//#define DEBUG_ITD
/**
* KWord ' s text formatter .
* It derives from KoTextFormatter and simply forwards formatVertically to KWTextFrameSet ,
* since only KWTextFrameSet knows about page - breaking , overlapping frames etc .
*/
class KWTextFormatter : public KoTextFormatter
{
public :
KWTextFormatter ( KWTextFrameSet * textfs ) : m_textfs ( textfs ) { }
virtual ~ KWTextFormatter ( ) { }
virtual int formatVertically ( KoTextDocument * , KoTextParag * parag )
{
return m_textfs - > formatVertically ( parag , parag - > rect ( ) ) ;
}
virtual void postFormat ( KoTextParag * parag )
{
m_textfs - > fixParagWidth ( static_cast < KWTextParag * > ( parag ) ) ;
}
private :
KWTextFrameSet * m_textfs ;
} ;
KWTextFrameSet : : KWTextFrameSet ( KWDocument * _doc , const TQString & name )
: KWFrameSet ( _doc )
{
//kdDebug() << "KWTextFrameSet::KWTextFrameSet " << this << endl;
if ( name . isEmpty ( ) )
m_name = _doc - > generateFramesetName ( i18n ( " Text Frameset %1 " ) ) ;
else
m_name = name ;
TQObject : : setName ( m_name . utf8 ( ) ) ; // store name in the TQObject, for DCOP users
init ( ) ;
}
KWTextFrameSet : : KWTextFrameSet ( KWDocument * doc , const TQDomElement & tag , KoOasisContext & /*context*/ )
: KWFrameSet ( doc )
{
m_name = tag . attributeNS ( KoXmlNS : : draw , " name " , TQString ( ) ) ;
if ( doc - > frameSetByName ( m_name ) ) // already exists!
m_name = doc - > generateFramesetName ( m_name + " %1 " ) ;
init ( ) ;
// Note that we don't call loadOasis here. The caller wants to do it,
// to get the frame it returns.
}
// protected constructor for testing purposes; does not do an init.
KWTextFrameSet : : KWTextFrameSet ( const TQString & name ) : KWFrameSet ( 0 ) {
m_name = name ;
TQObject : : setName ( m_name . utf8 ( ) ) ; // store name in the TQObject, for DCOP users
m_currentViewMode = 0L ;
m_currentDrawnFrame = 0L ;
m_lastTextDocHeight = 0 ;
m_textobj = 0 ;
}
void KWTextFrameSet : : init ( )
{
m_currentViewMode = 0L ;
m_currentDrawnFrame = 0L ;
m_lastTextDocHeight = 0 ;
// Create the text document to set in the text object
KWTextDocument * textdoc = new KWTextDocument ( this ,
new KoTextFormatCollection ( m_doc - > defaultFont ( ) , TQColor ( ) ,
m_doc - > globalLanguage ( ) ,
m_doc - > globalHyphenation ( ) ) ,
new KWTextFormatter ( this ) ) ;
textdoc - > setFlow ( this ) ;
textdoc - > setPageBreakEnabled ( true ) ; // get verticalBreak to be called
if ( m_doc - > tabStopValue ( ) ! = - 1 )
textdoc - > setTabStops ( m_doc - > ptToLayoutUnitPixX ( m_doc - > tabStopValue ( ) ) ) ;
m_textobj = new KoTextObject ( textdoc , m_doc - > styleCollection ( ) - > findStyle ( " Standard " ) ,
this , ( m_name + " -textobj " ) . utf8 ( ) ) ;
m_doc - > backSpeller ( ) - > registerNewTextObject ( m_textobj ) ;
connect ( m_textobj , TQT_SIGNAL ( availableHeightNeeded ( ) ) ,
TQT_SLOT ( slotAvailableHeightNeeded ( ) ) ) ;
connect ( m_textobj , TQT_SIGNAL ( afterFormatting ( int , KoTextParag * , bool * ) ) ,
TQT_SLOT ( slotAfterFormatting ( int , KoTextParag * , bool * ) ) ) ;
//connect( m_textobj, TQT_SIGNAL( formattingFirstParag() ),
// TQT_SLOT( slotFormattingFirstParag() ) );
//connect( m_textobj, TQT_SIGNAL( chapterParagraphFormatted( KoTextParag * ) ),
// TQT_SLOT( slotChapterParagraphFormatted( KoTextParag * ) ) );
connect ( m_textobj , TQT_SIGNAL ( newCommand ( KCommand * ) ) ,
TQT_SLOT ( slotNewCommand ( KCommand * ) ) ) ;
connect ( m_textobj , TQT_SIGNAL ( repaintChanged ( KoTextObject * ) ) ,
TQT_SLOT ( slotRepaintChanged ( ) ) ) ;
connect ( m_textobj , TQT_SIGNAL ( paragraphDeleted ( KoTextParag * ) ) ,
TQT_SLOT ( slotParagraphDeleted ( KoTextParag * ) ) ) ;
connect ( m_textobj , TQT_SIGNAL ( paragraphCreated ( KoTextParag * ) ) ,
TQT_SLOT ( slotParagraphCreated ( KoTextParag * ) ) ) ;
connect ( m_textobj , TQT_SIGNAL ( paragraphModified ( KoTextParag * , int , int , int ) ) ,
TQT_SLOT ( slotParagraphModified ( KoTextParag * , int , int , int ) ) ) ;
}
void KWTextFrameSet : : slotParagraphModified ( KoTextParag * _parag , int /*KoTextParag::ParagModifyType*/ _type , int start , int length )
{
kWordDocument ( ) - > paragraphModified ( _parag , _type , start , length ) ;
}
void KWTextFrameSet : : slotParagraphCreated ( KoTextParag * /*_parag*/ )
{
//todo
}
void KWTextFrameSet : : slotParagraphDeleted ( KoTextParag * _parag )
{
kWordDocument ( ) - > paragraphDeleted ( _parag , this ) ;
}
KWordFrameSetIface * KWTextFrameSet : : dcopObject ( )
{
if ( ! m_dcop )
m_dcop = new KWordTextFrameSetIface ( this ) ;
return m_dcop ;
}
KWFrameSetEdit * KWTextFrameSet : : createFrameSetEdit ( KWCanvas * canvas )
{
return new KWTextFrameSetEdit ( this , canvas ) ;
}
KoTextDocument * KWTextFrameSet : : textDocument ( ) const
{
return m_textobj - > textDocument ( ) ;
}
KWTextDocument * KWTextFrameSet : : kwTextDocument ( ) const
{
return static_cast < KWTextDocument * > ( m_textobj - > textDocument ( ) ) ;
}
void KWTextFrameSet : : slotAvailableHeightNeeded ( )
{
Q_ASSERT ( isVisible ( ) ) ;
kdDebug ( ) < < " KWTextFrameSet::slotAvailableHeightNeeded " < < name ( ) < < endl ;
updateFrames ( 0 ) ; // only do the available-height determination
}
KWFrame * KWTextFrameSet : : documentToInternal ( const KoPoint & dPoint , TQPoint & iPoint ) const
{
# ifdef DEBUG_DTI
kdDebug ( ) < < " KWTextFrameSet::documentToInternal dPoint: " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
# endif
if ( ! m_doc - > layoutViewMode ( ) - > hasFrames ( ) ) { // text viewmode
iPoint = TQPoint ( m_doc - > ptToLayoutUnitPixX ( dPoint . x ( ) ) ,
m_doc - > ptToLayoutUnitPixY ( dPoint . y ( ) ) ) ;
return m_frames . getFirst ( ) ;
}
// Find the frame that contains dPoint. To go fast, we look them up by page number.
int pageNum = m_doc - > pageManager ( ) - > pageNumber ( dPoint ) ;
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( pageNum ) ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
if ( theFrame - > contains ( dPoint ) )
{
iPoint . setX ( m_doc - > ptToLayoutUnitPixX ( dPoint . x ( ) - theFrame - > innerRect ( ) . x ( ) ) ) ;
iPoint . setY ( m_doc - > ptToLayoutUnitPixY ( dPoint . y ( ) - theFrame - > innerRect ( ) . y ( ) + theFrame - > internalY ( ) ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " internalY= " < < theFrame - > internalY ( ) < < " because frame= " < < theFrame
< < " contains dPoint: " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
# endif
return theFrame ;
}
# ifdef DEBUG_DTI
//else
// kdDebug() << "DTI: " << frameRect
// << " doesn't contain nPoint:" << nPoint.x() << "," << nPoint.y() << endl;
# endif
}
// Not found. This means the mouse isn't over any frame, in the page pageNum.
iPoint = m_doc - > ptToLayoutUnitPix ( dPoint ) ; // bah
return 0 ;
}
KWFrame * KWTextFrameSet : : documentToInternalMouseSelection ( const KoPoint & dPoint , TQPoint & iPoint , RelativePosition & relPos , KWViewMode * viewMode ) const
{
# ifdef DEBUG_DTI
kdDebug ( ) < < " KWTextFrameSet::documentToInternalMouseSelection dPoint: " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
# endif
if ( ! viewMode - > hasFrames ( ) ) { // text viewmode
relPos = InsideFrame ;
iPoint = TQPoint ( m_doc - > ptToLayoutUnitPixX ( dPoint . x ( ) ) ,
m_doc - > ptToLayoutUnitPixY ( dPoint . y ( ) ) ) ;
return m_frames . getFirst ( ) ;
}
// Find the frame that contains dPoint. To go fast, we look them up by page number.
int pageNum = m_doc - > pageManager ( ) - > pageNumber ( dPoint ) ;
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( pageNum ) ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
if ( theFrame - > contains ( dPoint ) )
{
iPoint . setX ( m_doc - > ptToLayoutUnitPixX ( dPoint . x ( ) - theFrame - > innerRect ( ) . x ( ) ) ) ;
iPoint . setY ( m_doc - > ptToLayoutUnitPixY ( dPoint . y ( ) - theFrame - > innerRect ( ) . y ( ) + theFrame - > internalY ( ) ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning InsideFrame " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " internalY= " < < theFrame - > internalY ( ) < < " because frame= " < < theFrame
< < " contains dPoint: " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
# endif
relPos = InsideFrame ;
return theFrame ;
}
}
frameIt . toFirst ( ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
KoRect openLeftRect ( theFrame - > innerRect ( ) ) ;
openLeftRect . setLeft ( theFrame - > paddingLeft ( ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: openLeftRect= " < < openLeftRect < < endl ;
# endif
if ( openLeftRect . contains ( dPoint ) )
{
// We are at the left of this frame (and not in any other frame of this frameset)
iPoint . setX ( m_doc - > ptToLayoutUnitPixX ( theFrame - > innerRect ( ) . left ( ) ) ) ;
iPoint . setY ( m_doc - > ptToLayoutUnitPixY ( dPoint . y ( ) - theFrame - > top ( ) + theFrame - > internalY ( ) ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning LeftOfFrame " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " internalY= " < < theFrame - > internalY ( ) < < " because openLeftRect= " < < openLeftRect
< < " contains dPoint: " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
# endif
relPos = LeftOfFrame ;
return theFrame ;
}
KoRect openTopRect ( KoPoint ( 0 , 0 ) , theFrame - > innerRect ( ) . bottomRight ( ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: openTopRect= " < < openTopRect < < endl ;
# endif
if ( openTopRect . contains ( dPoint ) )
{
// We are at the top of this frame (...)
iPoint . setX ( m_doc - > ptToLayoutUnitPixX ( dPoint . x ( ) - theFrame - > innerRect ( ) . left ( ) ) ) ;
iPoint . setY ( m_doc - > ptToLayoutUnitPixY ( theFrame - > internalY ( ) ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " internalY= " < < theFrame - > internalY ( ) < < " because openTopRect= " < < openTopRect
< < " contains dPoint: " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
# endif
relPos = TopOfFrame ;
return theFrame ;
}
}
// Not found. This means we are under (or at the right of), the frames in pageNum.
// In that case, go for the first frame in the next page.
if ( pageNum + 1 > = ( int ) m_framesInPage . size ( ) + m_firstPage )
{
// Under last frame of last page!
KWFrame * theFrame = m_frames . getLast ( ) ;
iPoint . setX ( m_doc - > ptToLayoutUnitPixX ( theFrame - > innerWidth ( ) ) ) ;
iPoint . setY ( m_doc - > ptToLayoutUnitPixY ( theFrame - > innerHeight ( ) ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning AtEnd " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " because we are under all frames of the last page " < < endl ;
# endif
relPos = AtEnd ;
return theFrame ;
}
else
{
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( pageNum + 1 ) ) ;
if ( frameIt . current ( ) )
{
// There is a frame on the next page
KWFrame * theFrame = frameIt . current ( ) ;
KoRect openTopRect ( theFrame - > innerRect ( ) ) ;
openTopRect . setTop ( 0 ) ;
if ( openTopRect . contains ( dPoint ) ) // We are at the top of this frame
iPoint . setX ( m_doc - > ptToLayoutUnitPixX ( dPoint . x ( ) - theFrame - > left ( ) ) ) ;
else
iPoint . setX ( 0 ) ; // We are, hmm, on the left or right of the frames
iPoint . setY ( m_doc - > ptToLayoutUnitPixY ( theFrame - > internalY ( ) ) ) ;
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning TopOfFrame " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " because we are under all frames of page " < < pageNum < < endl ;
# endif
relPos = TopOfFrame ;
return theFrame ;
} // else there is a gap (no frames on that page, but on some other further down)
// This case isn't handled (and should be VERY rare I think)
}
iPoint = m_doc - > ptToLayoutUnitPix ( dPoint ) ; // bah
# ifdef DEBUG_DTI
kdDebug ( ) < < " documentToInternal: returning not found for " < < iPoint . x ( ) < < " , " < < iPoint . y ( ) < < endl ;
# endif
return 0 ;
}
KWFrame * KWTextFrameSet : : internalToDocumentWithHint ( const TQPoint & iPoint , KoPoint & dPoint , const KoPoint & hintDPoint ) const
{
# ifdef DEBUG_ITD
kdDebug ( ) < < " KWTextFrameSet::internalToDocumentWithHint hintDPoint: " < < hintDPoint . x ( ) < < " , " < < hintDPoint . y ( ) < < endl ;
# endif
if ( ! m_doc - > layoutViewMode ( ) - > hasFrames ( ) ) { // text viewmode
dPoint = m_doc - > layoutUnitPtToPt ( m_doc - > pixelToPt ( iPoint ) ) ;
return m_frames . getFirst ( ) ;
}
KWFrame * lastFrame = 0L ;
TQPtrListIterator < KWFrame > frameIt ( frameIterator ( ) ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
TQRect r ( 0 , m_doc - > ptToLayoutUnitPixY ( theFrame - > internalY ( ) ) , m_doc - > ptToLayoutUnitPixX ( theFrame - > innerWidth ( ) ) + 1 , m_doc - > ptToLayoutUnitPixY ( theFrame - > innerHeight ( ) ) + 1 ) ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: r= " < < r < < " iPoint= " < < iPoint . x ( ) < < " , " < < iPoint . y ( ) < < endl ;
# endif
// r is the frame in qrt coords
if ( r . contains ( iPoint ) ) // both r and p are in layout units (aka internal)
{
dPoint = internalToDocumentKnowingFrame ( iPoint , theFrame ) ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " copy: " < < theFrame - > isCopy ( ) < < " hintDPoint.y()= " < < hintDPoint . y ( ) < < " dPoint.y()= " < < dPoint . y ( ) < < endl ;
# endif
// First test: No "hintDPoint" specified, go for the first match
// Second test: hintDPoint specified, check if we are far enough
if ( hintDPoint . isNull ( ) | | hintDPoint . y ( ) < = dPoint . y ( ) )
return theFrame ;
// Remember that this frame matched, in case we find no further frame that matches
lastFrame = theFrame ;
}
else if ( lastFrame )
{
return lastFrame ;
}
}
// This happens when the parag is on a not-yet-created page (formatMore will notice afterwards)
// So it doesn't matter much what happens here, we'll redo it anyway.
# ifdef DEBUG_ITD
kdDebug ( 32002 ) < < " KWTextFrameSet::internalToDocumentWithHint " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " not in any frame of " < < ( void * ) this < < endl ;
# endif
dPoint = m_doc - > layoutUnitPtToPt ( m_doc - > pixelToPt ( iPoint ) ) ; // bah
return 0L ;
}
// relPoint is in relative coordinates (pt)
KoPoint KWTextFrameSet : : internalToDocumentKnowingFrame ( const KoPoint & relPoint , KWFrame * theFrame ) const
{
// It's ok to have theFrame == 0 in the text viewmode, but not in other modes
if ( m_doc - > layoutViewMode ( ) - > hasFrames ( ) )
Q_ASSERT ( theFrame ) ;
if ( theFrame )
return KoPoint ( relPoint . x ( ) + theFrame - > innerRect ( ) . x ( ) ,
relPoint . y ( ) - theFrame - > internalY ( ) + theFrame - > innerRect ( ) . y ( ) ) ;
else
return relPoint ;
}
KoPoint KWTextFrameSet : : internalToDocumentKnowingFrame ( const TQPoint & iPoint , KWFrame * theFrame ) const
{
// Convert LU to relative coordinates (pt), then call the real internalToDocumentKnowingFrame().
return internalToDocumentKnowingFrame ( m_doc - > layoutUnitPtToPt ( m_doc - > pixelToPt ( iPoint ) ) , theFrame ) ;
}
TQPoint KWTextFrameSet : : moveToPage ( int currentPgNum , short int direction ) const
{
if ( ! isVisible ( ) | | m_frames . isEmpty ( ) )
return TQPoint ( ) ;
//kdDebug() << "KWTextFrameSet::moveToPage currentPgNum=" << currentPgNum << " direction=" << direction << endl;
int num = currentPgNum + direction ;
int pages = m_doc - > pageCount ( ) ;
for ( ; num > = 0 & & num < pages ; num + = direction )
{
//kdDebug() << "KWTextFrameSet::moveToPage num=" << num << " pages=" << pages << endl;
// Find the first frame on page num
if ( num < m_firstPage | | num > = ( int ) m_framesInPage . size ( ) + m_firstPage )
continue ; // No frame on that page
//kdDebug() << "KWTextFrameSet::moveToPage ok for first frame in page " << num << endl;
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( num ) ) ;
return TQPoint ( 0 , m_doc - > ptToLayoutUnitPixY ( frameIt . current ( ) - > internalY ( ) ) + 2 ) ; // found, ok.
}
// Not found. Go to top of first frame or bottom of last frame, depending on direction
if ( direction < 0 )
return TQPoint ( 0 , m_doc - > ptToLayoutUnitPixY ( m_frames . getFirst ( ) - > internalY ( ) ) + 2 ) ;
else
{
KWFrame * theFrame = m_frames . getLast ( ) ;
return TQPoint ( 0 , m_doc - > ptToLayoutUnitPixY ( theFrame - > internalY ( ) + theFrame - > innerHeight ( ) ) ) ;
}
}
void KWTextFrameSet : : drawContents ( TQPainter * p , const TQRect & crect , const TQColorGroup & cg ,
bool onlyChanged , bool resetChanged ,
KWFrameSetEdit * edit , KWViewMode * viewMode ,
KWFrameViewManager * fvm )
{
m_currentViewMode = viewMode ;
KWFrameSet : : drawContents ( p , crect , cg , onlyChanged , resetChanged , edit , viewMode , fvm ) ;
// Main textframeset: draw the footnote line if there are footnotes
if ( isMainFrameset ( ) & & viewMode - > hasFrames ( ) )
{
// We stored the info "there's a footnote in this page" in the frame[s]
// of the maintextframeset for that page. Usually one, but could be more
// if there are columns. However we want to draw the line only once, so we
// do it here and not in drawFrame (we'd have problems with cliprect anyway).
if ( m_doc - > footNoteSeparatorLineWidth ( ) = = 0.0 )
return ;
int pages = m_doc - > pageCount ( ) ;
KWPage * page = m_doc - > pageManager ( ) - > page ( m_doc - > pageManager ( ) - > startPage ( ) ) ;
double left = page - > leftMargin ( ) ;
double pageWidth = page - > width ( ) - page - > rightMargin ( ) - left ;
double width = pageWidth * m_doc - > footNoteSeparatorLineLength ( ) / 100.0 ;
int numColumns = m_doc - > numColumns ( ) ;
for ( int pageNum = 0 ; pageNum < pages ; pageNum + + )
{
//if ( viewMode->isPageVisible( pageNum ) )
{
uint frameNum = pageNum * numColumns /*+ col 0 here*/ ;
if ( frameNum < frameCount ( ) ) // not true on the "endnotes-only" page
{
KWFrame * frame = this - > frame ( frameNum ) ; // ## or use framesInPage ?
//kdDebug() << " Footnote line: page " << pageNum << " found frame " << frameNum << " drawFootNoteLine=" << frame->drawFootNoteLine() << endl;
if ( frame - > drawFootNoteLine ( ) )
{
double y = frame - > bottomLeft ( ) . y ( ) + m_doc - > headerFooterInfo ( ) . ptFootNoteBodySpacing / 2 ;
KoRect rect ( left , y , width , 0 ) ; // this rect is flat
switch ( m_doc - > footNoteSeparatorLinePosition ( ) )
{
case SLP_LEFT :
break ;
case SLP_CENTERED :
rect = KoRect ( pageWidth / 2.0 + left - width / 2.0 , y , width , 0 ) ;
break ;
case SLP_RIGHT :
rect = KoRect ( pageWidth + left - width , y , width , 0 ) ;
break ;
}
TQRect flatRect = viewMode - > normalToView ( m_doc - > zoomRect ( rect ) ) ;
//kdDebug() << " KWTextFrameSet::drawContents rect=" << rect << " zoomed:" << flatRect << endl;
flatRect . setBottom ( flatRect . top ( ) + 1 ) ; // #!@!@!& TQRect....
if ( flatRect . intersects ( crect ) ) {
p - > save ( ) ;
TQPen pen ( KoTextFormat : : defaultTextColor ( p ) , // always in default fg color (and black when printing)
KoBorder : : zoomWidthY ( m_doc - > footNoteSeparatorLineWidth ( ) , m_doc , 1 ) ) ; // penwidth = zoomIt( 2 pt )
switch ( m_doc - > footNoteSeparatorLineType ( ) )
{
case SLT_SOLID :
pen . setStyle ( Qt : : SolidLine ) ;
break ;
case SLT_DASH :
pen . setStyle ( Qt : : DashLine ) ;
break ;
case SLT_DOT :
pen . setStyle ( Qt : : DotLine ) ;
break ;
case SLT_DASH_DOT :
pen . setStyle ( Qt : : DashDotLine ) ;
break ;
case SLT_DASH_DOT_DOT :
pen . setStyle ( Qt : : DashDotDotLine ) ;
break ;
}
p - > setPen ( pen ) ;
p - > drawLine ( flatRect . left ( ) , flatRect . top ( ) , flatRect . right ( ) , flatRect . top ( ) ) ;
//kdDebug() << " drawLine( " << flatRect.left() << ", " << flatRect.top() << ", " << flatRect.right() << ", " << flatRect.top() << endl;
p - > restore ( ) ;
}
}
}
}
}
}
}
void KWTextFrameSet : : drawFrame ( KWFrame * theFrame , TQPainter * painter , const TQRect & fcrect , const TQRect & crect ,
const TQPoint & translationOffset ,
KWFrame * settingsFrame , const TQColorGroup & cg , bool onlyChanged , bool resetChanged ,
KWFrameSetEdit * edit , KWViewMode * viewMode , bool drawUnderlyingFrames )
{
// Detect if text frame needs transparency painting, to save time if it's using SolidPattern
// In theory this code should be in kwFrameSet, but currently only text frames obey m_backgroundColor.
if ( theFrame )
{
drawUnderlyingFrames & = theFrame - > isTransparent ( ) ;
}
KWFrameSet : : drawFrame ( theFrame , painter , fcrect , crect , translationOffset , settingsFrame , cg , onlyChanged , resetChanged , edit , viewMode , drawUnderlyingFrames ) ;
}
void KWTextFrameSet : : drawFrameContents ( KWFrame * theFrame , TQPainter * painter , const TQRect & r ,
const TQColorGroup & cg , bool onlyChanged , bool resetChanged ,
KWFrameSetEdit * edit , KWViewMode * viewMode )
{
Q_ASSERT ( r . isValid ( ) ) ;
// In this method the painter is translated to the frame's coordinate system
// (in the first frame (0,0) will be its topleft, in the second frame it will be (0,internalY) etc.
//kdDebug(32001) << "KWTextFrameSet::drawFrameContents " << name() << "(frame " << frameFromPtr( theFrame ) << ") crect(r)=" << r << " onlyChanged=" << onlyChanged << endl;
m_currentDrawnFrame = theFrame ;
if ( theFrame ) // 0L in the text viewmode
{
// Update variables for each frame (e.g. for page-number)
// If more than KWPgNumVariable need this functionality, create an intermediary base class
TQPtrListIterator < KoTextCustomItem > cit ( textDocument ( ) - > allCustomItems ( ) ) ;
for ( ; cit . current ( ) ; + + cit )
{
KWPgNumVariable * var = dynamic_cast < KWPgNumVariable * > ( cit . current ( ) ) ;
if ( var & & ! var - > isDeleted ( ) )
{
TQSize oldSize ( var - > width , var - > height ) ;
const int pageNumberOffset = kWordDocument ( ) - > variableCollection ( ) - > variableSetting ( ) - > startingPageNumber ( ) - 1 ;
switch ( var - > subType ( ) )
{
case KWPgNumVariable : : VST_PGNUM_CURRENT :
//kdDebug() << "KWTextFrameSet::drawFrame updating pgnum variable to " << theFrame->pageNumber()
// << " and invalidating parag " << var->paragraph() << endl;
var - > setPgNum ( theFrame - > pageNumber ( ) + pageNumberOffset ) ;
break ;
case KWPgNumVariable : : VST_CURRENT_SECTION :
var - > setSectionTitle ( kWordDocument ( ) - > sectionTitle ( theFrame - > pageNumber ( ) ) ) ;
break ;
case KWPgNumVariable : : VST_PGNUM_PREVIOUS :
var - > setPgNum ( TQMAX ( theFrame - > pageNumber ( ) - 1 , 0 ) + pageNumberOffset ) ;
break ;
case KWPgNumVariable : : VST_PGNUM_NEXT :
var - > setPgNum ( theFrame - > pageNumber ( ) + 1 + pageNumberOffset ) ;
break ;
}
var - > resize ( ) ;
TQSize newSize ( var - > width , var - > height ) ;
if ( oldSize ! = newSize )
var - > paragraph ( ) - > invalidate ( 0 ) ; // size has changed -> need reformatting !
var - > paragraph ( ) - > setChanged ( true ) ;
}
}
}
KoTextCursor * cursor = edit ? ( dynamic_cast < KWTextFrameSetEdit * > ( edit ) ? static_cast < KWTextFrameSetEdit * > ( edit ) - > cursor ( ) : 0 ) : 0 ;
uint drawingFlags = 0 ;
if ( viewMode - > drawSelections ( ) )
drawingFlags | = KoTextDocument : : DrawSelections ;
if ( ! viewMode - > drawFrameBackground ( ) )
drawingFlags | = KoTextDocument : : TransparentBackground ;
if ( m_doc - > backgroundSpellCheckEnabled ( ) )
drawingFlags | = KoTextDocument : : DrawMisspelledLine ;
if ( m_doc - > viewFormattingChars ( ) )
drawingFlags | = KoTextDocument : : DrawFormattingChars ;
//kdDebug(32001) << "KWTextFrameSet::drawFrame calling drawWYSIWYG. cg base color:" << cg.brush( TQColorGroup::Base) << endl;
KoTextParag * lastFormatted = textDocument ( ) - > drawWYSIWYG (
painter , r . x ( ) , r . y ( ) , r . width ( ) , r . height ( ) ,
cg , kWordDocument ( ) ,
onlyChanged , false , cursor , resetChanged , drawingFlags ) ;
// The last paragraph of this frame might have a bit in the next frame too.
// In that case, and if we're only drawing changed paragraphs, (and resetting changed),
// we have to set changed to true again, to draw the bottom of the parag in the next frame.
if ( onlyChanged & & resetChanged )
{
// Finding the "last parag of the frame" is a bit tricky.
// It's usually the one before lastFormatted, except if it's actually lastParag :} [see KoTextDocument::draw]
KoTextParag * lastDrawn = lastFormatted - > prev ( ) ;
if ( lastFormatted = = textDocument ( ) - > lastParag ( ) & & ( ! lastDrawn | | m_doc - > layoutUnitToPixelY ( lastDrawn - > rect ( ) . bottom ( ) ) < r . bottom ( ) ) )
lastDrawn = lastFormatted ;
//kdDebug(32002) << "KWTextFrameSet::drawFrame drawn. onlyChanged=" << onlyChanged << " resetChanged=" << resetChanged << " lastDrawn=" << lastDrawn->paragId() << " lastDrawn's bottom:" << lastDrawn->rect().bottom() << " r.bottom=" << r.bottom() << endl;
if ( lastDrawn & & m_doc - > layoutUnitToPixelY ( lastDrawn - > rect ( ) . bottom ( ) ) > r . bottom ( ) )
{
//kdDebug(32002) << "KWTextFrameSet::drawFrame setting lastDrawn " << lastDrawn->paragId() << " to changed" << endl;
lastDrawn - > setChanged ( true ) ;
}
}
// NOTE: TQTextView sets m_lastFormatted to lastFormatted here
// But when scrolling up, this causes to reformat a lot of stuff for nothing.
// And updateViewArea takes care of formatting things before we even arrive here.
// Blank area under the very last paragraph - TQRT draws it up to textdoc->height,
// we have to draw it from there up to the bottom of the last frame.
if ( ( ! lastFormatted | | lastFormatted = = textDocument ( ) - > lastParag ( ) )
& & viewMode - > drawFrameBackground ( ) )
{
// This is drawing code, so we convert everything to pixels
int docHeight = textDocument ( ) - > lastParag ( ) - > pixelRect ( m_doc ) . bottom ( ) + 1 ;
//TQRect frameRect = m_doc->zoomRect( (theFrame->innerRect()) );
TQSize availSize = viewMode - > availableSizeForText ( this ) ;
TQRect blank ( 0 , docHeight , availSize . width ( ) , availSize . height ( ) /*+ frameRect.height() ?? */ - docHeight ) ;
//kdDebug(32002) << this << " Blank area: " << blank << endl;
painter - > fillRect ( blank , cg . brush ( TQColorGroup : : Base ) ) ;
// for debugging :)
//painter->setPen( TQPen(TQt::blue, 1, DashLine) ); painter->drawRect( blank );
}
m_currentDrawnFrame = 0L ;
}
void KWTextFrameSet : : drawCursor ( TQPainter * p , KoTextCursor * cursor , bool cursorVisible , KWCanvas * canvas , KWFrame * theFrame )
{
// This redraws the paragraph where the cursor is - with a small clip region around the cursor
m_currentViewMode = canvas - > viewMode ( ) ;
bool hasFrames = m_currentViewMode - > hasFrames ( ) ;
m_currentDrawnFrame = theFrame ;
TQRect normalFrameRect ;
if ( hasFrames )
normalFrameRect = m_doc - > zoomRect ( theFrame - > innerRect ( ) ) ;
else
normalFrameRect = TQRect ( TQPoint ( 0 , 0 ) , m_currentViewMode - > contentsSize ( ) ) ;
KoTextParag * parag = cursor - > parag ( ) ;
TQPoint topLeft = parag - > rect ( ) . topLeft ( ) ; // in TQRT coords
int lineY ;
// Cursor height, in pixels
int cursorHeight = m_doc - > layoutUnitToPixelY ( topLeft . y ( ) , parag - > lineHeightOfChar ( cursor - > index ( ) , 0 , & lineY ) ) ;
TQPoint iPoint ( topLeft . x ( ) + cursor - > x ( ) ,
topLeft . y ( ) + lineY ) ;
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " KWTextFrameSet::drawCursor topLeft= " < < topLeft . x ( ) < < " , " < < topLeft . y ( )
< < " x= " < < cursor - > x ( ) < < " y= " < < lineY < < endl ;
kdDebug ( ) < < " KWTextFrameSet::drawCursor iPoint= " < < iPoint . x ( ) < < " , " < < iPoint . y ( )
< < " cursorHeight= " < < cursorHeight < < endl ;
# endif
KoPoint dPoint ;
KoPoint hintDPoint = theFrame ? theFrame - > innerRect ( ) . topLeft ( ) : KoPoint ( ) ;
if ( internalToDocumentWithHint ( iPoint , dPoint , hintDPoint ) )
{
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " dPoint(doc, pts)= " < < dPoint . x ( ) < < " , " < < dPoint . y ( ) < < endl ;
TQPoint debugPt = m_doc - > zoomPoint ( dPoint ) ;
kdDebug ( ) < < " zoomed dPoint(doc, pixels)= " < < debugPt . x ( ) < < " , " < < debugPt . y ( ) < < endl ;
# endif
TQPoint vPoint = m_currentViewMode - > normalToView ( m_doc - > zoomPoint ( dPoint ) ) ; // from doc to view contents
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " vPoint(view, pixels)= " < < vPoint . x ( ) < < " , " < < vPoint . y ( ) < < endl ;
# endif
// from now on, iPoint will be in pixels
iPoint = m_doc - > layoutUnitToPixel ( iPoint ) ;
//int xadj = parag->at( cursor->index() )->pixelxadj;
# ifdef DEBUG_CURSOR
//kdDebug() << " iPoint in pixels : " << iPoint.x() << "," << iPoint.y() << " will add xadj=" << xadj << endl;
# endif
//iPoint.rx() += xadj;
//vPoint.rx() += xadj;
// very small clipping around the cursor
TQRect clip ( vPoint . x ( ) - 5 , vPoint . y ( ) , 10 , cursorHeight ) ;
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " clip(view, before intersect)= " < < clip < < endl ;
# endif
TQRect viewFrameRect = m_currentViewMode - > normalToView ( normalFrameRect ) ;
clip & = viewFrameRect ; // clip to frame
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " KWTextFrameSet::drawCursor normalFrameRect= " < < normalFrameRect
< < " clip(view, after intersect)= " < < clip < < endl ;
# endif
TQRegion reg ;
if ( hasFrames ) {
reg = frameClipRegion ( p , theFrame , clip , m_currentViewMode ) ;
if ( ! isFloating ( ) ) // problem with multiparent inline frames
reg & = p - > xForm ( viewFrameRect ) ;
}
if ( ! hasFrames | | ! reg . isEmpty ( ) )
{
# ifdef DEBUG_CURSOR
// for debug only!
//p->fillRect( clip, TQBrush( TQt::red, TQBrush::Dense3Pattern ) );
# endif
p - > save ( ) ;
TQColorGroup cg = TQApplication : : palette ( ) . active ( ) ;
if ( hasFrames )
{
p - > setClipRegion ( reg ) ;
// translate to qrt coords - after setting the clip region !
// see internalToDocumentWithHint
int translationX = viewFrameRect . left ( ) ;
int translationY = viewFrameRect . top ( ) - m_doc - > zoomItY ( theFrame - > internalY ( ) ) ;
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " translating Y by viewFrameRect.top()-internalY in pixelY= " < < viewFrameRect . top ( ) < < " - " < < m_doc - > zoomItY ( theFrame - > internalY ( ) ) < < " = " < < viewFrameRect . top ( ) - m_doc - > zoomItY ( theFrame - > internalY ( ) ) < < endl ;
# endif
p - > translate ( translationX , translationY ) ;
p - > setBrushOrigin ( p - > brushOrigin ( ) . x ( ) + translationX , p - > brushOrigin ( ) . y ( ) + translationY ) ;
// The settings come from this frame
KWFrame * settings = settingsFrame ( theFrame ) ;
TQBrush bgBrush ( settings - > backgroundColor ( ) ) ;
bgBrush . setColor ( KWDocument : : resolveBgColor ( bgBrush . color ( ) , p ) ) ;
cg . setBrush ( TQColorGroup : : Base , bgBrush ) ;
// color of cursor, the inverse of the frame background
TQColor background = bgBrush . color ( ) ;
cg . setColor ( TQColorGroup : : Text , TQColor ( 255 - background . red ( ) ,
255 - background . green ( ) , 255 - background . blue ( ) ) ) ;
}
else if ( dynamic_cast < KWViewModeText * > ( m_currentViewMode ) ! = 0 )
p - > translate ( KWViewModeText : : OFFSET , 0 ) ;
TQPixmap * pix = 0 ;
uint drawingFlags = KoTextDocument : : DrawSelections ;
if ( m_doc - > backgroundSpellCheckEnabled ( ) )
drawingFlags | = KoTextDocument : : DrawMisspelledLine ;
if ( m_doc - > viewFormattingChars ( ) )
drawingFlags | = KoTextDocument : : DrawFormattingChars ;
// To force the drawing to happen:
bool wasChanged = parag - > hasChanged ( ) ;
int oldLineChanged = parag - > lineChanged ( ) ;
int line ; // line number
parag - > lineStartOfChar ( cursor - > index ( ) , 0 , & line ) ;
parag - > setChanged ( false ) ; // not all changed, only from a given line
parag - > setLineChanged ( line ) ;
textDocument ( ) - > drawParagWYSIWYG (
p , parag ,
TQMAX ( 0 , iPoint . x ( ) - 5 ) , // negative values create problems
iPoint . y ( ) , clip . width ( ) , clip . height ( ) ,
pix , cg , m_doc , // TODO view's zoom handler
cursorVisible , cursor , FALSE /*resetChanged*/ , drawingFlags ) ;
if ( wasChanged ) // Maybe we have more changes to draw, than those in the small cliprect
parag - > setLineChanged ( oldLineChanged ) ; // -1 = all
else
parag - > setChanged ( false ) ;
p - > restore ( ) ;
//XIM Position
TQPoint ximPoint = vPoint ;
canvas - > setXimPosition ( ximPoint . x ( ) , ximPoint . y ( ) ,
0 , cursorHeight - parag - > lineSpacing ( line ) ) ;
}
}
m_currentDrawnFrame = 0L ;
}
void KWTextFrameSet : : layout ( )
{
invalidate ( ) ;
// Get the thing going though, repainting doesn't call formatMore
m_textobj - > formatMore ( 2 ) ;
}
void KWTextFrameSet : : invalidate ( )
{
//kdDebug() << "KWTextFrameSet::invalidate " << name() << endl;
m_textobj - > setLastFormattedParag ( textDocument ( ) - > firstParag ( ) ) ;
textDocument ( ) - > invalidate ( ) ; // lazy layout, real update follows upon next repaint
}
void KWTextFrameSet : : slotRepaintChanged ( )
{
emit repaintChanged ( this ) ;
}
int KWTextFrameSet : : paragraphs ( )
{
int paragraphs = 0 ;
KoTextParag * parag = textDocument ( ) - > firstParag ( ) ;
for ( ; parag ; parag = parag - > next ( ) )
paragraphs + + ;
return paragraphs ;
}
int KWTextFrameSet : : paragraphsSelected ( )
{
int paragraphs = 0 ;
KoTextParag * parag = textDocument ( ) - > firstParag ( ) ;
for ( ; parag ; parag = parag - > next ( ) ) {
if ( parag - > hasSelection ( KoTextDocument : : Standard ) )
paragraphs + + ;
}
return paragraphs ;
}
bool KWTextFrameSet : : statistics ( TQProgressDialog * progress , ulong & charsWithSpace , ulong & charsWithoutSpace , ulong & words ,
ulong & sentences , ulong & syllables , ulong & lines , bool selected )
{
return m_textobj - > statistics ( progress , charsWithSpace , charsWithoutSpace , words , sentences , syllables , lines , selected ) ;
}
// Only interested in the body textframeset, not in header/footer
# define kdDebugBody(area) if ( frameSetInfo() == FI_BODY ) kdDebug(area)
TQValueList < KWFrame * > KWTextFrameSet : : framesFromTo ( int y1 , int y2 ) const
{
TQValueList < KWFrame * > framesList ;
KoPoint pt ;
KWFrame * firstFrame = internalToDocument ( TQPoint ( 0 , y1 ) , pt ) ;
if ( ! firstFrame )
return framesList ;
framesList . append ( firstFrame ) ;
uint frameIndex = const_cast < KWTextFrameSet * > ( this ) - > m_frames . findRef ( firstFrame ) ;
while ( + + frameIndex < m_frames . count ( ) ) {
KWFrame * f = frame ( frameIndex ) ;
if ( f - > internalY ( ) > y2 ) // too far down, we're done
break ;
framesList . append ( f ) ;
}
return framesList ;
}
// Helper for adjust*. There are 3 ways to use this method.
// 1) marginLeft and marginRight set -> determination of left and right margins for adjustMargins
// 2) marginRight set -> determination of right margin for adjustRMargin
// 3) breakBegin, breakEnd set -> check whether we should jump over some frames
// [when there is not enough space besides them]
// reqMinWidth is the width that the formatter wants to use (current char/item)
// validHeight is set to the height where marginLeft/marginRight applies (TODO)
void KWTextFrameSet : : getMargins ( int yp , int h , int reqMinWidth ,
int * marginLeft , int * marginRight , int * pageWidth ,
int * validHeight ,
int * breakBegin , int * breakEnd , KoTextParag * parag )
{
// paragLeftMargin will be used as the minimum width needed for the parag,
// to "see" the parag.
// So we only apply the first line margin if it increases that width, i.e. if > 0.
// Otherwise only the first line might be visible, in a narrow passage.
int paragLeftMargin = parag ? parag - > leftMargin ( ) : 0 ;
if ( parag & & ! parag - > string ( ) - > isRightToLeft ( ) & & parag - > firstLineMargin ( ) > 0 )
paragLeftMargin + = parag - > firstLineMargin ( ) ;
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " KWTextFrameSet " < < this < < " ( " < < name ( ) < < " ) getMargins yp= " < < yp
< < " h= " < < h < < " called by "
< < ( marginLeft & & marginRight ? " adjustMargins " : " formatVertically " )
< < " paragLeftMargin= " < < paragLeftMargin
< < endl ;
// Both or none...
if ( breakBegin ) assert ( breakEnd ) ;
if ( breakEnd ) assert ( breakBegin ) ;
// Idem
if ( marginLeft ) { assert ( marginRight ) ; assert ( pageWidth ) ; }
# endif
// List of text frames holding the paragraph (yp,yp+h)
// Usually there is only one, but you can have a paragraph
// starting in one frame/column and ending in another one.
TQValueList < KWFrame * > textFrames = framesFromTo ( yp , yp + h ) ;
if ( textFrames . isEmpty ( ) )
{
# ifdef DEBUG_MARGINS
kdDebug ( 32002 ) < < " getMargins: internalToDocument returned no text frames for y1= " < < yp < < " y2= " < < yp + h < < " ->aborting with 0 margins " < < endl ;
# endif
// frame == 0 happens when the parag is under the last frame.
// On an auto-resizable frame, we know the frame will grow so we can go ahead
// and use its width.
if ( ! m_frames . isEmpty ( ) & & m_frames . last ( ) - > frameBehavior ( ) = = KWFrame : : AutoExtendFrame )
{
textFrames . append ( m_frames . last ( ) ) ;
}
else
{
// On auto-create-new-frame, this means the parag is on a not-yet-created page
// (formatMore will notice afterwards)
// Abort then, no need to return precise values
// We also abort in the third case (Ignore)
if ( validHeight )
* validHeight = 0 ;
return ;
}
}
else
{
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins: internalToDocument returned " < < textFrames . count ( ) < < " frames holding this paragraph " < < endl ;
# endif
}
if ( validHeight )
* validHeight = h ; // TODO
// Everything from there is in layout units
// Note: it is very important that this method works in internal coordinates.
// Otherwise, parags broken at the line-level (e.g. between two columns) are seen
// as still in one piece, and we miss the frames in the 2nd column.
int from = 0 ;
// TODO support for variable width... maybe it's enough to take the max here
int to = m_doc - > ptToLayoutUnitPixX ( textFrames . first ( ) - > innerWidth ( ) ) ;
if ( pageWidth )
* pageWidth = to ;
bool init = false ;
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins: looking for frames between " < < yp < < " and " < < yp + h < < " (internal coords) " < < endl ;
# endif
if ( m_doc - > layoutViewMode ( ) - > shouldAdjustMargins ( ) )
{
// Principle: for every frame on top at this height, we'll move from and to
// towards each other. The text flows between 'from' and 'to'
for ( TQValueList < KWFrame * > : : const_iterator txtit = textFrames . begin ( ) , txtend = textFrames . end ( ) ; txtit ! = txtend ; + + txtit ) {
KWFrame * theFrame = * txtit ;
Q_ASSERT ( theFrame - > frameStack ( ) ) ;
TQValueList < KWFrame * > onTop = theFrame - > frameStack ( ) - > framesOnTop ( ) ;
for ( TQValueListIterator < KWFrame * > fIt = onTop . begin ( ) ; from < to & & fIt ! = onTop . end ( ) ; + + fIt )
{
if ( ( * fIt ) - > runAround ( ) = = KWFrame : : RA_BOUNDINGRECT )
{
KoRect rectOnTop = theFrame - > intersect ( ( * fIt ) - > runAroundRect ( ) ) ;
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins found frame on top " < < ( * fIt ) - > frameSet ( ) - > name ( ) < < " with rect-on-top at (normal coords) " < < rectOnTop < < endl ;
# endif
TQPoint iTop , iBottom ; // top and bottom of intersection in internal coordinates
if ( documentToInternal ( rectOnTop . topLeft ( ) , iTop ) & &
iTop . y ( ) < = yp + h & & // optimization
documentToInternal ( rectOnTop . bottomRight ( ) , iBottom ) )
{
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " in internal coords: " < < TQRect ( iTop , iBottom ) < < endl ;
# endif
// Look for intersection between yp -- yp+h and iTop -- iBottom
if ( TQMAX ( yp , iTop . y ( ) ) < = TQMIN ( yp + h , iBottom . y ( ) ) )
{
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins iTop= " < < iTop . x ( ) < < " , " < < iTop . y ( )
< < " iBottom= " < < iBottom . x ( ) < < " , " < < iBottom . y ( ) < < endl ;
# endif
int availLeft = TQMAX ( 0 , iTop . x ( ) - from ) ;
int availRight = TQMAX ( 0 , to - iBottom . x ( ) ) ;
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins availLeft= " < < availLeft
< < " availRight= " < < availRight < < endl ;
# endif
bool chooseLeft = false ;
switch ( ( * fIt ) - > runAroundSide ( ) ) {
case KWFrame : : RA_LEFT :
chooseLeft = true ;
break ;
case KWFrame : : RA_RIGHT :
break ; // chooseLeft remains false
case KWFrame : : RA_BIGGEST :
chooseLeft = ( availLeft > availRight ) ; // choose the max
} ;
if ( chooseLeft )
// flow text at the left of the frame
to = TQMIN ( to , from + availLeft - 1 ) ; // can only go left -> TQMIN
else
// flow text at the right of the frame
from = TQMAX ( from , to - availRight + 1 ) ; // can only go right -> TQMAX
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins from= " < < from < < " to= " < < to < < endl ;
# endif
// If the available space is too small, give up on it
if ( to - from < reqMinWidth + paragLeftMargin )
{
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " smaller than minimum= " < < m_doc - > ptToLayoutUnitPixX ( 15 ) + paragLeftMargin < < endl ;
# endif
from = to ;
}
if ( breakEnd & & from = = to ) // no-space case
{
if ( ! init ) // first time
{
init = true ;
* breakBegin = iTop . y ( ) ;
* breakEnd = iBottom . y ( ) ;
}
else
{
* breakBegin = TQMIN ( * breakBegin , iTop . y ( ) ) ;
* breakEnd = TQMAX ( * breakEnd , iBottom . y ( ) ) ;
}
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins iBottom.y= " < < iBottom . y ( )
< < " breakBegin= " < < * breakBegin
< < " breakEnd= " < < * breakEnd < < endl ;
# endif
}
} // else no intersection
} // else we got a 0L, or the iTop.y()<=yp+h test didn't work - wrong debug output
// kdDebugBody(32002) << " gerMargins: normalToInternal returned 0L" << endl;
}
}
}
}
if ( marginLeft /*&& marginRight && pageWidth -- implicit*/ )
{
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " getMargins done. from= " < < from < < " to= " < < to < < endl ;
# endif
if ( from = = to ) {
from = 0 ;
to = * pageWidth ;
}
if ( marginLeft )
* marginLeft + = from ;
if ( marginRight )
{
# ifdef DEBUG_MARGINS
kdDebug ( 32002 ) < < " getMargins " < < name ( )
< < " page width= " < < * pageWidth
< < " to= " < < to < < endl ;
# endif
* marginRight + = * pageWidth - to ;
}
}
}
void KWTextFrameSet : : adjustMargins ( int yp , int h , int reqMinWidth , int & leftMargin , int & rightMargin , int & pageWidth , KoTextParag * parag )
{
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " KWTextFrameSet::adjustMargins called for paragraph " < < ( parag ? parag - > paragId ( ) : - 1 ) < < endl ;
# endif
int validHeight ; // currently ignored (TODO)
getMargins ( yp , h , reqMinWidth , & leftMargin , & rightMargin , & pageWidth , & validHeight , 0L , 0L , parag ) ;
# ifdef DEBUG_MARGINS
kdDebugBody ( 32002 ) < < " KWTextFrameSet::adjustMargins(yp= " < < yp < < " h= " < < h < < " reqMinWidth= " < < reqMinWidth < < " returning "
< < " leftMargin= " < < leftMargin < < " rightMargin= " < < rightMargin
< < " valid from " < < yp < < " to " < < yp + validHeight < < endl ;
# endif
}
// helper for formatVertically
bool KWTextFrameSet : : checkVerticalBreak ( int & yp , int & hp , KoTextParag * parag , bool linesTogether , int breakBegin , int breakEnd )
{
// We need the "+1" here because when skipping a frame on top, we want to be _under_
// its bottom. Without the +1, we hit the frame again on the next adjustLMargin call.
// Check for intersection between the parag (yp -- yp+hp) and the break area (breakBegin -- breakEnd)
if ( TQMAX ( yp , breakBegin ) < = TQMIN ( yp + hp , breakEnd ) )
{
if ( ! parag | | linesTogether ) // Paragraph-level breaking
{
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " checkVerticalBreak ADJUSTING yp= " < < yp < < " hp= " < < hp
< < " breakEnd+2 [new value for yp]= " < < breakEnd + 2 < < endl ;
# endif
yp = breakEnd + 1 ;
return true ;
}
else // Line-level breaking
{
TQMap < int , KoTextParagLineStart * > & lineStarts = parag - > lineStartList ( ) ;
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " checkVerticalBreak parag " < < parag - > paragId ( )
< < " . lineStarts has " < < lineStarts . count ( )
< < " items " < < endl ;
# endif
int dy = 0 ;
int line = 0 ;
TQMap < int , KoTextParagLineStart * > : : Iterator it = lineStarts . begin ( ) ;
for ( ; it ! = lineStarts . end ( ) ; + + it , + + line )
{
KoTextParagLineStart * ls = it . data ( ) ;
Q_ASSERT ( ls ) ;
int y = parag - > rect ( ) . y ( ) + ls - > y ;
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " checkVerticalBreak parag " < < parag - > paragId ( )
< < " line " < < line < < " ls->y= " < < ls - > y
< < " ls->h= " < < ls - > h < < " y= " < < y
< < " breakBegin= " < < breakBegin
< < " breakEnd= " < < breakEnd < < endl ;
# endif
if ( ! dy )
{
if ( TQMAX ( y , breakBegin ) < = TQMIN ( y + ls - > h , breakEnd ) )
{
if ( line = = 0 ) // First line ? It's like a paragraph breaking then
{
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " checkVerticalBreak parag " < < parag - > paragId ( )
< < " BREAKING first line -> parag break " < < endl ;
# endif
yp = breakEnd + 1 ;
return true ;
}
dy = breakEnd + 1 - y ;
ls - > y = breakEnd + 1 - parag - > rect ( ) . y ( ) ;
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " checkVerticalBreak parag " < < parag - > paragId ( )
< < " BREAKING at line " < < line < < " dy= " < < dy < < " Setting ls->y to " < < ls - > y < < " , y= " < < breakEnd < < endl ;
# endif
}
}
else
{
ls - > y + = dy ;
# ifdef DEBUG_FORMATVERTICALLY
if ( dy )
kdDebug ( 32002 ) < < " moving down to position ls->y= " < < ls - > y < < endl ;
# endif
}
}
parag - > setMovedDown ( true ) ;
parag - > setHeight ( hp + dy ) ;
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " Paragraph height set to " < < hp + dy < < endl ;
# endif
hp + = dy ;
return true ;
} // End of line-level breaking
}
return false ;
}
int KWTextFrameSet : : formatVertically ( KoTextParag * _parag , const TQRect & paragRect )
{
// WARNING: in this whole method parag can be 0. See adjustFlow()
KWTextParag * parag = static_cast < KWTextParag * > ( _parag ) ;
if ( ! m_doc - > layoutViewMode ( ) - > shouldFormatVertically ( ) )
{
return 0 ;
}
# ifdef DEBUG_FORMATVERTICALLY
kdDebugBody ( 32002 ) < < " KWTextFrameSet::formatVertically called for paragraph " < < ( parag ? parag - > paragId ( ) : - 1 ) < < endl ;
# endif
int yp = paragRect . y ( ) ;
int hp = paragRect . height ( ) ;
int oldHeight = hp ;
int oldY = yp ;
// This is called by KoTextFormatter to apply "vertical breaks".
// End of frames/pages lead to those "vertical breaks".
// What we do, is adjust the Y accordingly,
// to implement page-break at the paragraph level and at the line level.
// It's cumulative (the space of one break will be included in the further
// paragraph's y position), which makes it easy to implement.
// But don't forget that formatVertically is called twice for every parag, since the formatting
// is re-done after moving down.
bool linesTogether = parag ? parag - > linesTogether ( ) : true ;
bool hardFrameBreak = parag ? parag - > hardFrameBreakBefore ( ) : false ;
if ( ! hardFrameBreak & & parag & & parag - > prev ( ) )
hardFrameBreak = static_cast < KWTextParag * > ( parag - > prev ( ) ) - > hardFrameBreakAfter ( ) ;
# ifdef DEBUG_FORMATVERTICALLY
kdDebugBody ( 32002 ) < < " KWTextFrameSet::formatVertically parag= " < < parag
< < " linesTogether= " < < linesTogether < < " hardFrameBreak= " < < hardFrameBreak
< < " yp= " < < yp
< < " hp= " < < hp < < endl ;
# endif
int totalHeight = 0 ;
TQPtrListIterator < KWFrame > frameIt ( frameIterator ( ) ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
int frameHeight = kWordDocument ( ) - > ptToLayoutUnitPixY ( frameIt . current ( ) - > innerHeight ( ) ) ;
int bottom = totalHeight + frameHeight ;
// Only skip bottom of frame if there is a next one or if there'll be another one created.
// ( Not for header/footer, for instance. )
bool check = frameIt . atLast ( ) & & frameIt . current ( ) - > frameBehavior ( ) = = KWFrame : : AutoCreateNewFrame ;
if ( ! check )
{
// ## TODO optimize this [maybe we should simply start from the end in the main loop?]
// Or cache the attribute ( e.g. "frame->hasCopy()" ).
TQPtrListIterator < KWFrame > nextFrame ( frameIt ) ;
while ( ! check & & ! nextFrame . atLast ( ) )
{
+ + nextFrame ;
if ( ! nextFrame . current ( ) - > isCopy ( ) )
check = true ; // Found a frame after us that isn't a copy => we have somewhere for our overflow
}
}
if ( check )
{
if ( hardFrameBreak & & yp > totalHeight & & yp < bottom & & ! parag - > wasMovedDown ( ) )
{
// The paragraph wants a frame break before it, and is in the current frame
// The last check is for whether we did the frame break already
// (formatVertically is called twice for each paragraph, if a break was done)
yp = bottom /*+ 2*/ ;
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " KWTextFrameSet::formatVertically -> HARD FRAME BREAK " < < endl ;
kdDebug ( 32002 ) < < " KWTextFrameSet::formatVertically yp now " < < yp < < endl ;
# endif
break ;
}
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " formatVertically: frameHeight= " < < frameHeight < < " bottom= " < < bottom < < endl ;
# endif
// don't move down parags that have only one line and are bigger than the page (e.g. floating tables)
if ( hp < frameHeight | | ( parag & & parag - > lineStartList ( ) . count ( ) > 1 ) )
{
// breakBegin==breakEnd==bottom, since the next frame's top is the same as bottom, in TQRT coords.
( void ) checkVerticalBreak ( yp , hp , parag , linesTogether , bottom , bottom ) ;
// Some people write a single paragraph over 3 frames! So we have to keep looking, that's why we ignore the return value
}
}
if ( yp + hp < bottom )
break ; // we've been past the parag, so stop here
totalHeight = bottom ;
}
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( 32002 ) < < " formatVertically: now looking at RA_SKIP " < < endl ;
# endif
// Another case for a vertical break is frames with the RA_SKIP flag
// Currently looking at all frames on top of all of our frames... maybe optimize better
frameIt . toFirst ( ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
Q_ASSERT ( frameIt . current ( ) - > frameStack ( ) ) ;
TQValueList < KWFrame * > onTop = frameIt . current ( ) - > frameStack ( ) - > framesOnTop ( ) ;
for ( TQValueListIterator < KWFrame * > fIt = onTop . begin ( ) ; fIt ! = onTop . end ( ) ; + + fIt )
{
if ( ( * fIt ) - > runAround ( ) = = KWFrame : : RA_SKIP )
{
KoRect rectOnTop = frameIt . current ( ) - > intersect ( ( * fIt ) - > runAroundRect ( ) ) ;
TQPoint iTop , iBottom ; // top and bottom in internal coordinates
if ( documentToInternal ( rectOnTop . topLeft ( ) , iTop ) & &
iTop . y ( ) < = yp + hp & &
documentToInternal ( rectOnTop . bottomLeft ( ) , iBottom ) & &
checkVerticalBreak ( yp , hp , parag , linesTogether ,
iTop . y ( ) , iBottom . y ( ) ) )
{
kdDebug ( 32002 ) < < " KWTextFrameSet::formatVertically breaking around RA_SKIP frame yp= " < < yp < < " hp= " < < hp < < endl ;
// We don't "break;" here because there could be another such frame below the first one
// We assume that the frames on top are in order ( top to bottom ), btw.
// They should be, since updateFrames reorders before updating frames-on-top
}
}
}
}
// And the last case for a vertical break is RA_BOUNDINGRECT frames that
// leave no space by their side for any text (e.g. most tables)
int breakBegin = 0 ;
int breakEnd = 0 ;
int reqMinWidth = parag ? parag - > string ( ) - > at ( 0 ) . width : 0 ;
getMargins ( yp , hp , reqMinWidth , 0L , 0L , 0L , 0L , & breakBegin , & breakEnd , parag ) ;
if ( breakEnd )
{
kdDebug ( 32002 ) < < " KWTextFrameSet( " < < name ( ) < < " )::formatVertically no-space case. breakBegin= " < < breakBegin
< < " breakEnd= " < < breakEnd < < " hp= " < < hp < < endl ;
Q_ASSERT ( breakBegin < = breakEnd ) ;
if ( checkVerticalBreak ( yp , hp , parag , linesTogether , breakBegin , breakEnd ) )
; //kdDebug(32002) << "checkVerticalBreak ok." << endl;
else // shouldn't happen
kdWarning ( 32002 ) < < " checkVerticalBreak didn't find it " < < endl ;
}
// ## TODO loop around those three methods until we don't move anymore ?
if ( parag )
{
if ( hp ! = oldHeight )
parag - > setHeight ( hp ) ;
if ( yp ! = oldY ) {
TQRect r = parag - > rect ( ) ;
r . moveBy ( 0 , yp - oldY ) ;
parag - > setRect ( r ) ;
parag - > setMovedDown ( true ) ;
}
}
# ifdef DEBUG_FORMATVERTICALLY
kdDebug ( ) < < " KWTextFrameSet::formatVertically returning " < < ( yp + hp ) - ( oldY + oldHeight ) < < endl ;
# endif
return ( yp + hp ) - ( oldY + oldHeight ) ;
}
// adjustFlow is called e.g. to break the "top margin" of a paragraph.
// There is no parag pointer in that case.
int KWTextFrameSet : : adjustFlow ( int y , int w , int h )
{
TQRect r ( 0 , y , w , h ) ;
return formatVertically ( 0L , r ) ;
}
void KWTextFrameSet : : fixParagWidth ( KWTextParag * parag )
{
// Fixing the parag rect for the formatting chars (CR and frame break).
if ( parag & & m_doc - > viewFormattingChars ( ) & & parag - > rect ( ) . width ( ) < textDocument ( ) - > width ( ) )
{
if ( parag - > hardFrameBreakAfter ( ) )
{
KoTextFormat * lastFormat = parag - > at ( parag - > length ( ) - 1 ) - > format ( ) ;
const TQFontMetrics & refFontMetrics = lastFormat - > refFontMetrics ( ) ;
// keep in sync with KWTextFrameSet::formatVertically
TQString str = i18n ( " --- Frame Break --- " ) ;
int width = refFontMetrics . width ( str ) ;
parag - > setWidth ( TQMIN ( parag - > rect ( ) . width ( ) + width , textDocument ( ) - > width ( ) ) ) ;
}
else // default KoTextFormatter implementation
parag - > fixParagWidth ( true ) ;
}
}
KWTextFrameSet : : ~ KWTextFrameSet ( )
{
textDocument ( ) - > takeFlow ( ) ;
//kdDebug(32001) << "KWTextFrameSet::~KWTextFrameSet" << endl;
m_doc = 0L ;
delete m_textobj ;
}
// This struct is used for sorting frames.
// Since pages are one below the other, simply sorting on (y, x) does what we want.
struct FrameStruct
{
KWFrame * frame ;
bool operator < ( const FrameStruct & t ) const {
return compare ( frame , t . frame ) < 0 ;
}
bool operator < = ( const FrameStruct & t ) const {
return compare ( frame , t . frame ) < = 0 ;
}
bool operator > ( const FrameStruct & t ) const {
return compare ( frame , t . frame ) > 0 ;
}
/*
the sorting of all frames in the same frameset is done as all sorting
based on a simple frameOne > frameTwo question .
Frame frameOne is greater then frameTwo if the center point lies more down then ( the whole of )
frame frameTwo . When they are equal , the X position is considered . */
int compare ( const KWFrame * frameOne , const KWFrame * frameTwo ) const {
// The first criteria is the page number though!
int pageOne = frameOne - > pageNumber ( ) ;
int pageTwo = frameTwo - > pageNumber ( ) ;
if ( ( pageOne = = - 1 ) ^ ( pageTwo = = - 1 ) ) {
if ( pageOne = = - 1 )
return 5 ; // undefined is higher than defined.
return - 5 ;
}
if ( pageOne > pageTwo ) return 4 ; // frameOne > frameTwo
if ( pageOne < pageTwo ) return - 4 ; // frameOne < frameTwo
double centerX = frameOne - > left ( ) + ( frameOne - > width ( ) / 2 ) ;
// reverse the return values of the next two for RTL
if ( centerX > frameTwo - > right ( ) ) return 3 ; // frameOne > frameTwo
if ( centerX < frameTwo - > left ( ) ) return - 3 ; // frameOne < frameTwo
// check the Y position. Y is greater only when it is below the other frame.
double centerY = frameOne - > top ( ) + ( frameOne - > height ( ) / 2 ) ;
if ( centerY > frameTwo - > bottom ( ) ) return 2 ; // frameOne > frameTwo
if ( centerY < frameTwo - > top ( ) ) return - 2 ; // frameOne < frameTwo
// the center of frameOne lies inside frameTwo. Lets check the topleft pos.
if ( frameOne - > top ( ) > frameTwo - > top ( ) ) return 1 ;
return - 1 ;
}
} ;
void KWTextFrameSet : : updateFrames ( int flags )
{
// Not visible ? Don't bother then.
if ( ! isVisible ( ) ) {
//kdDebug(32002) << "KWTextFrameSet::updateFrames " << name() << " not visible" << endl;
m_textobj - > setVisible ( false ) ;
return ;
}
m_textobj - > setVisible ( true ) ;
//kdDebug(32002) << "KWTextFrameSet::updateFrames " << name() << " frame-count=" << m_frames.count() << endl;
// Sort frames of this frameset on (y coord, x coord)
// Adjustment on 20-Jun-2002 which does not change the itent of this but moves the
// sorting from top-left of frame to the whole frame area. (TZ)
TQValueList < FrameStruct > sortedFrames ;
int width = 0 ;
TQPtrListIterator < KWFrame > frameIter ( frameIterator ( ) ) ;
for ( ; frameIter . current ( ) ; + + frameIter )
{
// Calculate max width while we're at it
//kdDebug(32002) << "KWTextFrameSet::updateFrames frame " << *frameIter.current() << " innerWidth=" << frameIter.current()->innerWidth() << "pt" << endl;
width = TQMAX ( width , m_doc - > ptToLayoutUnitPixX ( frameIter . current ( ) - > innerWidth ( ) ) ) ;
if ( flags & SortFrames )
{
FrameStruct str ;
str . frame = frameIter . current ( ) ;
sortedFrames . append ( str ) ;
}
}
if ( width ! = textDocument ( ) - > width ( ) )
{
//kdDebug(32002) << "KWTextFrameSet::updateFrames setWidth " << width << " LU pixels." << endl;
//textDocument()->setMinimumWidth( -1, 0 );
textDocument ( ) - > setWidth ( width + 1 ) ; // TQRect semantics problem (#32866)
} //else kdDebug(32002) << "KWTextFrameSet::updateFrames width already " << width << " LU pixels." << endl;
if ( flags & SortFrames )
{
qHeapSort ( sortedFrames ) ;
// Re-fill the frames list with the frames in the right order
m_frames . setAutoDelete ( false ) ;
m_frames . clear ( ) ;
TQValueList < FrameStruct > : : Iterator it = sortedFrames . begin ( ) ;
for ( ; it ! = sortedFrames . end ( ) ; + + it )
m_frames . append ( ( * it ) . frame ) ;
}
double availHeight = 0 ;
double internalYpt = 0 ;
double lastRealFrameHeight = 0 ;
bool firstFrame = true ;
TQPtrListIterator < KWFrame > frameIt ( m_frames ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
if ( ! theFrame - > isCopy ( ) )
internalYpt + = lastRealFrameHeight ;
theFrame - > setInternalY ( internalYpt ) ;
// Update availHeight with the internal height of this frame - unless it's a copy
if ( ! theFrame - > isCopy ( ) | | firstFrame )
{
lastRealFrameHeight = theFrame - > innerHeight ( ) ;
availHeight + = lastRealFrameHeight ;
}
firstFrame = false ;
}
m_textobj - > setAvailableHeight ( m_doc - > ptToLayoutUnitPixY ( availHeight ) ) ;
//kdDebug(32002) << this << " (" << name() << ") KWTextFrameSet::updateFrames availHeight=" << availHeight
// << " (LU: " << m_doc->ptToLayoutUnitPixY( availHeight ) << ")" << endl;
m_frames . setAutoDelete ( true ) ;
KWFrameSet : : updateFrames ( flags ) ;
}
int KWTextFrameSet : : availableHeight ( ) const
{
return m_textobj - > availableHeight ( ) ;
}
KWFrame * KWTextFrameSet : : internalToDocument ( const KoPoint & relPoint , KoPoint & dPoint ) const
{
# ifdef DEBUG_ITD
kdDebug ( ) < < name ( ) < < " ITD called for relPoint= " < < relPoint . x ( ) < < " , " < < relPoint . y ( ) < < endl ;
# endif
if ( ! m_doc - > layoutViewMode ( ) - > hasFrames ( ) ) { // text viewmode
dPoint = relPoint ;
return m_frames . getFirst ( ) ;
}
// This does a binary search in the m_framesInPage array, with internalY as criteria
// We only look at the first frame of each page. Refining is done later on.
Q_ASSERT ( ! m_framesInPage . isEmpty ( ) ) ;
int len = m_framesInPage . count ( ) ;
int n1 = 0 ;
int n2 = len - 1 ;
double internalY = 0.0 ;
int mid = 0 ;
bool found = FALSE ;
while ( n1 < = n2 ) {
double res ;
mid = ( n1 + n2 ) / 2 ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: begin. mid= " < < mid < < endl ;
# endif
Q_ASSERT ( m_framesInPage [ mid ] ) ; // We have no null items
if ( m_framesInPage [ mid ] - > isEmpty ( ) )
res = - 1 ;
else
{
KWFrame * theFrame = m_framesInPage [ mid ] - > first ( ) ;
internalY = theFrame - > internalY ( ) ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: relPoint.y= " < < relPoint . y ( ) < < " internalY= " < < internalY < < endl ;
# endif
res = relPoint . y ( ) - internalY ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: res= " < < res < < endl ;
# endif
// Anything between this internalY (top) and internalY+height (bottom) is fine
// (Using the next page's first frame's internalY only works if there is a frame on the next page)
if ( res > = 0 )
{
double height = theFrame - > innerHeight ( ) ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: height= " < < height < < " -> the bottom is at " < < internalY + height < < endl ;
# endif
if ( relPoint . y ( ) < internalY + height )
{
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: found a match " < < mid < < endl ;
# endif
found = true ;
break ;
}
}
}
// res == 0 can't happen in theory, but in practice it happens when a frame has a height of 0
// (e.g. newly imported table without correct row heights)
if ( res < 0 )
n2 = mid - 1 ;
else // if ( res >= 0 )
n1 = mid + 1 ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: End of loop. n1= " < < n1 < < " n2= " < < n2 < < endl ;
# endif
}
if ( ! found )
{
// Not found (n2 < n1)
// We might have missed the frame because n2 has many frames
// (and we only looked at the first one).
mid = n2 ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " ITD: Setting mid to n2= " < < mid < < endl ;
# endif
if ( mid < 0 )
{
# ifdef DEBUG_ITD
kdDebug ( 32002 ) < < " KWTextFrameSet::internalToDocument " < < relPoint . x ( ) < < " , " < < relPoint . y ( )
< < " before any frame of " < < ( void * ) this < < endl ;
# endif
dPoint = relPoint ; // "bah", I said above :)
return 0L ;
}
}
// search to first of equal items
// This happens with copied frames, which have the same internalY
int result = mid ;
while ( mid - 1 > = 0 )
{
mid - - ;
if ( ! m_framesInPage [ mid ] - > isEmpty ( ) )
{
KWFrame * theFrame = m_framesInPage [ mid ] - > first ( ) ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " KWTextFrameSet::internalToDocument going back to page " < < mid < < " - frame: " < < theFrame - > internalY ( ) < < endl ;
# endif
if ( theFrame - > internalY ( ) = = internalY ) // same internalY as the frame we found before
result = mid ;
else
break ;
}
}
// Now iterate over the frames in page 'result' and find the right one
TQPtrListIterator < KWFrame > frameIt ( * m_framesInPage [ result ] ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
KoRect relRect ( 0 , theFrame - > internalY ( ) , theFrame - > innerWidth ( ) , theFrame - > innerHeight ( ) ) ;
# ifdef DEBUG_ITD
kdDebug ( ) < < " KWTextFrameSet::internalToDocument frame's relative rect: " < < relRect < < endl ;
# endif
if ( relRect . contains ( relPoint ) ) // both relRect and relPoint are in "relative coordinates"
{
dPoint = internalToDocumentKnowingFrame ( relPoint , theFrame ) ;
return theFrame ;
}
}
# ifdef DEBUG_ITD
kdDebug ( 32002 ) < < " KWTextFrameSet::internalToDocument " < < relPoint . x ( ) < < " , " < < relPoint . y ( )
< < " not in any frame of " < < ( void * ) this < < " (looked on page " < < result < < " ) " < < endl ;
# endif
dPoint = relPoint ; // bah again
return 0L ;
}
// same but with iPoint in LU
KWFrame * KWTextFrameSet : : internalToDocument ( const TQPoint & iPoint , KoPoint & dPoint ) const
{
KoPoint relPoint = m_doc - > layoutUnitPtToPt ( m_doc - > pixelToPt ( iPoint ) ) ;
return internalToDocument ( relPoint , dPoint ) ;
}
# ifndef NDEBUG
void KWTextFrameSet : : printDebug ( )
{
KWFrameSet : : printDebug ( ) ;
if ( ! isDeleted ( ) )
{
kdDebug ( ) < < " KoTextDocument width = " < < textDocument ( ) - > width ( ) < < " height = " < < textDocument ( ) - > height ( ) < < endl ;
}
TQPtrListIterator < KoTextCustomItem > cit ( textDocument ( ) - > allCustomItems ( ) ) ;
for ( ; cit . current ( ) ; + + cit )
{
KWAnchor * anc = dynamic_cast < KWAnchor * > ( cit . current ( ) ) ;
if ( anc )
kdDebug ( ) < < " Inline framesets: " < < anc - > frameSet ( ) - > name ( ) < < endl ;
}
}
# endif
TQDomElement KWTextFrameSet : : saveInternal ( TQDomElement & parentElem , bool saveFrames , bool saveAnchorsFramesets )
{
if ( m_frames . isEmpty ( ) ) // Deleted frameset -> don't save
return TQDomElement ( ) ;
TQDomElement framesetElem = parentElem . ownerDocument ( ) . createElement ( " FRAMESET " ) ;
parentElem . appendChild ( framesetElem ) ;
if ( m_groupmanager ) {
framesetElem . setAttribute ( " grpMgr " , m_groupmanager - > name ( ) ) ;
KWTableFrameSet : : Cell * cell = ( KWTableFrameSet : : Cell * ) this ;
framesetElem . setAttribute ( " row " , cell - > firstRow ( ) ) ;
framesetElem . setAttribute ( " col " , cell - > firstColumn ( ) ) ;
framesetElem . setAttribute ( " rows " , cell - > rowSpan ( ) ) ;
framesetElem . setAttribute ( " cols " , cell - > columnSpan ( ) ) ;
}
if ( protectContent ( ) )
framesetElem . setAttribute ( " protectContent " , static_cast < int > ( protectContent ( ) ) ) ;
KWFrameSet : : saveCommon ( framesetElem , saveFrames ) ;
// Save paragraphs
KWTextParag * start = static_cast < KWTextParag * > ( textDocument ( ) - > firstParag ( ) ) ;
while ( start ) {
start - > save ( framesetElem , saveAnchorsFramesets ) ;
start = static_cast < KWTextParag * > ( start - > next ( ) ) ;
}
return framesetElem ;
}
KWFrame * KWTextFrameSet : : loadOasisTextFrame ( const TQDomElement & frameTag , const TQDomElement & tag , KoOasisContext & context )
{
context . styleStack ( ) . save ( ) ;
context . fillStyleStack ( frameTag , KoXmlNS : : draw , " style-name " , " graphic " ) ; // get the style for the graphics element
KWFrame * frame = loadOasisFrame ( frameTag , context ) ;
// Load minimum height - only available for text-box
bool hasMinHeight = tag . hasAttributeNS ( KoXmlNS : : fo , " min-height " ) ;
if ( hasMinHeight ) {
double height = KoUnit : : parseValue ( tag . attributeNS ( KoXmlNS : : fo , " min-height " , TQString ( ) ) ) ;
frame - > setMinimumFrameHeight ( height ) ;
if ( height > frame - > height ( ) | | ! tag . hasAttributeNS ( KoXmlNS : : fo , " height " ) )
frame - > setHeight ( height ) ;
}
// Load overflow behavior (OASIS 14.27.27, not in OO-1.1 DTD). This is here since it's only for text framesets.
const TQString overflowBehavior = context . styleStack ( ) . attributeNS ( KoXmlNS : : style , " overflow-behavior " ) ;
if ( frame - > minimumFrameHeight ( ) > 0 )
frame - > setFrameBehavior ( KWFrame : : AutoExtendFrame ) ;
else if ( overflowBehavior = = " auto-create-new-frame " )
{
frame - > setFrameBehavior ( KWFrame : : AutoCreateNewFrame ) ;
frame - > setNewFrameBehavior ( KWFrame : : Reconnect ) ; // anything else doesn't make sense
}
else if ( overflowBehavior . isEmpty ( ) | | overflowBehavior = = " clip " )
frame - > setFrameBehavior ( KWFrame : : Ignore ) ;
else
kdWarning ( 32001 ) < < " Unknown value for style:overflow-behavior: " < < overflowBehavior < < endl ;
context . styleStack ( ) . restore ( ) ;
return frame ;
}
void KWTextFrameSet : : loadOasisContent ( const TQDomElement & bodyElem , KoOasisContext & context )
{
return m_textobj - > loadOasisContent ( bodyElem , context , m_doc - > styleCollection ( ) ) ;
}
KWFrame * KWTextFrameSet : : loadOasis ( const TQDomElement & frameTag , const TQDomElement & tag , KoOasisContext & context )
{
KWFrame * frame = loadOasisTextFrame ( frameTag , tag , context ) ;
loadOasisContent ( tag , context ) ;
return frame ;
}
static void finishTOC ( KoXmlWriter & writer )
{
writer . endElement ( ) ; // text:table-of-content
writer . endElement ( ) ; // text:index-body
}
void KWTextFrameSet : : saveOasisContent ( KoXmlWriter & writer , KoSavingContext & context ) const
{
// TODO save protectContent
TQMap < const KoTextParag * , KoTextBookmarkList > bookmarksPerParagraph ;
if ( m_doc - > bookmarkList ( ) )
bookmarksPerParagraph = m_doc - > bookmarkList ( ) - > bookmarksPerParagraph ( ) ;
// Basically just call saveOasis on every paragraph.
// But we do table-of-contents-handling (for kword) in addition,
// as well as bookmarks.
KoTextParag * parag = textDocument ( ) - > firstParag ( ) ;
bool inTOC = false ;
while ( parag ) {
bool tocParag = parag - > partOfTableOfContents ( ) ;
if ( tocParag ! = inTOC ) {
if ( tocParag ) { // first TOC paragraph
writer . startElement ( " text:table-of-content " ) ;
writer . addAttribute ( " text:name " , " Table Of Contents " ) ;
writer . addAttribute ( " text:protected " , " false " ) ; // true by default in OO, but we don't support that yet anyway
writer . startElement ( " text:table-of-content-source " ) ;
// TODO writer.addAttribute( "text:outline-level", ... );
// TODO for each level writer.startElement( "text:table-of-content-entry-template" );
// TODO writer.endElement(); // text:table-of-content-entry-template
writer . endElement ( ) ; // text:table-of-content-source
writer . startElement ( " text:index-body " ) ;
writer . startElement ( " text:index-title " ) ;
writer . addAttribute ( " text:name " , " Table Of Contents Heading " ) ;
} else {
finishTOC ( writer ) ;
}
}
// I want TQt4's TQMap/TQHash::value()!
KoSavingContext : : BookmarkPositions bookmarkStarts , bookmarkEnds ;
TQMap < const KoTextParag * , KoTextBookmarkList > : : const_iterator bkit = bookmarksPerParagraph . find ( parag ) ;
if ( bkit ! = bookmarksPerParagraph . end ( ) ) {
// Massage a bit the bookmarks data; KoTextParag wants it ordered by position, for speed.
const KoTextBookmarkList & bookmarks = * bkit ;
for ( KoTextBookmarkList : : const_iterator it = bookmarks . begin ( ) ; it ! = bookmarks . end ( ) ; + + it )
{
const KoTextBookmark & bk = * it ;
if ( bk . startParag ( ) = = parag )
bookmarkStarts . append ( KoSavingContext : : BookmarkPosition (
bk . bookmarkName ( ) , bk . bookmarkStartIndex ( ) ,
bk . isSimple ( ) ) ) ;
if ( bk . endParag ( ) = = parag & & ! bk . isSimple ( ) )
bookmarkEnds . append ( KoSavingContext : : BookmarkPosition ( bk . bookmarkName ( ) ,
bk . bookmarkEndIndex ( ) , false ) ) ;
}
qHeapSort ( bookmarkStarts ) ;
qHeapSort ( bookmarkEnds ) ;
}
// should be done in all cases, even if both lists are empty
context . setBookmarkPositions ( bookmarkStarts , bookmarkEnds ) ;
// Save the whole parag, without the trailing space.
parag - > saveOasis ( writer , context , 0 , parag - > lastCharPos ( ) ) ;
if ( tocParag & & ! inTOC )
writer . endElement ( ) ; // text:index-title
inTOC = tocParag ;
parag = parag - > next ( ) ;
}
if ( inTOC )
finishTOC ( writer ) ;
}
void KWTextFrameSet : : saveOasis ( KoXmlWriter & writer , KoSavingContext & context , bool saveFrames ) const
{
// Save first frame with the whole contents
KWFrame * frame = m_frames . getFirst ( ) ;
TQString lastFrameName = name ( ) ;
frame - > startOasisFrame ( writer , context . mainStyles ( ) , lastFrameName ) ;
TQString nextFrameName = name ( ) + " - " ;
writer . startElement ( " draw:text-box " ) ;
if ( frame - > frameBehavior ( ) = = KWFrame : : AutoExtendFrame )
writer . addAttributePt ( " fo:min-height " , frame - > minimumFrameHeight ( ) ) ;
if ( m_frames . count ( ) > 1 & & saveFrames )
writer . addAttribute ( " draw:chain-next-name " , nextFrameName + " 2 " ) ;
saveOasisContent ( writer , context ) ;
writer . endElement ( ) ; // draw:text-box
writer . endElement ( ) ; // draw:frame
// Save other frames using chaining
if ( saveFrames ) // false when called from KWDocument::saveSelectedFrames
{
int frameNumber = 2 ;
TQPtrListIterator < KWFrame > frameIter ( frameIterator ( ) ) ;
+ + frameIter ; // skip first frame, already saved
for ( ; frameIter . current ( ) ; + + frameIter , + + frameNumber )
{
const TQString frameName = nextFrameName + TQString : : number ( frameNumber ) ;
frameIter . current ( ) - > startOasisFrame ( writer , context . mainStyles ( ) , frameName , lastFrameName ) ;
lastFrameName = frameName ; // this is used for copy-frames
writer . startElement ( " draw:text-box " ) ;
if ( frame - > frameBehavior ( ) = = KWFrame : : AutoExtendFrame )
writer . addAttributePt ( " fo:min-height " , frame - > minimumFrameHeight ( ) ) ;
if ( frameNumber < ( int ) m_frames . count ( ) )
writer . addAttribute ( " draw:chain-next-name " , nextFrameName + TQString : : number ( frameNumber + 1 ) ) ;
// No contents. Well, OOo saves an empty paragraph, but I'd say that's wrong.
writer . endElement ( ) ;
writer . endElement ( ) ; // draw:frame
}
}
}
void KWTextFrameSet : : load ( TQDomElement & attributes , bool loadFrames )
{
KWFrameSet : : load ( attributes , loadFrames ) ;
if ( attributes . hasAttribute ( " protectContent " ) )
setProtectContent ( ( bool ) attributes . attribute ( " protectContent " ) . toInt ( ) ) ;
textDocument ( ) - > clear ( false ) ; // Get rid of dummy paragraph (and more if any)
m_textobj - > setLastFormattedParag ( 0L ) ; // no more parags, avoid UMR in next setLastFormattedParag call
KWTextParag * lastParagraph = 0L ;
// <PARAGRAPH>
TQDomElement paragraph = attributes . firstChild ( ) . toElement ( ) ;
for ( ; ! paragraph . isNull ( ) ; paragraph = paragraph . nextSibling ( ) . toElement ( ) )
{
if ( paragraph . tagName ( ) = = " PARAGRAPH " )
{
KWTextParag * parag = new KWTextParag ( textDocument ( ) , lastParagraph ) ;
parag - > load ( paragraph ) ;
if ( ! lastParagraph ) // First parag
textDocument ( ) - > setFirstParag ( parag ) ;
lastParagraph = parag ;
m_doc - > progressItemLoaded ( ) ;
}
}
if ( ! lastParagraph ) // We created no paragraph
{
// Create an empty one, then. See KWTextDocument ctor.
textDocument ( ) - > clear ( true ) ;
static_cast < KWTextParag * > ( textDocument ( ) - > firstParag ( ) ) - > setStyle ( m_doc - > styleCollection ( ) - > findStyle ( " Standard " ) ) ;
}
else
textDocument ( ) - > setLastParag ( lastParagraph ) ;
m_textobj - > setLastFormattedParag ( textDocument ( ) - > firstParag ( ) ) ;
//kdDebug(32001) << "KWTextFrameSet::load done" << endl;
}
void KWTextFrameSet : : finalize ( )
{
KWFrameSet : : finalize ( ) ;
m_textobj - > formatMore ( 0 ) ; // just to get the timer going
// This is important in case of auto-resized frames or table cells,
// which come from an import filter, which didn't give them the right size.
// However it shouldn't start _now_ (so we use 0), because e.g. main frames
// don't have the right size yet (KWFrameLayout not done yet).
}
void KWTextFrameSet : : setVisible ( bool visible )
{
setInlineFramesVisible ( visible ) ;
KWFrameSet : : setVisible ( visible ) ;
}
void KWTextFrameSet : : setInlineFramesVisible ( bool visible )
{
TQPtrListIterator < KoTextCustomItem > cit ( textDocument ( ) - > allCustomItems ( ) ) ;
for ( ; cit . current ( ) ; + + cit )
{
KWAnchor * anc = dynamic_cast < KWAnchor * > ( cit . current ( ) ) ;
if ( anc )
anc - > frameSet ( ) - > setVisible ( visible ) ;
}
}
void KWTextFrameSet : : addTextFrameSets ( TQPtrList < KWTextFrameSet > & lst , bool onlyReadWrite )
{
if ( ! textObject ( ) - > protectContent ( ) | | ! onlyReadWrite )
lst . append ( this ) ;
}
void KWTextFrameSet : : slotNewCommand ( KCommand * cmd )
{
m_doc - > addCommand ( cmd ) ;
}
void KWTextFrameSet : : ensureFormatted ( KoTextParag * parag , bool emitAfterFormatting )
{
if ( ! isVisible ( ) )
return ;
m_textobj - > ensureFormatted ( parag , emitAfterFormatting ) ;
}
bool KWTextFrameSet : : slotAfterFormattingNeedMoreSpace ( int bottom , KoTextParag * lastFormatted )
{
int availHeight = availableHeight ( ) ;
# ifdef DEBUG_FORMAT_MORE
if ( lastFormatted )
kdDebug ( 32002 ) < < " slotAfterFormatting We need more space in " < < name ( )
< < " bottom= " < < bottom + lastFormatted - > rect ( ) . height ( )
< < " availHeight= " < < availHeight < < endl ;
else
kdDebug ( 32002 ) < < " slotAfterFormatting We need more space in " < < name ( )
< < " bottom2= " < < bottom < < " availHeight= " < < availHeight < < endl ;
# endif
if ( m_frames . isEmpty ( ) )
{
kdWarning ( 32002 ) < < " slotAfterFormatting no more space, but no frame ! " < < endl ;
return true ; // abort
}
KWFrame : : FrameBehavior frmBehavior = m_frames . last ( ) - > frameBehavior ( ) ;
if ( frmBehavior = = KWFrame : : AutoExtendFrame & & isProtectSize ( ) )
frmBehavior = KWFrame : : Ignore ;
if ( frmBehavior = = KWFrame : : AutoCreateNewFrame )
{
KWFrame * theFrame = settingsFrame ( m_frames . last ( ) ) ;
double minHeight = s_minFrameHeight + theFrame - > paddingTop ( ) + theFrame - > paddingBottom ( ) + 5 ;
if ( availHeight < minHeight )
frmBehavior = KWFrame : : Ignore ;
}
int difference = ( bottom + 2 ) - availHeight ; // in layout unit pixels
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " AutoExtendFrame bottom= " < < bottom < < " availHeight= " < < availHeight
< < " => difference = " < < difference < < endl ;
# endif
if ( lastFormatted & & bottom + lastFormatted - > rect ( ) . height ( ) > availHeight ) {
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " next will be off -> adding " < < lastFormatted - > rect ( ) . height ( ) < < endl ;
# endif
difference + = lastFormatted - > rect ( ) . height ( ) ;
}
switch ( frmBehavior ) {
case KWFrame : : AutoExtendFrame :
{
if ( difference > 0 ) {
// There's no point in resizing a copy, so go back to the last non-copy frame
KWFrame * theFrame = settingsFrame ( m_frames . last ( ) ) ;
double wantedPosition = 0 ;
// Footers and footnotes go up
if ( theFrame - > frameSet ( ) - > isAFooter ( ) | | theFrame - > frameSet ( ) - > isFootNote ( ) )
{
// The Y position doesn't matter much, recalcFrames will reposition the frame
// But the point of this code is set the correct height for the frame.
double maxFooterSize = footerHeaderSizeMax ( theFrame ) ;
double diffPt = m_doc - > layoutUnitPtToPt ( m_doc - > pixelYToPt ( difference ) ) ;
wantedPosition = theFrame - > top ( ) - diffPt ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " diffPt= " < < diffPt < < " -> wantedPosition= " < < wantedPosition < < endl ;
# endif
if ( wantedPosition < 0 )
{
m_textobj - > setLastFormattedParag ( 0 ) ;
return true ; // abort
}
if ( wantedPosition ! = theFrame - > top ( ) & &
( theFrame - > frameSet ( ) - > isFootEndNote ( ) | |
theFrame - > bottom ( ) - maxFooterSize < = wantedPosition ) ) // Apply maxFooterSize for footers only
{
theFrame - > setTop ( wantedPosition ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " ok: frame= " < < * theFrame < < " bottom= " < < theFrame - > bottom ( ) < < " height= " < < theFrame - > height ( ) < < endl ;
# endif
frameResized ( theFrame , true ) ;
// We only got room for the next paragraph, we still have to keep the formatting going...
return false ; // keep going
}
kdDebug ( ) < < " slotAfterFormatting didn't manage to get more space for footer/footnote, aborting " < < endl ;
return true ; // abort
}
// Other frames are resized by the bottom
wantedPosition = m_doc - > layoutUnitPtToPt ( m_doc - > pixelYToPt ( difference ) ) + theFrame - > bottom ( ) ;
KWPage * page = m_doc - > pageManager ( ) - > page ( theFrame ) ;
double pageBottom ;
if ( page )
pageBottom = page - > offsetInDocument ( ) + page - > height ( ) - page - > bottomMargin ( ) ;
else
pageBottom = theFrame - > bottom ( ) ;
double newPosition = TQMIN ( wantedPosition , pageBottom ) ;
kdDebug ( 32002 ) < < " wantedPosition= " < < wantedPosition < < " pageBottom= " < < pageBottom
< < " -> newPosition= " < < newPosition < < endl ;
if ( theFrame - > frameSet ( ) - > isAHeader ( ) )
{
double maxHeaderSize = footerHeaderSizeMax ( theFrame ) ;
newPosition = TQMIN ( newPosition , maxHeaderSize + theFrame - > top ( ) ) ;
}
newPosition = TQMAX ( newPosition , theFrame - > top ( ) ) ; // avoid negative heights
kdDebug ( 32002 ) < < " newPosition= " < < newPosition < < endl ;
bool resized = false ;
if ( theFrame - > frameSet ( ) - > groupmanager ( ) ) {
KWTableFrameSet * table = theFrame - > frameSet ( ) - > groupmanager ( ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " is table cell; just setting new minFrameHeight, to " < < newPosition - theFrame - > top ( ) < < endl ;
# endif
double newMinFrameHeight = newPosition - theFrame - > top ( ) ;
resized = TQABS ( newMinFrameHeight - theFrame - > minimumFrameHeight ( ) ) > 1E-10 ;
if ( resized ) {
theFrame - > setMinimumFrameHeight ( newMinFrameHeight ) ;
KWTableFrameSet : : Cell * cell = ( KWTableFrameSet : : Cell * ) theFrame - > frameSet ( ) ;
table - > recalcCols ( cell - > firstColumn ( ) , cell - > firstRow ( ) ) ;
table - > recalcRows ( cell - > firstColumn ( ) , cell - > firstRow ( ) ) ;
if ( ! table - > anchorFrameset ( ) )
; // do nothing
else if ( table - > anchorFrameset ( ) & & table - > anchorFrameset ( ) - > isAHeader ( ) ) //we must recalculate the header frame size
{
theFrame = table - > anchorFrameset ( ) - > frameIterator ( ) . getLast ( ) ;
theFrame - > setBottom ( newPosition ) ;
frameResized ( theFrame , false ) ;
}
else if ( table - > anchorFrameset ( ) - > isAFooter ( ) | | table - > anchorFrameset ( ) - > isFootNote ( ) ) //we must recalculate the footer frame size
{
theFrame = table - > anchorFrameset ( ) - > frameIterator ( ) . getLast ( ) ;
// The Y position doesn't matter much, recalcFrames will reposition the frame
// But the point of this code is set the correct height for the frame.
double maxFooterSize = footerHeaderSizeMax ( theFrame ) ;
double diffPt = m_doc - > layoutUnitPtToPt ( m_doc - > pixelYToPt ( difference ) ) ;
wantedPosition = theFrame - > top ( ) - diffPt ;
if ( wantedPosition < 0 )
{
m_textobj - > setLastFormattedParag ( 0 ) ;
return true ; // abort
}
if ( wantedPosition ! = theFrame - > top ( ) & &
( theFrame - > frameSet ( ) - > isFootEndNote ( ) | |
theFrame - > bottom ( ) - maxFooterSize < = wantedPosition ) ) // Apply maxFooterSize for footers only
{
theFrame - > setTop ( wantedPosition ) ;
frameResized ( theFrame , true ) ;
// We only got room for the next paragraph, we still have to keep the formatting going...
}
}
m_doc - > delayedRepaintAllViews ( ) ;
}
return true ; // abort formatting for now (not sure this is correct)
} else {
resized = TQABS ( theFrame - > bottom ( ) - newPosition ) > 1E-10 ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " bottom= " < < theFrame - > bottom ( ) < < " new position: " < < newPosition < < " wantedPosition= " < < wantedPosition < < " resized= " < < resized < < endl ;
# endif
if ( resized )
{
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " slotAfterFormatting changing bottom from " < < theFrame - > bottom ( ) < < " to " < < newPosition < < endl ;
# endif
theFrame - > setBottom ( newPosition ) ;
frameResized ( theFrame , false ) ;
}
}
if ( newPosition < wantedPosition & &
( theFrame - > newFrameBehavior ( ) = = KWFrame : : Reconnect
& & ! theFrame - > frameSet ( ) - > isEndNote ( ) ) ) // end notes are handled by KWFrameLayout
{
wantedPosition = wantedPosition - newPosition + theFrame - > top ( ) + page - > height ( ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " Not enough room in this page -> creating new one, with a reconnect frame " < < endl ;
kdDebug ( 32002 ) < < " new wantedPosition= " < < wantedPosition < < endl ;
# endif
// fall through to AutoCreateNewFrame
}
else if ( newPosition < wantedPosition & & ( theFrame - > newFrameBehavior ( ) = = KWFrame : : NoFollowup ) ) {
if ( theFrame - > frameSet ( ) - > isEndNote ( ) ) // we'll need a new page
m_doc - > delayedRecalcFrames ( theFrame - > pageNumber ( ) ) ;
m_textobj - > setLastFormattedParag ( 0 ) ;
return true ; // abort
} else {
if ( resized ) // we managed to resize a frame
return false ; // keep going
return true ; // abort
}
}
}
case KWFrame : : AutoCreateNewFrame :
{
// We need a new frame in this frameset.
return createNewPageAndNewFrame ( lastFormatted , difference ) ;
}
case KWFrame : : Ignore :
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " slotAfterFormatting frame behaviour is Ignore " < < endl ;
# endif
m_textobj - > setLastFormattedParag ( 0 ) ;
return true ; // abort
}
kdWarning ( ) < < " NEVERREACHED " < < endl ;
// NEVERREACHED
return true ;
}
void KWTextFrameSet : : slotAfterFormattingTooMuchSpace ( int bottom )
{
int availHeight = availableHeight ( ) ;
// The + 2 here leaves 2 pixels below the last line. Without it we hit
// the "break at end of frame" case in formatVertically (!!).
int difference = availHeight - ( bottom + 2 ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " slotAfterFormatting less text than space (AutoExtendFrame). Frameset " < < name ( ) < < " availHeight= " < < availHeight < < " bottom= " < < bottom < < " ->difference= " < < difference < < endl ;
# endif
// There's no point in resizing a copy, so go back to the last non-copy frame
KWFrame * theFrame = settingsFrame ( m_frames . last ( ) ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " frame is " < < * theFrame < < " footer: " < < ( theFrame - > frameSet ( ) - > isAFooter ( ) | | theFrame - > frameSet ( ) - > isFootEndNote ( ) ) < < endl ;
# endif
if ( theFrame - > frameSet ( ) - > isAFooter ( ) | | theFrame - > frameSet ( ) - > isFootEndNote ( ) )
{
double wantedPosition = theFrame - > top ( ) + m_doc - > layoutUnitPtToPt ( m_doc - > pixelYToPt ( difference ) ) ;
Q_ASSERT ( wantedPosition < theFrame - > bottom ( ) ) ;
if ( wantedPosition ! = theFrame - > top ( ) )
{
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " top= " < < theFrame - > top ( ) < < " setTop " < < wantedPosition < < endl ;
# endif
theFrame - > setTop ( wantedPosition ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " -> the frame is now " < < * theFrame < < endl ;
# endif
frameResized ( theFrame , true ) ;
}
}
else // header or other frame: resize bottom
{
double wantedPosition = theFrame - > bottom ( ) - m_doc - > layoutUnitPtToPt ( m_doc - > pixelYToPt ( difference ) ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " slotAfterFormatting wantedPosition= " < < wantedPosition < < " top+minheight= " < < theFrame - > top ( ) + s_minFrameHeight < < endl ;
# endif
wantedPosition = TQMAX ( wantedPosition , theFrame - > top ( ) + s_minFrameHeight ) ;
if ( theFrame - > frameSet ( ) - > groupmanager ( ) ) {
if ( wantedPosition ! = theFrame - > bottom ( ) ) {
KWTableFrameSet * table = theFrame - > frameSet ( ) - > groupmanager ( ) ;
// When a frame can be smaller we don't rescale it if it is a table, since
// we don't have the full picture of the change.
// We will set the minFrameHeight to the correct value and let the tables code
// do the rescaling based on all the frames in the row. (see KWTableFrameSet::recalcRows())
if ( wantedPosition ! = theFrame - > top ( ) + theFrame - > minimumFrameHeight ( ) ) {
theFrame - > setMinimumFrameHeight ( wantedPosition - theFrame - > top ( ) ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " is table cell; only setting new minFrameHeight to " < < theFrame - > minimumFrameHeight ( ) < < " , recalcrows will do the rest " < < endl ;
# endif
KWTableFrameSet : : Cell * cell = ( KWTableFrameSet : : Cell * ) theFrame - > frameSet ( ) ;
table - > recalcCols ( cell - > firstColumn ( ) , cell - > firstRow ( ) ) ;
table - > recalcRows ( cell - > firstColumn ( ) , cell - > firstRow ( ) ) ;
if ( ! table - > anchorFrameset ( ) )
; // do nothing
else if ( table - > anchorFrameset ( ) & & table - > anchorFrameset ( ) - > isAHeader ( ) )
{
theFrame = table - > anchorFrameset ( ) - > frameIterator ( ) . getLast ( ) ;
theFrame - > setBottom ( wantedPosition ) ;
frameResized ( theFrame , false ) ;
}
else if ( table - > anchorFrameset ( ) - > isAFooter ( ) | | table - > anchorFrameset ( ) - > isFootEndNote ( ) )
{
theFrame = table - > anchorFrameset ( ) - > frameIterator ( ) . getLast ( ) ;
double wantedPosition = theFrame - > top ( ) + m_doc - > layoutUnitPtToPt ( m_doc - > pixelYToPt ( difference ) ) ;
Q_ASSERT ( wantedPosition < theFrame - > bottom ( ) ) ;
if ( wantedPosition ! = theFrame - > top ( ) )
{
theFrame - > setTop ( wantedPosition ) ;
frameResized ( theFrame , true ) ;
}
}
m_doc - > delayedRepaintAllViews ( ) ;
}
}
} else {
// Also apply the frame's minimum height
wantedPosition = TQMAX ( wantedPosition , theFrame - > top ( ) + theFrame - > minimumFrameHeight ( ) ) ;
if ( wantedPosition ! = theFrame - > bottom ( ) ) {
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " the frame was " < < * theFrame < < endl ;
kdDebug ( ) < < " setBottom " < < wantedPosition < < endl ;
# endif
theFrame - > setBottom ( wantedPosition ) ;
# ifdef DEBUG_FORMAT_MORE
kdDebug ( ) < < " -> the frame is now " < < * theFrame < < endl ;
# endif
frameResized ( theFrame , true ) ;
}
}
}
}
void KWTextFrameSet : : slotAfterFormatting ( int bottom , KoTextParag * lastFormatted , bool * abort )
{
int availHeight = availableHeight ( ) ;
if ( ( bottom > availHeight ) | | // this parag is already off page
( lastFormatted & & bottom + lastFormatted - > rect ( ) . height ( ) > availHeight ) ) // or next parag will be off page
{
* abort = slotAfterFormattingNeedMoreSpace ( bottom , lastFormatted ) ;
}
// Handle the case where the last frame is empty, so we may want to
// remove the last page.
else if ( m_frames . count ( ) > 1 & & ! lastFormatted & & frameSetInfo ( ) = = KWFrameSet : : FI_BODY
& & bottom < availHeight - m_doc - > ptToLayoutUnitPixY ( m_frames . last ( ) - > innerHeight ( ) ) )
{
# ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " slotAfterFormatting too much space (bottom= " < < bottom < < " , availHeight= " < < availHeight < < " ) , trying to remove last frame " < < endl ;
# endif
// Remove the empty last frame, if it's an auto-created one (e.g. a
// continuation on the next page). Not when the user just created it!
if ( m_frames . last ( ) - > frameBehavior ( ) = = KWFrame : : AutoExtendFrame
& & m_frames . last ( ) - > minimumFrameHeight ( ) < 1E-10 ) { // i.e. equal to 0
deleteFrame ( m_frames . last ( ) , true ) ;
m_doc - > frameChanged ( 0L ) ;
}
if ( m_doc - > processingType ( ) = = KWDocument : : WP ) {
bool removed = m_doc - > tryRemovingPages ( ) ;
// Do all the recalc in one go. Speeds up deleting many pages.
if ( removed )
m_doc - > afterRemovePages ( ) ;
}
}
// Handle the case where the last frame is in AutoExtendFrame mode
// and there is less text than space
else if ( ! lastFormatted & & bottom + 2 < availHeight & &
( m_frames . last ( ) - > frameBehavior ( ) = = KWFrame : : AutoExtendFrame & & ! isProtectSize ( ) ) )
{
slotAfterFormattingTooMuchSpace ( bottom ) ;
* abort = false ;
}
if ( m_doc - > processingType ( ) = = KWDocument : : WP
& & this = = m_doc - > frameSet ( 0 ) )
{
if ( m_lastTextDocHeight ! = textDocument ( ) - > height ( ) )
{
m_lastTextDocHeight = textDocument ( ) - > height ( ) ;
emit mainTextHeightChanged ( ) ;
}
}
}
// This is called when a text frame with behaviour AutoCreateNewFrame
// has more text than available frame height, so we need to create a new page
// so that a followup frame is created for this one
bool KWTextFrameSet : : createNewPageAndNewFrame ( KoTextParag * lastFormatted , int /*difference*/ )
{
KWFrame * lastFrame = m_frames . last ( ) ;
// This is only going to help us if the new frame is reconnected. Otherwise bail out.
if ( ! lastFrame | | lastFrame - > newFrameBehavior ( ) ! = KWFrame : : Reconnect ) {
kdDebug ( 32002 ) < < name ( ) < < " : frame is AutoCreateNewFrame but not Reconnect !?!? Aborting. " < < endl ;
m_textobj - > setLastFormattedParag ( 0 ) ;
return true ; // abort
}
//#ifdef DEBUG_FORMAT_MORE
kdDebug ( 32002 ) < < " createNewPageAndNewFrame creating new frame in frameset " < < name ( ) < < endl ;
//#endif
uint oldCount = m_frames . count ( ) ;
int lastPageNumber = m_doc - > pageManager ( ) - > lastPageNumber ( ) ;
kdDebug ( 32002 ) < < " last frame= " < < lastFrame < < " pagenum= " < < lastFrame - > pageNumber ( ) < < " lastPageNumber= " < < lastPageNumber < < " m_frames count= " < < oldCount < < endl ;
// First create a new page for it if necessary
if ( lastFrame - > pageNumber ( ) = = lastPageNumber )
{
// Let's first check if it will give us more space than we
// already have left in this page. Otherwise we'll loop infinitely.
int heightWeWillGet = 0 ; // in LU
if ( isMainFrameset ( ) ) // is never added in the framesToCopyOnNewPage
heightWeWillGet + = m_doc - > ptToLayoutUnitPixY ( m_frames . last ( ) - > height ( ) ) ;
else {
TQPtrList < KWFrame > framesToCopy = m_doc - > framesToCopyOnNewPage ( lastPageNumber ) ;
TQPtrListIterator < KWFrame > frameIt ( framesToCopy ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
if ( frameIt . current ( ) - > frameSet ( ) = = this & &
frameIt . current ( ) - > newFrameBehavior ( ) = = KWFrame : : Reconnect )
heightWeWillGet + = m_doc - > ptToLayoutUnitPixY ( frameIt . current ( ) - > height ( ) ) ;
}
// This logic doesn't applies to tables though, since they can be broken over multiple pages
// TODO: lastFormatted->containsTable() or so (containsPageBreakableItem rather).
// "difference" doesn't apply if we're pasting multiple paragraphs.
// We want to compare the height of one paragraph, not all the missing height.
KoTextParag * parag = lastFormatted ? lastFormatted : textDocument ( ) - > lastParag ( ) ;
// In fact the parag height isn't the right thing to test for - we should check
// for the highest character that remains to be positioned.
// Testcase: many big inline pictures in one paragraph.
int paragHeight = parag - > rect ( ) . height ( ) ;
kdDebug ( 32002 ) < < " height we will get in the new page: " < < heightWeWillGet < < " parag " < < parag < < " height: " < < paragHeight < < endl ;
if ( heightWeWillGet < paragHeight & & ! m_groupmanager )
{
kdDebug ( 32002 ) < < " not enough height on the new page, not worth it " < < endl ;
m_textobj - > setLastFormattedParag ( 0 ) ;
return true ; // abort
}
KWPage * page = m_doc - > appendPage ( ) ;
if ( ! m_doc - > isLoading ( ) )
m_doc - > afterInsertPage ( page - > pageNumber ( ) ) ;
kdDebug ( 32002 ) < < " now frames count= " < < m_frames . count ( ) < < endl ;
}
// Maybe creating the new page created the frame in this frameset, then we're done
// Otherwise let's create it ourselves:
if ( m_frames . count ( ) = = oldCount )
{
Q_ASSERT ( ! isMainFrameset ( ) ) ; // ouch, should have gone to the appendPage case above...
// Otherwise, create a new frame on next page
kdDebug ( 32002 ) < < " createNewPageAndNewFrame creating frame on page " < < lastFrame - > pageNumber ( ) + 1 < < endl ;
KWFrame * frm = lastFrame - > getCopy ( ) ;
frm - > moveBy ( 0 , m_doc - > pageManager ( ) - > page ( frm ) - > height ( ) ) ;
addFrame ( frm ) ;
}
updateFrames ( ) ;
Q_ASSERT ( frame ( 0 ) & & frame ( 0 ) - > frameStack ( ) ) ;
frame ( 0 ) - > frameStack ( ) - > update ( ) ;
/// We don't want to start from the beginning every time !
////m_doc->invalidate();
// Reformat the last paragraph. If it's over the two pages, it will need
// the new page (e.g. for inline frames that need internalToDocument to work)
if ( lastFormatted )
lastFormatted = lastFormatted - > prev ( ) ;
else
lastFormatted = textDocument ( ) - > lastParag ( ) ;
if ( lastFormatted )
{
m_textobj - > setLastFormattedParag ( lastFormatted ) ;
lastFormatted - > invalidate ( 0 ) ;
//This was a way to format the rest from here (recursively), but it didn't help much ensureCursorVisible()
//So instead I fixed formatMore to return formatMore(2) itself.
//m_textobj->formatMore( 2 );
return false ; // keep going
}
m_doc - > delayedRepaintAllViews ( ) ;
return false ; // all done
}
double KWTextFrameSet : : footNoteSize ( KWFrame * theFrame )
{
double tmp = 0.0 ;
int page = theFrame - > pageNumber ( ) ;
TQPtrListIterator < KWFrameSet > fit = m_doc - > framesetsIterator ( ) ;
for ( ; fit . current ( ) ; + + fit )
{
if ( ( fit . current ( ) - > isFootNote ( ) | | fit . current ( ) - > isEndNote ( ) ) & &
fit . current ( ) - > isVisible ( ) )
{
KWFrame * frm = fit . current ( ) - > frame ( 0 ) ;
if ( frm - > pageNumber ( ) = = page )
tmp + = frm - > innerHeight ( ) + m_doc - > ptFootnoteBodySpacing ( ) ;
}
}
return tmp ;
}
double KWTextFrameSet : : footerHeaderSizeMax ( KWFrame * theFrame )
{
KWPage * page = m_doc - > pageManager ( ) - > page ( theFrame ) ;
Q_ASSERT ( page ) ;
if ( ! page )
return 0 ;
double tmp = page - > height ( ) - page - > bottomMargin ( ) - page - > topMargin ( ) - 40 ; //default min 40 for page size
bool header = theFrame - > frameSet ( ) - > isAHeader ( ) ;
if ( header ? m_doc - > isHeaderVisible ( ) : m_doc - > isFooterVisible ( ) )
{
TQPtrListIterator < KWFrameSet > fit = m_doc - > framesetsIterator ( ) ;
for ( ; fit . current ( ) ; + + fit )
{
bool state = header ? fit . current ( ) - > isAFooter ( ) : fit . current ( ) - > isAHeader ( ) ;
if ( fit . current ( ) - > isVisible ( ) & & state )
{
KWFrame * frm = fit . current ( ) - > frame ( 0 ) ;
if ( frm - > pageNumber ( ) = = page - > pageNumber ( ) )
{
return ( tmp - frm - > innerHeight ( ) - footNoteSize ( theFrame ) ) ;
}
}
}
}
if ( theFrame - > frameSet ( ) - > isHeaderOrFooter ( ) )
return ( tmp - footNoteSize ( theFrame ) ) ;
return tmp ;
}
void KWTextFrameSet : : frameResized ( KWFrame * theFrame , bool invalidateLayout )
{
kdDebug ( 32002 ) < < " KWTextFrameSet::frameResized " < < theFrame < < " " < < * theFrame < < " invalidateLayout= " < < invalidateLayout < < endl ;
if ( theFrame - > height ( ) < 0 )
return ; // safety!
KWFrameSet * fs = theFrame - > frameSet ( ) ;
Q_ASSERT ( fs = = this ) ;
fs - > updateFrames ( ) ; // update e.g. available height
Q_ASSERT ( frame ( 0 ) & & frame ( 0 ) - > frameStack ( ) ) ;
frame ( 0 ) - > frameStack ( ) - > update ( ) ;
theFrame - > updateRulerHandles ( ) ;
// Do a full KWFrameLayout if this will have influence on other frames, i.e.:
// * if we resized the last main text frame (the one before the first endnote)
// * if we resized an endnote
// Delay it though, to get the full height first.
if ( fs - > isMainFrameset ( ) | | fs - > isEndNote ( ) )
m_doc - > delayedRecalcFrames ( theFrame - > pageNumber ( ) ) ;
// * if we resized a header, footer, or footnote
else if ( fs - > frameSetInfo ( ) ! = KWFrameSet : : FI_BODY )
m_doc - > recalcFrames ( theFrame - > pageNumber ( ) , - 1 ) ; // warning this can delete theFrame!
// m_doc->frameChanged( theFrame );
// Warning, can't call layout() (frameChanged calls it)
// from here, since it calls formatMore() !
if ( invalidateLayout )
m_doc - > invalidate ( this ) ;
// Can't repaint directly, we might be in a paint event already
m_doc - > delayedRepaintAllViews ( ) ;
}
bool KWTextFrameSet : : isFrameEmpty ( KWFrame * theFrame )
{
KoTextParag * lastParag = textDocument ( ) - > lastParag ( ) ;
// The problem is that if we format things here, and don't emit afterFormatting,
// we won't resize autoresize frames properly etc. (e.g. endnotes)
// Testcase for this problem: werner's footnote-1.doc
//ensureFormatted( lastParag, false ); // maybe true here would do too? slow if maintextframeset though.
if ( ! lastParag - > isValid ( ) )
return false ; // we don't know yet
int bottom = lastParag - > rect ( ) . top ( ) + lastParag - > rect ( ) . height ( ) ;
if ( theFrame - > frameSet ( ) = = this ) // safety check
{
kdDebug ( ) < < " KWTextFrameSet::isFrameEmpty text bottom=(LU) " < < bottom < < " theFrame= " < < theFrame < < " " < < * theFrame < < " its internalY(LU)= " < < m_doc - > ptToLayoutUnitPixY ( theFrame - > internalY ( ) ) < < endl ;
return bottom < m_doc - > ptToLayoutUnitPixY ( theFrame - > internalY ( ) ) ;
}
kdWarning ( ) < < " KWTextFrameSet::isFrameEmpty called for frame " < < theFrame < < " which isn't a child of ours! " < < endl ;
if ( theFrame - > frameSet ( ) ! = 0L & & theFrame - > frameSet ( ) - > name ( ) ! = 0L )
kdDebug ( ) < < " (this is " < < name ( ) < < " and the frame belongs to " < < theFrame - > frameSet ( ) - > name ( ) < < " ) " < < endl ;
return false ;
}
bool KWTextFrameSet : : canRemovePage ( int num )
{
kdDebug ( ) < < " KWTextFrameSet( " < < name ( ) < < " )::canRemovePage " < < num < < endl ;
// No frame on that page ? ok for us then
if ( num < m_firstPage | | num > = ( int ) m_framesInPage . size ( ) + m_firstPage ) {
kdDebug ( ) < < " No frame on that page. Number of frames: " < < frameCount ( ) < < endl ;
return true ;
}
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( num ) ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
KWFrame * theFrame = frameIt . current ( ) ;
kdDebug ( ) < < " canRemovePage: looking at " < < theFrame < < " pageNum= " < < theFrame - > pageNumber ( ) < < endl ;
Q_ASSERT ( theFrame - > pageNumber ( ) = = num ) ;
Q_ASSERT ( theFrame - > frameSet ( ) = = this ) ;
bool isEmpty = isFrameEmpty ( theFrame ) ;
kdDebug ( ) < < " KWTextFrameSet( " < < name ( ) < < " )::canRemovePage "
< < " found a frame on page " < < num < < " empty: " < < isEmpty < < endl ;
// Ok, so we have a frame on that page -> we can't remove it unless it's a copied frame OR it's empty
bool isCopy = theFrame - > isCopy ( ) & & frameIt . current ( ) ! = m_frames . first ( ) ;
if ( ! isCopy & & ! isEmpty )
return false ;
}
return true ;
}
void KWTextFrameSet : : deleteFrame ( unsigned int num , bool remove , bool recalc )
{
KWFrame * frm = m_frames . at ( num ) ;
kdDebug ( ) < < " KWTextFrameSet( " < < name ( ) < < " )::deleteFrame " < < frm < < " ( " < < num < < " ) " < < endl ;
if ( frm )
emit frameDeleted ( frm ) ;
KWFrameSet : : deleteFrame ( num , remove , recalc ) ;
}
void KWTextFrameSet : : updateViewArea ( TQWidget * w , KWViewMode * viewMode , const TQPoint & nPointBottom )
{
if ( ! isVisible ( viewMode ) )
return ;
int ah = availableHeight ( ) ; // make sure that it's not -1
# ifdef DEBUG_VIEWAREA
kdDebug ( 32002 ) < < " KWTextFrameSet::updateViewArea " < < ( void * ) w < < " " < < w - > name ( )
< < " nPointBottom= " < < nPointBottom . x ( ) < < " , " < < nPointBottom . y ( )
< < " availHeight= " < < ah < < " textDocument()->height()= " < < textDocument ( ) - > height ( ) < < endl ;
# endif
// Find last page that is visible
int maxPage = m_doc - > pageManager ( ) - > pageNumber ( m_doc - > unzoomItY ( nPointBottom . y ( ) ) ) ;
int maxY = 0 ;
if ( maxPage < m_firstPage | | maxPage > = ( int ) m_framesInPage . size ( ) + m_firstPage )
maxY = ah ;
else
{
// Find frames on that page, and keep the max bottom, in internal coordinates
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( maxPage ) ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
maxY = TQMAX ( maxY , m_doc - > ptToLayoutUnitPixY ( frameIt . current ( ) - > internalY ( ) + frameIt . current ( ) - > innerHeight ( ) ) ) ;
}
}
# ifdef DEBUG_VIEWAREA
kdDebug ( 32002 ) < < " KWTextFrameSet ( " < < name ( ) < < " )::updateViewArea maxY now " < < maxY < < endl ;
# endif
m_textobj - > setViewArea ( w , maxY ) ;
m_textobj - > formatMore ( 2 ) ;
}
KCommand * KWTextFrameSet : : setPageBreakingCommand ( KoTextCursor * cursor , int pageBreaking )
{
if ( ! textDocument ( ) - > hasSelection ( KoTextDocument : : Standard ) & &
static_cast < KWTextParag * > ( cursor - > parag ( ) ) - > pageBreaking ( ) = = pageBreaking )
return 0L ; // No change needed.
m_textobj - > emitHideCursor ( ) ;
m_textobj - > storeParagUndoRedoInfo ( cursor ) ;
if ( ! textDocument ( ) - > hasSelection ( KoTextDocument : : Standard ) ) {
KWTextParag * parag = static_cast < KWTextParag * > ( cursor - > parag ( ) ) ;
parag - > setPageBreaking ( pageBreaking ) ;
m_textobj - > setLastFormattedParag ( cursor - > parag ( ) ) ;
}
else
{
KoTextParag * start = textDocument ( ) - > selectionStart ( KoTextDocument : : Standard ) ;
KoTextParag * end = textDocument ( ) - > selectionEnd ( KoTextDocument : : Standard ) ;
m_textobj - > setLastFormattedParag ( start ) ;
for ( ; start & & start ! = end - > next ( ) ; start = start - > next ( ) )
static_cast < KWTextParag * > ( start ) - > setPageBreaking ( pageBreaking ) ;
}
m_textobj - > formatMore ( 2 ) ;
emit repaintChanged ( this ) ;
KoTextObject : : UndoRedoInfo & undoRedoInfo = m_textobj - > undoRedoInfoStruct ( ) ;
undoRedoInfo . newParagLayout . pageBreaking = pageBreaking ;
KoTextParagCommand * cmd = new KoTextParagCommand (
textDocument ( ) , undoRedoInfo . id , undoRedoInfo . eid ,
undoRedoInfo . oldParagLayouts , undoRedoInfo . newParagLayout ,
KoParagLayout : : PageBreaking ) ;
textDocument ( ) - > addCommand ( cmd ) ;
undoRedoInfo . clear ( ) ;
m_textobj - > emitShowCursor ( ) ;
m_textobj - > emitUpdateUI ( true ) ;
m_textobj - > emitEnsureCursorVisible ( ) ;
// ## find a better name for the command
return new KoTextCommand ( m_textobj , /*cmd, */ i18n ( " Change Paragraph Attribute " ) ) ;
}
KCommand * KWTextFrameSet : : pasteOasis ( KoTextCursor * cursor , const TQByteArray & data , bool removeSelected )
{
if ( protectContent ( ) )
return 0 ;
kdDebug ( 32001 ) < < " KWTextFrameSet::pasteOasis data: " < < data . size ( ) < < " bytes " < < endl ;
KMacroCommand * macroCmd = new KMacroCommand ( i18n ( " Paste " ) ) ;
if ( removeSelected & & textDocument ( ) - > hasSelection ( KoTextDocument : : Standard ) )
macroCmd - > addCommand ( m_textobj - > removeSelectedTextCommand ( cursor , KoTextDocument : : Standard ) ) ;
m_textobj - > emitHideCursor ( ) ;
m_textobj - > setLastFormattedParag ( cursor - > parag ( ) - > prev ( ) ?
cursor - > parag ( ) - > prev ( ) : cursor - > parag ( ) ) ;
KWOasisPasteCommand * cmd = new KWOasisPasteCommand ( textDocument ( ) , cursor - > parag ( ) - > paragId ( ) , cursor - > index ( ) , data ) ;
textDocument ( ) - > addCommand ( cmd ) ;
macroCmd - > addCommand ( new KoTextCommand ( m_textobj , /*cmd, */ TQString ( ) ) ) ;
* cursor = * ( cmd - > execute ( cursor ) ) ;
// not enough when pasting many pages. We need the cursor's parag to be formatted.
//m_textobj->formatMore( 2 );
ensureFormatted ( cursor - > parag ( ) ) ;
emit repaintChanged ( this ) ;
m_textobj - > emitEnsureCursorVisible ( ) ;
m_textobj - > emitUpdateUI ( true ) ;
m_textobj - > emitShowCursor ( ) ;
m_textobj - > selectionChangedNotify ( ) ;
return macroCmd ;
}
void KWTextFrameSet : : insertTOC ( KoTextCursor * cursor )
{
m_textobj - > emitHideCursor ( ) ;
KMacroCommand * macroCmd = new KMacroCommand ( i18n ( " Insert Table of Contents " ) ) ;
// Remove old TOC
KoTextCursor * cur = KWInsertTOCCommand : : removeTOC ( this , cursor , macroCmd ) ;
// Insert new TOC
KoTextDocCommand * cmd = new KWInsertTOCCommand ( this , cur ? cur - > parag ( ) : cursor - > parag ( ) ) ;
textDocument ( ) - > addCommand ( cmd ) ;
macroCmd - > addCommand ( new KoTextCommand ( m_textobj , TQString ( ) ) ) ;
* cursor = * ( cmd - > execute ( cursor ) ) ;
m_textobj - > setLastFormattedParag ( textDocument ( ) - > firstParag ( ) ) ;
m_textobj - > formatMore ( 2 ) ;
emit repaintChanged ( this ) ;
m_textobj - > emitEnsureCursorVisible ( ) ;
m_textobj - > emitUpdateUI ( true ) ;
m_textobj - > emitShowCursor ( ) ;
m_doc - > addCommand ( macroCmd ) ;
}
KNamedCommand * KWTextFrameSet : : insertFrameBreakCommand ( KoTextCursor * cursor )
{
KMacroCommand * macroCmd = new KMacroCommand ( TQString ( ) ) ;
macroCmd - > addCommand ( m_textobj - > insertParagraphCommand ( cursor ) ) ;
KWTextParag * parag = static_cast < KWTextParag * > ( cursor - > parag ( ) ) ;
if ( parag - > prev ( ) ) {
parag = static_cast < KWTextParag * > ( parag - > prev ( ) ) ;
cursor - > setParag ( parag ) ;
cursor - > setIndex ( parag - > length ( ) - 1 ) ;
}
macroCmd - > addCommand ( setPageBreakingCommand ( cursor , parag - > pageBreaking ( ) | KoParagLayout : : HardFrameBreakAfter ) ) ;
Q_ASSERT ( parag - > next ( ) ) ;
if ( parag - > next ( ) ) {
cursor - > setParag ( parag - > next ( ) ) ;
cursor - > setIndex ( 0 ) ;
}
return macroCmd ;
}
void KWTextFrameSet : : insertFrameBreak ( KoTextCursor * cursor )
{
clearUndoRedoInfo ( ) ;
m_textobj - > emitHideCursor ( ) ;
KNamedCommand * cmd = insertFrameBreakCommand ( cursor ) ;
cmd - > setName ( i18n ( " Insert Break After Paragraph " ) ) ;
m_doc - > addCommand ( cmd ) ;
m_textobj - > setLastFormattedParag ( cursor - > parag ( ) ) ;
m_textobj - > formatMore ( 2 ) ;
emit repaintChanged ( this ) ;
m_textobj - > emitEnsureCursorVisible ( ) ;
m_textobj - > emitUpdateUI ( true ) ;
m_textobj - > emitShowCursor ( ) ;
}
TQRect KWTextFrameSet : : paragRect ( KoTextParag * parag ) const
{
// ## Warning. Imagine a paragraph cut in two pieces (at the line-level),
// between two columns. A single rect in internal coords, but two rects in
// normal coords. TQRect( topLeft, bottomRight ) is just plain wrong.
// Currently this method is only used for "ensure visible" so that's fine, but
// we shouldn't use it for more precise stuff.
KoPoint p ;
( void ) internalToDocument ( parag - > rect ( ) . topLeft ( ) , p ) ;
TQPoint topLeft = m_doc - > zoomPoint ( p ) ;
( void ) internalToDocument ( parag - > rect ( ) . bottomRight ( ) , p ) ;
TQPoint bottomRight = m_doc - > zoomPoint ( p ) ;
return TQRect ( topLeft , bottomRight ) ;
}
void KWTextFrameSet : : findPosition ( const KoPoint & dPoint , KoTextParag * & parag , int & index )
{
KoTextCursor cursor ( textDocument ( ) ) ;
TQPoint iPoint ;
if ( documentToInternal ( dPoint , iPoint ) )
{
cursor . place ( iPoint , textDocument ( ) - > firstParag ( ) ) ;
parag = cursor . parag ( ) ;
index = cursor . index ( ) ;
}
else
{
// Not found, maybe under everything ?
parag = textDocument ( ) - > lastParag ( ) ;
if ( parag )
index = parag - > length ( ) - 1 ;
}
}
bool KWTextFrameSet : : minMaxInternalOnPage ( int pageNum , int & topLU , int & bottomLU ) const
{
TQPtrListIterator < KWFrame > frameIt ( framesInPage ( pageNum ) ) ;
if ( ! frameIt . current ( ) )
return false ;
// Look at all frames in the page, and keep min and max "internalY" positions
double topPt = frameIt . current ( ) - > internalY ( ) ;
double bottomPt = topPt + frameIt . current ( ) - > height ( ) ;
for ( ; frameIt . current ( ) ; + + frameIt )
{
double y = frameIt . current ( ) - > internalY ( ) ;
topPt = TQMIN ( topPt , y ) ;
bottomPt = TQMAX ( bottomPt , y + frameIt . current ( ) - > height ( ) ) ;
}
// Convert to layout units
topLU = m_doc - > ptToLayoutUnitPixY ( topPt ) ;
bottomLU = m_doc - > ptToLayoutUnitPixY ( bottomPt ) ;
return true ;
}
KoTextParag * KWTextFrameSet : : paragAtLUPos ( int yLU ) const
{
KoTextParag * parag = textDocument ( ) - > firstParag ( ) ;
for ( ; parag ; parag = parag - > next ( ) )
{
if ( parag - > rect ( ) . bottom ( ) > = yLU )
return parag ;
}
return 0L ;
}
KCommand * KWTextFrameSet : : deleteAnchoredFrame ( KWAnchor * anchor )
{
kdDebug ( ) < < " KWTextFrameSet::deleteAnchoredFrame anchor->index= " < < anchor - > index ( ) < < endl ;
Q_ASSERT ( anchor ) ;
KoTextCursor c ( textDocument ( ) ) ;
c . setParag ( anchor - > paragraph ( ) ) ;
c . setIndex ( anchor - > index ( ) ) ;
textDocument ( ) - > setSelectionStart ( KoTextDocument : : Temp , & c ) ;
c . setIndex ( anchor - > index ( ) + 1 ) ;
textDocument ( ) - > setSelectionEnd ( KoTextDocument : : Temp , & c ) ;
KCommand * cmd = m_textobj - > removeSelectedTextCommand ( & c , KoTextDocument : : Temp ) ;
m_doc - > repaintAllViews ( ) ;
return cmd ;
}
bool KWTextFrameSet : : hasSelection ( ) const
{
return m_textobj - > hasSelection ( ) ;
}
TQString KWTextFrameSet : : selectedText ( ) const
{
return m_textobj - > selectedText ( ) ;
}
TQString KWTextFrameSet : : toPlainText ( ) const
{
return m_textobj - > textDocument ( ) - > plainText ( ) ;
}
void KWTextFrameSet : : highlightPortion ( KoTextParag * parag , int index , int length , KWCanvas * canvas , bool repaint , KDialogBase * dialog )
{
Q_ASSERT ( isVisible ( ) ) ;
Q_ASSERT ( m_textobj - > isVisible ( ) ) ;
//kdDebug() << "highlighting in " << name() << " parag=" << parag->paragId() << " index=" << index << " repaint=" << repaint << endl;
m_textobj - > highlightPortion ( parag , index , length , repaint ) ;
if ( repaint ) {
// Position the cursor
canvas - > editTextFrameSet ( this , parag , index ) ;
// Ensure text is fully visible
TQRect expose = canvas - > viewMode ( ) - > normalToView ( paragRect ( parag ) ) ;
canvas - > ensureVisible ( ( expose . left ( ) + expose . right ( ) ) / 2 , // point = center of the rect
( expose . top ( ) + expose . bottom ( ) ) / 2 ,
( expose . right ( ) - expose . left ( ) ) / 2 , // margin = half-width of the rect
( expose . bottom ( ) - expose . top ( ) ) / 2 ) ;
if ( dialog ) {
//kdDebug() << k_funcinfo << " dialog=" << dialog << " avoiding rect=" << expose << endl;
TQRect globalRect ( expose ) ;
globalRect . moveTopLeft ( canvas - > mapToGlobal ( globalRect . topLeft ( ) ) ) ;
KDialog : : avoidArea ( dialog , globalRect ) ;
}
}
}
void KWTextFrameSet : : removeHighlight ( bool repaint )
{
m_textobj - > removeHighlight ( repaint ) ;
}
void KWTextFrameSet : : clearUndoRedoInfo ( )
{
m_textobj - > clearUndoRedoInfo ( ) ;
}
void KWTextFrameSet : : applyStyleChange ( KoStyleChangeDefMap changed )
{
m_textobj - > applyStyleChange ( changed ) ;
}
// KoTextFormatInterface methods
KoTextFormat * KWTextFrameSet : : currentFormat ( ) const
{
return m_textobj - > currentFormat ( ) ;
}
KCommand * KWTextFrameSet : : setChangeCaseOfTextCommand ( KoChangeCaseDia : : TypeOfCase _type )
{
KoTextDocument * textdoc = m_textobj - > textDocument ( ) ;
textdoc - > selectAll ( KoTextDocument : : Standard ) ;
KoTextCursor * cursor = new KoTextCursor ( textDocument ( ) ) ;
KCommand * cmd = m_textobj - > changeCaseOfText ( cursor , _type ) ;
textdoc - > removeSelection ( KoTextDocument : : Standard ) ;
delete cursor ;
return cmd ;
}
KCommand * KWTextFrameSet : : setFormatCommand ( const KoTextFormat * newFormat , int flags , bool zoomFont )
{
m_textobj - > textDocument ( ) - > selectAll ( KoTextDocument : : Temp ) ;
KCommand * cmd = m_textobj - > setFormatCommand ( 0L , 0L , newFormat , flags , zoomFont , KoTextDocument : : Temp ) ;
m_textobj - > textDocument ( ) - > removeSelection ( KoTextDocument : : Temp ) ;
return cmd ;
}
const KoParagLayout * KWTextFrameSet : : currentParagLayoutFormat ( ) const
{
return m_textobj - > currentParagLayoutFormat ( ) ;
}
bool KWTextFrameSet : : rtl ( ) const
{
return m_textobj - > rtl ( ) ;
}
KCommand * KWTextFrameSet : : setParagLayoutFormatCommand ( KoParagLayout * newLayout , int flags , int marginIndex )
{
return m_textobj - > setParagLayoutFormatCommand ( newLayout , flags , marginIndex ) ;
}
class KWFootNoteVarList : public TQPtrList < KWFootNoteVariable >
{
protected :
virtual int compareItems ( TQPtrCollection : : Item a , TQPtrCollection : : Item b )
{
KWFootNoteVariable * vara = ( ( KWFootNoteVariable * ) a ) ;
KWFootNoteVariable * varb = ( ( KWFootNoteVariable * ) b ) ;
if ( vara - > paragraph ( ) = = varb - > paragraph ( ) ) {
// index() is a bit slow. But this is only called when there are
// two footnotes in the same paragraph.
int indexa = vara - > index ( ) ;
int indexb = varb - > index ( ) ;
return indexa < indexb ? - 1 : indexa = = indexb ? 0 : 1 ;
}
if ( vara - > paragraph ( ) - > paragId ( ) < varb - > paragraph ( ) - > paragId ( ) )
return - 1 ;
return 1 ;
}
} ;
void KWTextFrameSet : : renumberFootNotes ( bool repaint )
{
KWFootNoteVarList lst ;
TQPtrListIterator < KoTextCustomItem > cit ( textDocument ( ) - > allCustomItems ( ) ) ;
for ( ; cit . current ( ) ; + + cit )
{
KWFootNoteVariable * fnv = dynamic_cast < KWFootNoteVariable * > ( cit . current ( ) ) ;
if ( fnv & & ! fnv - > isDeleted ( ) & & ( fnv - > frameSet ( ) & & ! fnv - > frameSet ( ) - > isDeleted ( ) ) )
lst . append ( fnv ) ;
}
lst . sort ( ) ;
short int footNoteVarNumber = 0 ; // absolute order number [internal, not saved nor displayed]
short int endNoteVarNumber = 0 ;
short int footNoteNumDisplay = 1 ; // the number being displayed
short int endNoteNumDisplay = 1 ;
bool needRepaint = false ;
TQPtrListIterator < KWFootNoteVariable > vit ( lst ) ;
//create a list with all manual footnotes numbers
TQValueList < int > addedNums ;
for ( ; vit . current ( ) ; + + vit )
{
KWFootNoteVariable * var = vit . current ( ) ;
if ( var - > numberingType ( ) = = KWFootNoteVariable : : Manual )
{
uint const num = var - > text ( ) . toUInt ( ) ;
if ( num ! = 0 )
addedNums . append ( num ) ;
}
}
for ( vit . toFirst ( ) ; vit . current ( ) ; )
{
KWFootNoteVariable * var = vit . current ( ) ;
bool endNote = var - > noteType ( ) = = EndNote ;
short int & varNumber = endNote ? endNoteVarNumber : footNoteVarNumber ;
short int & numDisplay = endNote ? endNoteNumDisplay : footNoteNumDisplay ;
+ + varNumber ;
bool changed = false ;
if ( varNumber ! = var - > num ( ) | | var - > numberingType ( ) = = KWFootNoteVariable : : Manual )
{
changed = true ;
var - > setNum ( varNumber ) ;
}
if ( var - > numberingType ( ) = = KWFootNoteVariable : : Auto )
{
if ( addedNums . contains ( numDisplay ) ! = 0 ) // the automatic generated number should not be equal to a manual one
{
numDisplay + + ;
continue ; //try with the next number
}
if ( numDisplay ! = var - > numDisplay ( ) )
{
changed = true ;
var - > setNumDisplay ( numDisplay ) ;
}
numDisplay + + ;
}
if ( changed )
{
if ( var - > frameSet ( ) ) //safety
{
TQString fsName = endNote ? i18n ( " Endnote %1 " ) : i18n ( " Footnote %1 " ) ;
if ( var - > numberingType ( ) = = KWFootNoteVariable : : Manual )
var - > frameSet ( ) - > setName ( m_doc - > generateFramesetName ( fsName ) ) ;
else
var - > frameSet ( ) - > setName ( fsName . arg ( var - > text ( ) ) ) ;
var - > frameSet ( ) - > setCounterText ( var - > text ( ) ) ;
}
var - > resize ( ) ;
var - > paragraph ( ) - > invalidate ( 0 ) ;
var - > paragraph ( ) - > setChanged ( true ) ;
needRepaint = true ;
}
+ + vit ;
}
if ( needRepaint & & repaint )
m_doc - > slotRepaintChanged ( this ) ;
}
KoTextDocCommand * KWTextFrameSet : : deleteTextCommand ( KoTextDocument * textdoc , int id , int index , const TQMemArray < KoTextStringChar > & str , const CustomItemsMap & customItemsMap , const TQValueList < KoParagLayout > & oldParagLayouts )
{
return new KWTextDeleteCommand ( textdoc , id , index , str , customItemsMap , oldParagLayouts ) ;
}
TQByteArray KWTextFrameSet : : sortText ( SortType type ) const
{
const KoTextCursor c1 = textDocument ( ) - > selectionStartCursor ( KoTextDocument : : Standard ) ;
const KoTextCursor c2 = textDocument ( ) - > selectionEndCursor ( KoTextDocument : : Standard ) ;
if ( c1 . parag ( ) = = c2 . parag ( ) )
return TQByteArray ( ) ;
else
{
// ( paragraph text -> paragraph ) map. Note that this sorts on the key automatically.
TQMap < TQString , const KoTextParag * > sortMap ;
sortMap . insert ( c1 . parag ( ) - > toString ( 0 ) , c1 . parag ( ) ) ;
const KoTextParag * p = c1 . parag ( ) - > next ( ) ;
while ( p & & p ! = c2 . parag ( ) ) {
sortMap . insert ( p - > toString ( 0 ) , p ) ;
p = p - > next ( ) ;
}
sortMap . insert ( c2 . parag ( ) - > toString ( 0 ) , c2 . parag ( ) ) ;
typedef TQValueList < const KoTextParag * > ParagList ;
ParagList sortedParags = sortMap . values ( ) ;
if ( type = = KW_SORTDECREASE )
{
// I could use an STL algorithm here, but only if TQt was compiled with STL support...
ParagList newList ;
for ( ParagList : : const_iterator it = sortedParags . begin ( ) ,
end = sortedParags . end ( ) ;
it ! = end ; + + it ) {
newList . prepend ( * it ) ;
}
sortedParags = newList ;
}
KWOasisSaver oasisSaver ( m_doc ) ;
oasisSaver . saveParagraphs ( sortedParags ) ;
if ( ! oasisSaver . finish ( ) )
return TQByteArray ( ) ;
return oasisSaver . data ( ) ;
}
}
// This is used when loading (KWTextDocument::loadOasisFootnote)
// and when inserting from the GUI (KWTextFrameSetEdit::insertFootNote),
// so don't add any 'repaint' or 'recalc' code here
KWFootNoteFrameSet * KWTextFrameSet : : insertFootNote ( NoteType noteType , KWFootNoteVariable : : Numbering numType , const TQString & manualString )
{
kdDebug ( ) < < " KWTextFrameSetEdit::insertFootNote " < < endl ;
KWDocument * doc = m_doc ;
KWFootNoteVariable * var = new KWFootNoteVariable ( textDocument ( ) , doc - > variableFormatCollection ( ) - > format ( " NUMBER " ) , doc - > variableCollection ( ) , doc ) ;
var - > setNoteType ( noteType ) ;
var - > setNumberingType ( numType ) ;
if ( numType = = KWFootNoteVariable : : Manual )
var - > setManualString ( manualString ) ;
// Now create text frameset which will hold the variable's contents
KWFootNoteFrameSet * fs = new KWFootNoteFrameSet ( doc , i18n ( " Footnotes " ) ) ;
fs - > setFrameSetInfo ( KWFrameSet : : FI_FOOTNOTE ) ;
doc - > addFrameSet ( fs ) ;
// Bind the footnote variable and its text frameset
var - > setFrameSet ( fs ) ;
fs - > setFootNoteVariable ( var ) ;
return fs ;
}
KoVariable * KWTextFrameSet : : variableUnderMouse ( const KoPoint & dPoint )
{
TQPoint iPoint ;
if ( documentToInternal ( dPoint , iPoint ) )
return textObject ( ) - > variableAtPoint ( iPoint ) ;
return 0 ;
}
KoLinkVariable * KWTextFrameSet : : linkVariableUnderMouse ( const KoPoint & dPoint )
{
TQPoint iPoint ;
if ( documentToInternal ( dPoint , iPoint ) )
{
KoLinkVariable * linkVariable = dynamic_cast < KoLinkVariable * > ( textObject ( ) - > variableAtPoint ( iPoint ) ) ;
return linkVariable ;
}
return 0 ;
}
///////////////////////////////////////////////////////////////////////////////
KWTextFrameSetEdit : : KWTextFrameSetEdit ( KWTextFrameSet * fs , KWCanvas * canvas )
: KoTextView ( fs - > textObject ( ) ) , KWFrameSetEdit ( fs , canvas ) , m_rtl ( false )
{
setBackSpeller ( fs - > kWordDocument ( ) - > backSpeller ( ) ) ;
//kdDebug(32001) << "KWTextFrameSetEdit::KWTextFrameSetEdit " << fs->name() << endl;
KoTextView : : setReadWrite ( fs - > kWordDocument ( ) - > isReadWrite ( ) ) ;
KoTextObject * textobj = fs - > textObject ( ) ;
connect ( textobj , TQT_SIGNAL ( selectionChanged ( bool ) ) , canvas , TQT_SIGNAL ( selectionChanged ( bool ) ) ) ;
connect ( fs , TQT_SIGNAL ( frameDeleted ( KWFrame * ) ) , this , TQT_SLOT ( slotFrameDeleted ( KWFrame * ) ) ) ;
connect ( textView ( ) , TQT_SIGNAL ( cut ( ) ) , TQT_SLOT ( cut ( ) ) ) ;
connect ( textView ( ) , TQT_SIGNAL ( copy ( ) ) , TQT_SLOT ( copy ( ) ) ) ;
connect ( textView ( ) , TQT_SIGNAL ( paste ( ) ) , TQT_SLOT ( paste ( ) ) ) ;
updateUI ( true , true ) ;
if ( canvas - > gui ( ) & & canvas - > gui ( ) - > getHorzRuler ( ) )
{
if ( ! textobj - > protectContent ( ) )
canvas - > gui ( ) - > getHorzRuler ( ) - > changeFlags ( KoRuler : : F_INDENTS | KoRuler : : F_TABS ) ;
else
canvas - > gui ( ) - > getHorzRuler ( ) - > changeFlags ( 0 ) ;
}
setOverwriteMode ( canvas - > overwriteMode ( ) ) ;
}
KWTextFrameSetEdit : : ~ KWTextFrameSetEdit ( )
{
//kdDebug(32001) << "KWTextFrameSetEdit::~KWTextFrameSetEdit" << endl;
//m_canvas->gui()->getHorzRuler()->changeFlags(0);
}
KoTextViewIface * KWTextFrameSetEdit : : dcopObject ( )
{
if ( ! dcop )
dcop = new KWordTextFrameSetEditIface ( this ) ;
return dcop ;
}
void KWTextFrameSetEdit : : terminate ( bool removeSelection )
{
disconnect ( textView ( ) - > textObject ( ) , TQT_SIGNAL ( selectionChanged ( bool ) ) , m_canvas , TQT_SIGNAL ( selectionChanged ( bool ) ) ) ;
textView ( ) - > terminate ( removeSelection ) ;
}
void KWTextFrameSetEdit : : slotFrameDeleted ( KWFrame * frm )
{
if ( m_currentFrame = = frm )
m_currentFrame = 0L ;
}
void KWTextFrameSetEdit : : paste ( )
{
TQMimeSource * data = TQApplication : : clipboard ( ) - > data ( ) ;
int provides = KWView : : checkClipboard ( data ) ;
pasteData ( data , provides , false ) ;
}
void KWTextFrameSetEdit : : pasteData ( TQMimeSource * data , int provides , bool drop )
{
if ( provides & KWView : : ProvidesOasis )
{
KCommand * cmd = pasteOasisCommand ( data ) ;
if ( cmd )
frameSet ( ) - > kWordDocument ( ) - > addCommand ( cmd ) ;
}
else if ( provides & KWView : : ProvidesPlainText )
{
// Note: TQClipboard::text() seems to do a better job than encodedData( "text/plain" )
// In particular it handles charsets (in the mimetype).
const TQString text = TQApplication : : clipboard ( ) - > text ( ) ;
const bool removeSelected = ! drop ;
if ( ! text . isEmpty ( ) )
textObject ( ) - > pasteText ( cursor ( ) , text , currentFormat ( ) , removeSelected ) ;
}
else {
kdWarning ( 32002 ) < < " Unhandled case in KWTextFrameSetEdit::pasteData: provides= " < < provides < < endl ;
}
// be sure that the footnote number didn't got erased
KWFootNoteFrameSet * footNote = dynamic_cast < KWFootNoteFrameSet * > ( textFrameSet ( ) ) ;
if ( footNote )
{
KoParagCounter * counter = footNote - > textDocument ( ) - > firstParag ( ) - > counter ( ) ;
if ( ! counter | | ( counter - > numbering ( ) ! = KoParagCounter : : NUM_FOOTNOTE ) )
footNote - > setCounterText ( footNote - > footNoteVariable ( ) - > text ( ) ) ;
frameSet ( ) - > kWordDocument ( ) - > slotRepaintChanged ( frameSet ( ) ) ;
}
}
KCommand * KWTextFrameSetEdit : : pasteOasisCommand ( TQMimeSource * data )
{
// Find which mimetype it was (could be oasis text, oasis presentation etc.)
TQCString returnedTypeMime = KoTextObject : : providesOasis ( data ) ;
if ( ! returnedTypeMime . isEmpty ( ) )
{
TQByteArray arr = data - > encodedData ( returnedTypeMime ) ;
Q_ASSERT ( ! arr . isEmpty ( ) ) ;
if ( arr . size ( ) )
return textFrameSet ( ) - > pasteOasis ( cursor ( ) , arr , true ) ;
}
return 0 ;
}
void KWTextFrameSetEdit : : cut ( )
{
if ( textDocument ( ) - > hasSelection ( KoTextDocument : : Standard ) ) {
copy ( ) ;
textObject ( ) - > removeSelectedText ( cursor ( ) ) ;
}
}
void KWTextFrameSetEdit : : copy ( )
{
if ( textDocument ( ) - > hasSelection ( KoTextDocument : : Standard ) ) {
TQDragObject * drag = newDrag ( 0 ) ;
TQApplication : : clipboard ( ) - > setData ( drag ) ;
}
}
bool KWTextFrameSetEdit : : doIgnoreDoubleSpace ( KoTextParag * parag ,
int index , TQChar ch )
{
if ( textFrameSet ( ) - > kWordDocument ( ) - > allowAutoFormat ( ) )
{
KoAutoFormat * autoFormat = textFrameSet ( ) - > kWordDocument ( ) - > autoFormat ( ) ;
if ( autoFormat )
{
return autoFormat - > doIgnoreDoubleSpace ( parag , index , ch ) ;
}
}
return false ;
}
void KWTextFrameSetEdit : : doAutoFormat ( KoTextCursor * cursor , KoTextParag * parag , int index , TQChar ch )
{
if ( textFrameSet ( ) - > kWordDocument ( ) - > allowAutoFormat ( ) )
{
KoAutoFormat * autoFormat = textFrameSet ( ) - > kWordDocument ( ) - > autoFormat ( ) ;
if ( autoFormat )
autoFormat - > doAutoFormat ( cursor , parag , index , ch , textObject ( ) ) ;
}
}
bool KWTextFrameSetEdit : : doCompletion ( KoTextCursor * cursor , KoTextParag * parag , int index )
{
if ( textFrameSet ( ) - > kWordDocument ( ) - > allowAutoFormat ( ) )
{
KoAutoFormat * autoFormat = textFrameSet ( ) - > kWordDocument ( ) - > autoFormat ( ) ;
if ( autoFormat )
return autoFormat - > doCompletion ( cursor , parag , index , textObject ( ) ) ;
}
return false ;
}
bool KWTextFrameSetEdit : : doToolTipCompletion ( KoTextCursor * cursor , KoTextParag * parag , int index , int keyPressed )
{
if ( textFrameSet ( ) - > kWordDocument ( ) - > allowAutoFormat ( ) )
{
KoAutoFormat * autoFormat = textFrameSet ( ) - > kWordDocument ( ) - > autoFormat ( ) ;
if ( autoFormat )
return autoFormat - > doToolTipCompletion ( cursor , parag , index , textObject ( ) , keyPressed ) ;
}
return false ;
}
void KWTextFrameSetEdit : : showToolTipBox ( KoTextParag * parag , int index , TQWidget * widget , const TQPoint & pos )
{
if ( textFrameSet ( ) - > kWordDocument ( ) - > allowAutoFormat ( ) )
{
KoAutoFormat * autoFormat = textFrameSet ( ) - > kWordDocument ( ) - > autoFormat ( ) ;
if ( autoFormat )
autoFormat - > showToolTipBox ( parag , index , widget , pos ) ;
}
}
void KWTextFrameSetEdit : : removeToolTipCompletion ( )
{
if ( textFrameSet ( ) - > kWordDocument ( ) - > allowAutoFormat ( ) )
{
KoAutoFormat * autoFormat = textFrameSet ( ) - > kWordDocument ( ) - > autoFormat ( ) ;
if ( autoFormat )
autoFormat - > removeToolTipCompletion ( ) ;
}
}
void KWTextFrameSetEdit : : textIncreaseIndent ( )
{
kdDebug ( 32001 ) < < " Increasing list " < < endl ;
m_canvas - > gui ( ) - > getView ( ) - > textIncreaseIndent ( ) ;
}
bool KWTextFrameSetEdit : : textDecreaseIndent ( )
{
if ( currentLeftMargin ( ) > 0 )
{
kdDebug ( 32001 ) < < " Decreasing list " < < endl ;
m_canvas - > gui ( ) - > getView ( ) - > textDecreaseIndent ( ) ;
return true ;
}
else
return false ;
}
void KWTextFrameSetEdit : : startDrag ( )
{
textView ( ) - > dragStarted ( ) ;
m_canvas - > dragStarted ( ) ;
TQDragObject * drag = newDrag ( m_canvas - > viewport ( ) ) ;
if ( ! frameSet ( ) - > kWordDocument ( ) - > isReadWrite ( ) )
drag - > dragCopy ( ) ;
else {
bool move = ( drag - > drag ( ) ) ;
if ( move )
{
#if 0
if ( TQDragObject : : target ( ) ! = m_canvas & & TQDragObject : : target ( ) ! = m_canvas - > viewport ( ) ) {
//This is when dropping text _out_ of KWord. Since we have Move and Copy
//options (Copy being accessed by pressing CTRL), both are possible.
//But is that intuitive enough ? Doesn't the user expect a Copy in all cases ?
//Losing the selected text when dropping out of kword seems quite unexpected to me.
//Undecided about this........
textObject ( ) - > removeSelectedText ( cursor ( ) ) ;
}
# endif
}
}
}
TQDragObject * KWTextFrameSetEdit : : newDrag ( TQWidget * parent )
{
KWTextFrameSet * fs = textFrameSet ( ) ;
return fs - > kWordDocument ( ) - > dragSelected ( parent , fs ) ;
}
void KWTextFrameSetEdit : : ensureCursorVisible ( )
{
//kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible paragId=" << cursor()->parag()->paragId() << " cursor->index()=" << cursor()->index() << endl;
KoTextParag * parag = cursor ( ) - > parag ( ) ;
int idx = cursor ( ) - > index ( ) ;
textFrameSet ( ) - > ensureFormatted ( parag ) ;
KoTextStringChar * chr = parag - > at ( idx ) ;
int cursorHeight = parag - > lineHeightOfChar ( idx ) ;
int x = parag - > rect ( ) . x ( ) + cursor ( ) - > x ( ) ; // this includes +charwidth for an RTL char
//kdDebug() << "parag->rect().x()=" << parag->rect().x() << " x=" << cursor()->x() << endl;
int y = 0 ; int dummy ;
parag - > lineHeightOfChar ( idx , & dummy , & y ) ;
y + = parag - > rect ( ) . y ( ) ;
//kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible y=" << y << endl;
// make sure one char is visible before, and one after
KoTextStringChar * chrLeft = idx > 0 ? chr - 1 : chr ;
// which char is on the left and which one is on the right depends on chr->rightToLeft
int areaLeft = chr - > rightToLeft ? chr - > width : chrLeft - > width ;
int areaRight = chr - > rightToLeft ? chrLeft - > width : chr - > width ;
KoPoint pt ;
KoPoint hintDPoint ;
if ( m_currentFrame )
hintDPoint = m_currentFrame - > topLeft ( ) ;
KWFrame * theFrame = textFrameSet ( ) - > internalToDocumentWithHint ( TQPoint ( x , y ) , pt , hintDPoint ) ;
//kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible frame=" << theFrame << " m_currentFrame=" << m_currentFrame << endl;
if ( theFrame & & m_currentFrame ! = theFrame )
{
m_currentFrame = theFrame ;
m_canvas - > gui ( ) - > getView ( ) - > updatePageInfo ( ) ;
}
TQPoint cursorPos = textFrameSet ( ) - > kWordDocument ( ) - > zoomPoint ( pt ) ;
cursorPos = m_canvas - > viewMode ( ) - > normalToView ( cursorPos ) ;
areaLeft = textFrameSet ( ) - > kWordDocument ( ) - > layoutUnitToPixelX ( areaLeft ) + 1 ;
areaRight = textFrameSet ( ) - > kWordDocument ( ) - > layoutUnitToPixelX ( areaRight ) + 1 ;
cursorHeight = textFrameSet ( ) - > kWordDocument ( ) - > layoutUnitToPixelY ( cursorHeight ) ;
//kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible pt=" << pt << " cursorPos=" << cursorPos
// << " areaLeft=" << areaLeft << " areaRight=" << areaRight << " y=" << y << endl;
m_canvas - > ensureVisible ( cursorPos . x ( ) - areaLeft , cursorPos . y ( ) + cursorHeight / 2 , areaLeft + areaRight , cursorHeight / 2 + 2 ) ;
}
bool KWTextFrameSetEdit : : enterCustomItem ( KoTextCustomItem * customItem , bool fromRight )
{
KWAnchor * anchor = dynamic_cast < KWAnchor * > ( customItem ) ;
if ( anchor ) {
KWFrameSet * frameSet = anchor - > frameSet ( ) ;
if ( frameSet - > type ( ) = = FT_FORMULA | | frameSet - > type ( ) = = FT_TEXT ) {
// store the instance variable we need after "delete this"
KWCanvas * canvas = m_canvas ;
// this will "delete this"!
m_canvas - > editFrameSet ( frameSet ) ;
// We assume that `editFrameSet' succeeded.
if ( fromRight ) {
KWFrameSetEdit * edit = canvas - > currentFrameSetEdit ( ) ;
if ( frameSet - > type ( ) = = FT_FORMULA )
static_cast < KWFormulaFrameSetEdit * > ( edit ) - > moveEnd ( ) ;
else
static_cast < KWTextFrameSetEdit * > ( edit ) - > moveCursor ( MoveEnd ) ;
}
if ( frameSet - > type ( ) = = FT_FORMULA )
{
// A FormulaFrameSetEdit looks a little different from
// a FormulaFrameSet. (Colors)
static_cast < KWFormulaFrameSet * > ( frameSet ) - > setChanged ( ) ;
canvas - > repaintChanged ( frameSet , true ) ;
}
return true ;
}
}
return false ;
}
void KWTextFrameSetEdit : : keyPressEvent ( TQKeyEvent * e )
{
// Handle moving into inline frames (e.g. formula frames).
if ( ! ( e - > state ( ) & ControlButton ) & & ! ( e - > state ( ) & ShiftButton ) )
{
if ( e - > state ( ) ! = Qt : : NoButton )
removeToolTipCompletion ( ) ;
switch ( e - > key ( ) ) {
case Key_Left : {
KoTextCursor * cursor = textView ( ) - > cursor ( ) ;
KoTextParag * parag = cursor - > parag ( ) ;
int index = cursor - > index ( ) ;
if ( index > 0 ) {
KoTextStringChar * ch = parag - > at ( index - 1 ) ;
if ( ch - > isCustom ( ) ) {
KoTextCustomItem * customItem = ch - > customItem ( ) ;
if ( enterCustomItem ( customItem , true ) ) {
// Don't do anything here, "this" is deleted!
return ;
}
}
}
if ( index = = 0 & & ! parag - > prev ( ) )
if ( exitLeft ( ) )
return ;
break ;
}
case Key_Right : {
KoTextCursor * cursor = textView ( ) - > cursor ( ) ;
KoTextParag * parag = cursor - > parag ( ) ;
int index = cursor - > index ( ) ;
if ( index < parag - > length ( ) - 1 ) {
KoTextStringChar * ch = parag - > at ( index ) ;
if ( ch - > isCustom ( ) ) {
KoTextCustomItem * customItem = ch - > customItem ( ) ;
if ( enterCustomItem ( customItem , false ) ) {
// Don't do anything here, "this" is deleted!
return ;
}
}
} else if ( /*at end, covered by previous if, && */ ! parag - > next ( ) )
if ( exitRight ( ) )
return ;
break ;
}
}
}
// Calculate position of tooltip for autocompletion
TQPoint pos = textFrameSet ( ) - > cursorPos ( cursor ( ) , m_canvas , m_currentFrame ) ;
textView ( ) - > handleKeyPressEvent ( e , m_canvas , pos ) ;
}
void KWTextFrameSetEdit : : keyReleaseEvent ( TQKeyEvent * e )
{
textView ( ) - > handleKeyReleaseEvent ( e ) ;
}
void KWTextFrameSetEdit : : imStartEvent ( TQIMEvent * e )
{
textView ( ) - > handleImStartEvent ( e ) ;
}
void KWTextFrameSetEdit : : imComposeEvent ( TQIMEvent * e )
{
textView ( ) - > handleImComposeEvent ( e ) ;
}
void KWTextFrameSetEdit : : imEndEvent ( TQIMEvent * e )
{
textView ( ) - > handleImEndEvent ( e ) ;
}
void KWTextFrameSetEdit : : mousePressEvent ( TQMouseEvent * e , const TQPoint & , const KoPoint & dPoint )
{
if ( dPoint . x ( ) < 0 | | dPoint . y ( ) < 0 )
return ; // Ignore clicks completely outside of the page (e.g. in the gray area, or ruler)
textFrameSet ( ) - > textObject ( ) - > clearUndoRedoInfo ( ) ;
if ( m_currentFrame )
hideCursor ( ) ; // Need to do that with the old m_currentFrame
TQPoint iPoint ;
KWTextFrameSet : : RelativePosition relPos ;
KWFrame * theFrame = textFrameSet ( ) - > documentToInternalMouseSelection ( dPoint , iPoint , relPos , m_canvas - > viewMode ( ) ) ;
if ( theFrame & & m_currentFrame ! = theFrame )
{
m_currentFrame = theFrame ;
m_canvas - > gui ( ) - > getView ( ) - > updatePageInfo ( ) ;
}
if ( m_currentFrame )
{
// Let KoTextView handle the mousepress event - but don't let it start
// a drag if clicking on the left of the text (out of the frame itself)
bool addParag = textView ( ) - > handleMousePressEvent ( e , iPoint , relPos ! = KWTextFrameSet : : LeftOfFrame , frameSet ( ) - > kWordDocument ( ) - > insertDirectCursor ( ) ) ;
// Clicked on the left of the text -> select the whole paragraph
if ( relPos = = KWTextFrameSet : : LeftOfFrame )
textView ( ) - > selectParagUnderCursor ( * textView ( ) - > cursor ( ) ) ;
if ( addParag )
frameSet ( ) - > kWordDocument ( ) - > setModified ( true ) ;
}
// else mightStartDrag = FALSE; necessary?
if ( e - > button ( ) ! = Qt : : LeftButton )
return ;
KoVariable * var = variable ( ) ;
if ( var )
{
KWFootNoteVariable * footNoteVar = dynamic_cast < KWFootNoteVariable * > ( var ) ;
if ( footNoteVar )
{
footNoteVar - > frameSet ( ) - > startEditing ( m_canvas ) ;
// --- and now we are deleted! ---
}
}
}
void KWTextFrameSetEdit : : mouseMoveEvent ( TQMouseEvent * e , const TQPoint & nPoint , const KoPoint & )
{
if ( textView ( ) - > maybeStartDrag ( e ) )
return ;
if ( nPoint . x ( ) < 0 | | nPoint . y ( ) < 0 )
return ; // Ignore clicks completely outside of the page (e.g. in the gray area, or ruler)
TQPoint iPoint ;
KoPoint dPoint = frameSet ( ) - > kWordDocument ( ) - > unzoomPoint ( nPoint ) ;
KWTextFrameSet : : RelativePosition relPos ;
if ( nPoint . y ( ) > 0 & & textFrameSet ( ) - > documentToInternalMouseSelection ( dPoint , iPoint , relPos , m_canvas - > viewMode ( ) ) )
{
if ( relPos = = KWTextFrameSet : : LeftOfFrame )
textView ( ) - > extendParagraphSelection ( iPoint ) ;
else
textView ( ) - > handleMouseMoveEvent ( e , iPoint ) ;
}
}
bool KWTextFrameSetEdit : : openLink ( KoLinkVariable * variable )
{
KWTextFrameSet * fs = textFrameSet ( ) ;
KWDocument * doc = fs - > kWordDocument ( ) ;
if ( doc - > variableCollection ( ) - > variableSetting ( ) - > displayLink ( ) ) {
const TQString url = variable - > url ( ) ;
if ( url . startsWith ( " bkm:// " ) )
{
const KoTextBookmark * bookmark = doc - > bookmarkByName ( url . mid ( 6 ) ) ;
if ( bookmark )
{
cursor ( ) - > setParag ( bookmark - > startParag ( ) ) ;
ensureCursorVisible ( ) ;
return true ;
}
}
KoTextView : : openLink ( variable ) ;
return true ;
}
return false ;
}
void KWTextFrameSetEdit : : openLink ( )
{
KoLinkVariable * v = linkVariable ( ) ;
if ( v )
openLink ( v ) ;
}
void KWTextFrameSetEdit : : mouseReleaseEvent ( TQMouseEvent * , const TQPoint & , const KoPoint & )
{
textView ( ) - > handleMouseReleaseEvent ( ) ;
}
void KWTextFrameSetEdit : : mouseDoubleClickEvent ( TQMouseEvent * e , const TQPoint & , const KoPoint & )
{
textView ( ) - > handleMouseDoubleClickEvent ( e , TQPoint ( ) /* Currently unused */ ) ;
}
void KWTextFrameSetEdit : : dragEnterEvent ( TQDragEnterEvent * e )
{
int provides = KWView : : checkClipboard ( e ) ;
if ( ! frameSet ( ) - > kWordDocument ( ) - > isReadWrite ( ) | | provides = = 0 )
{
e - > ignore ( ) ;
return ;
}
e - > acceptAction ( ) ;
}
void KWTextFrameSetEdit : : dragMoveEvent ( TQDragMoveEvent * e , const TQPoint & nPoint , const KoPoint & )
{
int provides = KWView : : checkClipboard ( e ) ;
if ( ! frameSet ( ) - > kWordDocument ( ) - > isReadWrite ( ) | | provides = = 0 )
{
e - > ignore ( ) ;
return ;
}
// place cursor - unless dropping an image. well it's hard to know if the user
// wants the dropped image to be inline or absolute positioned.
if ( provides & ( KWView : : ProvidesOasis | KWView : : ProvidesPlainText | KWView : : ProvidesFormula ) )
{
TQPoint iPoint ;
KoPoint dPoint = frameSet ( ) - > kWordDocument ( ) - > unzoomPoint ( nPoint ) ;
if ( textFrameSet ( ) - > documentToInternal ( dPoint , iPoint ) )
{
textObject ( ) - > emitHideCursor ( ) ;
placeCursor ( iPoint ) ;
textObject ( ) - > emitShowCursor ( ) ;
}
}
e - > acceptAction ( ) ;
}
void KWTextFrameSetEdit : : dragLeaveEvent ( TQDragLeaveEvent * )
{
}
void KWTextFrameSetEdit : : dropEvent ( TQDropEvent * e , const TQPoint & nPoint , const KoPoint & , KWView * view )
{
int provides = KWView : : checkClipboard ( e ) ;
if ( frameSet ( ) - > kWordDocument ( ) - > isReadWrite ( ) & & provides )
{
e - > acceptAction ( ) ;
KoTextCursor dropCursor ( textDocument ( ) ) ;
TQPoint dropPoint ;
KoPoint dPoint = frameSet ( ) - > kWordDocument ( ) - > unzoomPoint ( nPoint ) ;
if ( ! textFrameSet ( ) - > documentToInternal ( dPoint , dropPoint ) )
return ; // Don't know where to paste
dropCursor . place ( dropPoint , textDocument ( ) - > firstParag ( ) ) ;
kdDebug ( 32001 ) < < " KWTextFrameSetEdit::dropEvent dropCursor at parag= " < < dropCursor . parag ( ) - > paragId ( ) < < " index= " < < dropCursor . index ( ) < < endl ;
if ( ( e - > source ( ) = = m_canvas | |
e - > source ( ) = = m_canvas - > viewport ( ) ) & &
e - > action ( ) = = TQDropEvent : : Move & &
// this is the indicator that the source and dest text objects are the same
textDocument ( ) - > hasSelection ( KoTextDocument : : Standard ) ) {
KCommand * cmd = textView ( ) - > prepareDropMove ( dropCursor ) ;
if ( cmd )
{
KMacroCommand * macroCmd = new KMacroCommand ( i18n ( " Move Text " ) ) ;
macroCmd - > addCommand ( cmd ) ;
cmd = pasteOasisCommand ( e ) ;
if ( cmd )
macroCmd - > addCommand ( cmd ) ;
//relayout textframeset after a dnd otherwise autoextend
//frameset is not re-layouted
textFrameSet ( ) - > layout ( ) ;
frameSet ( ) - > kWordDocument ( ) - > addCommand ( macroCmd ) ;
}
return ;
}
else
{ // drop coming from outside -> forget about current selection
textDocument ( ) - > removeSelection ( KoTextDocument : : Standard ) ;
textObject ( ) - > selectionChangedNotify ( ) ;
}
// The cursor is already correctly positioned, all we need to do is to "paste" the dropped data.
view - > pasteData ( e , true ) ;
}
}
void KWTextFrameSetEdit : : focusInEvent ( )
{
textView ( ) - > focusInEvent ( ) ;
}
void KWTextFrameSetEdit : : focusOutEvent ( )
{
textView ( ) - > focusOutEvent ( ) ;
}
void KWTextFrameSetEdit : : selectAll ( )
{
textObject ( ) - > selectAll ( true ) ;
}
void KWTextFrameSetEdit : : drawCursor ( bool visible )
{
# ifdef DEBUG_CURSOR
kdDebug ( ) < < " KWTextFrameSetEdit::drawCursor " < < visible < < endl ;
# endif
KoTextView : : drawCursor ( visible ) ;
if ( ! cursor ( ) - > parag ( ) )
return ;
if ( ! cursor ( ) - > parag ( ) - > isValid ( ) )
textFrameSet ( ) - > ensureFormatted ( cursor ( ) - > parag ( ) ) ;
if ( ! frameSet ( ) - > kWordDocument ( ) - > isReadWrite ( ) )
return ;
if ( m_canvas - > viewMode ( ) - > hasFrames ( ) & & ! m_currentFrame )
return ;
TQPainter p ( m_canvas - > viewport ( ) ) ;
p . translate ( - m_canvas - > contentsX ( ) , - m_canvas - > contentsY ( ) ) ;
p . setBrushOrigin ( - m_canvas - > contentsX ( ) , - m_canvas - > contentsY ( ) ) ;
textFrameSet ( ) - > drawCursor ( & p , cursor ( ) , visible , m_canvas , m_currentFrame ) ;
}
bool KWTextFrameSetEdit : : pgUpKeyPressed ( )
{
TQRect crect ( m_canvas - > contentsX ( ) , m_canvas - > contentsY ( ) ,
m_canvas - > visibleWidth ( ) , m_canvas - > visibleHeight ( ) ) ;
crect = m_canvas - > viewMode ( ) - > viewToNormal ( crect ) ;
// Go up of 90% of crect.height()
int h = frameSet ( ) - > kWordDocument ( ) - > pixelToLayoutUnitY ( ( int ) ( ( double ) crect . height ( ) * 0.9 ) ) ;
KoTextParag * s = textView ( ) - > cursor ( ) - > parag ( ) ;
KoTextParag * oldParag = s ;
int y = s - > rect ( ) . y ( ) ;
while ( s ) {
if ( y - s - > rect ( ) . y ( ) > = h )
break ;
s = s - > prev ( ) ;
}
if ( ! s )
s = textDocument ( ) - > firstParag ( ) ;
textView ( ) - > cursor ( ) - > setParag ( s ) ;
textView ( ) - > cursor ( ) - > setIndex ( 0 ) ;
if ( s = = oldParag )
{
m_canvas - > viewportScroll ( true ) ;
return false ;
}
return true ;
}
bool KWTextFrameSetEdit : : pgDownKeyPressed ( )
{
TQRect crect ( m_canvas - > contentsX ( ) , m_canvas - > contentsY ( ) ,
m_canvas - > visibleWidth ( ) , m_canvas - > visibleHeight ( ) ) ;
crect = m_canvas - > viewMode ( ) - > viewToNormal ( crect ) ;
// Go down of 90% of crect.height()
int h = frameSet ( ) - > kWordDocument ( ) - > pixelToLayoutUnitY ( ( int ) ( ( double ) crect . height ( ) * 0.9 ) ) ;
KoTextCursor * cursor = textView ( ) - > cursor ( ) ;
KoTextParag * s = cursor - > parag ( ) ;
KoTextParag * oldParag = s ;
int y = s - > rect ( ) . y ( ) ;
while ( s ) {
if ( s - > rect ( ) . y ( ) - y > = h )
break ;
s = s - > next ( ) ;
}
if ( ! s ) {
s = textDocument ( ) - > lastParag ( ) ;
cursor - > setParag ( s ) ;
cursor - > setIndex ( s - > length ( ) - 1 ) ;
} else {
cursor - > setParag ( s ) ;
cursor - > setIndex ( 0 ) ;
}
if ( s = = oldParag )
{
m_canvas - > viewportScroll ( false ) ;
return false ;
}
return true ;
}
void KWTextFrameSetEdit : : ctrlPgUpKeyPressed ( )
{
if ( m_currentFrame )
{
TQPoint iPoint = textFrameSet ( ) - > moveToPage ( m_currentFrame - > pageNumber ( ) , - 1 ) ;
if ( ! iPoint . isNull ( ) )
placeCursor ( iPoint ) ;
}
}
void KWTextFrameSetEdit : : ctrlPgDownKeyPressed ( )
{
if ( m_currentFrame )
{
TQPoint iPoint = textFrameSet ( ) - > moveToPage ( m_currentFrame - > pageNumber ( ) , + 1 ) ;
if ( ! iPoint . isNull ( ) )
placeCursor ( iPoint ) ;
}
}
void KWTextFrameSetEdit : : setCursor ( KoTextParag * parag , int index )
{
cursor ( ) - > setParag ( parag ) ;
cursor ( ) - > setIndex ( index ) ;
}
void KWTextFrameSetEdit : : insertExpression ( const TQString & _c )
{
if ( textObject ( ) - > hasSelection ( ) )
frameSet ( ) - > kWordDocument ( ) - > addCommand ( textObject ( ) - > replaceSelectionCommand (
cursor ( ) , _c , i18n ( " Insert Expression " ) ) ) ;
else
textObject ( ) - > insert ( cursor ( ) , currentFormat ( ) , _c , i18n ( " Insert Expression " ) ) ;
}
void KWTextFrameSetEdit : : insertFloatingFrameSet ( KWFrameSet * fs , const TQString & commandName )
{
textObject ( ) - > clearUndoRedoInfo ( ) ;
CustomItemsMap customItemsMap ;
TQString placeHolders ;
// TODO support for multiple floating items (like multiple-page tables)
int frameNumber = 0 ;
int index = 0 ;
int insertFlags = KoTextObject : : DoNotRemoveSelected ;
{ // the loop will start here :)
KWAnchor * anchor = fs - > createAnchor ( textFrameSet ( ) - > textDocument ( ) , frameNumber ) ;
if ( frameNumber = = 0 & & anchor - > ownLine ( ) & & cursor ( ) - > index ( ) > 0 ) // enforce start of line - currently unused
{
kdDebug ( ) < < " ownline -> prepending \\ n " < < endl ;
placeHolders + = TQChar ( ' \n ' ) ;
index + + ;
insertFlags | = KoTextObject : : CheckNewLine ;
}
placeHolders + = KoTextObject : : customItemChar ( ) ;
customItemsMap . insert ( index , anchor ) ;
}
fs - > setAnchored ( textFrameSet ( ) ) ;
textObject ( ) - > insert ( cursor ( ) , currentFormat ( ) , placeHolders ,
commandName , KoTextDocument : : Standard , insertFlags ,
customItemsMap ) ;
}
void KWTextFrameSetEdit : : insertLink ( const TQString & _linkName , const TQString & hrefName )
{
KWDocument * doc = frameSet ( ) - > kWordDocument ( ) ;
KoVariable * var = new KoLinkVariable ( textFrameSet ( ) - > textDocument ( ) , _linkName , hrefName , doc - > variableFormatCollection ( ) - > format ( " STRING " ) , doc - > variableCollection ( ) ) ;
insertVariable ( var ) ;
}
void KWTextFrameSetEdit : : insertComment ( const TQString & _comment )
{
KWDocument * doc = frameSet ( ) - > kWordDocument ( ) ;
KoVariable * var = new KoNoteVariable ( textFrameSet ( ) - > textDocument ( ) , _comment , doc - > variableFormatCollection ( ) - > format ( " STRING " ) , doc - > variableCollection ( ) ) ;
insertVariable ( var ) ;
}
void KWTextFrameSetEdit : : insertCustomVariable ( const TQString & name )
{
KWDocument * doc = frameSet ( ) - > kWordDocument ( ) ;
KoVariable * var = new KoCustomVariable ( textFrameSet ( ) - > textDocument ( ) , name , doc - > variableFormatCollection ( ) - > format ( " STRING " ) , doc - > variableCollection ( ) ) ;
insertVariable ( var ) ;
}
void KWTextFrameSetEdit : : insertFootNote ( NoteType noteType , KWFootNoteVariable : : Numbering numType , const TQString & manualString )
{
KWFootNoteFrameSet * fs = textFrameSet ( ) - > insertFootNote ( noteType , numType , manualString ) ;
KWFootNoteVariable * var = fs - > footNoteVariable ( ) ;
// Place the frame on the correct page, but the exact coordinates
// will be determined by recalcFrames (KWFrameLayout)
int pageNum = m_currentFrame - > pageNumber ( ) ;
fs - > createInitialFrame ( pageNum ) ;
insertVariable ( var ) ;
// Re-number footnote variables
textFrameSet ( ) - > renumberFootNotes ( ) ;
// Layout the footnote frame
textFrameSet ( ) - > kWordDocument ( ) - > recalcFrames ( pageNum , - 1 ) ; // we know that for sure nothing changed before this page.
//KoTextParag* parag = fs->textDocument()->firstParag();
//parag->truncate(0); // why? we just created it, anyway...
// And now edit the footnote frameset - all WPs do that it seems.
fs - > startEditing ( m_canvas ) ;
// --- and now we are deleted! ---
}
void KWTextFrameSetEdit : : insertVariable ( int type , int subtype )
{
kdDebug ( ) < < " KWTextFrameSetEdit::insertVariable " < < type < < endl ;
KWDocument * doc = frameSet ( ) - > kWordDocument ( ) ;
KoVariable * var = 0L ;
bool refreshCustomMenu = false ;
if ( type = = VT_CUSTOM )
{
KoCustomVarDialog dia ( m_canvas ) ;
if ( dia . exec ( ) = = TQDialog : : Accepted )
{
KoCustomVariable * v = new KoCustomVariable ( textFrameSet ( ) - > textDocument ( ) , dia . name ( ) , doc - > variableFormatCollection ( ) - > format ( " STRING " ) , doc - > variableCollection ( ) ) ;
v - > setValue ( dia . value ( ) ) ;
var = v ;
refreshCustomMenu = true ;
}
}
else if ( type = = VT_MAILMERGE )
{
KWMailMergeVariableInsertDia dia ( m_canvas , doc - > mailMergeDataBase ( ) ) ;
if ( dia . exec ( ) = = TQDialog : : Accepted )
{
var = new KWMailMergeVariable ( textFrameSet ( ) - > textDocument ( ) , dia . getName ( ) , doc - > variableFormatCollection ( ) - > format ( " STRING " ) , doc - > variableCollection ( ) , doc ) ;
}
}
else
var = doc - > variableCollection ( ) - > createVariable ( type , subtype , doc - > variableFormatCollection ( ) , 0L , textFrameSet ( ) - > textDocument ( ) , doc , 0 ) ;
if ( var )
insertVariable ( var , 0L /*means currentFormat()*/ , refreshCustomMenu ) ;
}
void KWTextFrameSetEdit : : insertVariable ( KoVariable * var , KoTextFormat * format /*=0*/ , bool refreshCustomMenu )
{
if ( var )
{
CustomItemsMap customItemsMap ;
customItemsMap . insert ( 0 , var ) ;
if ( ! format )
format = currentFormat ( ) ;
kdDebug ( ) < < " KWTextFrameSetEdit::insertVariable inserting into paragraph " < < endl ;
# ifdef DEBUG_FORMATS
kdDebug ( ) < < " KWTextFrameSetEdit::insertVariable format= " < < format < < endl ;
# endif
textObject ( ) - > insert ( cursor ( ) , format , KoTextObject : : customItemChar ( ) ,
i18n ( " Insert Variable " ) ,
KoTextDocument : : Standard ,
KoTextObject : : DoNotRemoveSelected ,
customItemsMap ) ;
frameSet ( ) - > kWordDocument ( ) - > slotRepaintChanged ( frameSet ( ) ) ;
if ( var - > type ( ) = = VT_CUSTOM & & refreshCustomMenu )
frameSet ( ) - > kWordDocument ( ) - > refreshMenuCustomVariable ( ) ;
}
}
void KWTextFrameSetEdit : : insertWPPage ( )
{
KWTextFrameSet * textfs = textFrameSet ( ) ;
textfs - > clearUndoRedoInfo ( ) ;
KoTextObject * textobj = textObject ( ) ;
KWDocument * doc = frameSet ( ) - > kWordDocument ( ) ;
int pages = doc - > pageCount ( ) ;
int columns = doc - > numColumns ( ) ;
// There could be N columns. In that case we may need to add up to N framebreaks.
int inserted = 0 ;
KMacroCommand * macroCmd = new KMacroCommand ( i18n ( " Insert Page " ) ) ;
do {
macroCmd - > addCommand ( textfs - > insertFrameBreakCommand ( cursor ( ) ) ) ;
textobj - > setLastFormattedParag ( cursor ( ) - > parag ( ) ) ;
textobj - > formatMore ( 2 ) ;
} while ( pages = = doc - > pageCount ( ) & & + + inserted < = columns ) ;
if ( pages = = doc - > pageCount ( ) )
kdWarning ( 32002 ) < < k_funcinfo < < " didn't manage to insert a new page! inserted= " < < inserted < < " columns= " < < columns < < " pages= " < < pages < < endl ;
doc - > addCommand ( macroCmd ) ;
textfs - > slotRepaintChanged ( ) ;
textobj - > emitEnsureCursorVisible ( ) ;
textobj - > emitUpdateUI ( true ) ;
textobj - > emitShowCursor ( ) ;
}
KoBorder KWTextFrameSetEdit : : border ( KoBorder : : BorderType type ) {
if ( type = = KoBorder : : LeftBorder )
return m_paragLayout . leftBorder ;
if ( type = = KoBorder : : RightBorder )
return m_paragLayout . rightBorder ;
if ( type = = KoBorder : : TopBorder )
return m_paragLayout . topBorder ;
return m_paragLayout . bottomBorder ;
}
// Update the GUI toolbar button etc. to reflect the current cursor position.
void KWTextFrameSetEdit : : updateUI ( bool updateFormat , bool force )
{
// Update UI - only for those items which have changed
KoTextView : : updateUI ( updateFormat , force ) ;
// Paragraph settings
KWTextParag * parag = static_cast < KWTextParag * > ( cursor ( ) - > parag ( ) ) ;
if ( m_paragLayout . alignment ! = parag - > resolveAlignment ( ) | | force ) {
m_paragLayout . alignment = parag - > resolveAlignment ( ) ;
m_canvas - > gui ( ) - > getView ( ) - > showAlign ( m_paragLayout . alignment ) ;
}
// Counter
if ( ! m_paragLayout . counter )
m_paragLayout . counter = new KoParagCounter ; // we can afford to always have one here
KoParagCounter : : Style cstyle = m_paragLayout . counter - > style ( ) ;
if ( parag - > counter ( ) )
* m_paragLayout . counter = * parag - > counter ( ) ;
else
{
m_paragLayout . counter - > setNumbering ( KoParagCounter : : NUM_NONE ) ;
m_paragLayout . counter - > setStyle ( KoParagCounter : : STYLE_NONE ) ;
}
if ( m_paragLayout . counter - > style ( ) ! = cstyle | | force )
m_canvas - > gui ( ) - > getView ( ) - > showCounter ( * m_paragLayout . counter ) ;
if ( m_paragLayout . leftBorder ! = parag - > leftBorder ( ) | |
m_paragLayout . rightBorder ! = parag - > rightBorder ( ) | |
m_paragLayout . topBorder ! = parag - > topBorder ( ) | |
m_paragLayout . bottomBorder ! = parag - > bottomBorder ( ) | | force )
{
m_paragLayout . leftBorder = parag - > leftBorder ( ) ;
m_paragLayout . rightBorder = parag - > rightBorder ( ) ;
m_paragLayout . topBorder = parag - > topBorder ( ) ;
m_paragLayout . bottomBorder = parag - > bottomBorder ( ) ;
m_canvas - > gui ( ) - > getView ( ) - > updateBorderButtons ( m_paragLayout . leftBorder , m_paragLayout . rightBorder , m_paragLayout . topBorder , m_paragLayout . bottomBorder ) ;
}
if ( ! parag - > style ( ) )
kdWarning ( ) < < " Paragraph " < < parag - > paragId ( ) < < " has no style " < < endl ;
else if ( m_paragLayout . style ! = parag - > style ( ) | | force )
{
m_paragLayout . style = parag - > style ( ) ;
m_canvas - > gui ( ) - > getView ( ) - > showStyle ( m_paragLayout . style - > name ( ) ) ;
}
if ( m_paragLayout . margins [ TQStyleSheetItem : : MarginLeft ] ! = parag - > margin ( TQStyleSheetItem : : MarginLeft )
| | m_paragLayout . margins [ TQStyleSheetItem : : MarginFirstLine ] ! = parag - > margin ( TQStyleSheetItem : : MarginFirstLine )
| | m_paragLayout . margins [ TQStyleSheetItem : : MarginRight ] ! = parag - > margin ( TQStyleSheetItem : : MarginRight )
| | parag - > string ( ) - > isRightToLeft ( ) ! = m_rtl
| | force )
{
m_paragLayout . margins [ TQStyleSheetItem : : MarginFirstLine ] = parag - > margin ( TQStyleSheetItem : : MarginFirstLine ) ;
m_paragLayout . margins [ TQStyleSheetItem : : MarginLeft ] = parag - > margin ( TQStyleSheetItem : : MarginLeft ) ;
m_paragLayout . margins [ TQStyleSheetItem : : MarginRight ] = parag - > margin ( TQStyleSheetItem : : MarginRight ) ;
if ( m_rtl ! = parag - > string ( ) - > isRightToLeft ( ) & & parag - > counter ( ) )
{
parag - > counter ( ) - > invalidate ( ) ;
parag - > setChanged ( true ) ; // repaint
}
m_rtl = parag - > string ( ) - > isRightToLeft ( ) ;
m_canvas - > gui ( ) - > getView ( ) - > showRulerIndent ( m_paragLayout . margins [ TQStyleSheetItem : : MarginLeft ] , m_paragLayout . margins [ TQStyleSheetItem : : MarginFirstLine ] , m_paragLayout . margins [ TQStyleSheetItem : : MarginRight ] , m_rtl ) ;
}
if ( m_paragLayout . tabList ( ) ! = parag - > tabList ( ) | | force )
{
m_paragLayout . setTabList ( parag - > tabList ( ) ) ;
KoRuler * hr = m_canvas - > gui ( ) - > getHorzRuler ( ) ;
if ( hr )
hr - > setTabList ( parag - > tabList ( ) ) ;
}
if ( m_paragLayout . lineSpacingType ! = parag - > paragLayout ( ) . lineSpacingType | | force )
{
m_paragLayout . lineSpacingType = parag - > paragLayout ( ) . lineSpacingType ;
m_canvas - > gui ( ) - > getView ( ) - > showSpacing ( m_paragLayout . lineSpacingType ) ;
}
// There are more paragraph settings, but those that are not directly
// visible in the UI don't need to be handled here.
// For instance parag stuff, borders etc.
}
void KWTextFrameSetEdit : : showFormat ( KoTextFormat * format )
{
m_canvas - > gui ( ) - > getView ( ) - > showFormat ( * format ) ;
}
TQPoint KWTextFrameSet : : cursorPos ( KoTextCursor * cursor , KWCanvas * canvas , KWFrame * currentFrame )
{
KWViewMode * viewMode = canvas - > viewMode ( ) ;
KoTextParag * parag = cursor - > parag ( ) ;
const TQPoint topLeft = parag - > rect ( ) . topLeft ( ) ; // in TQRT coords
int lineY ;
parag - > lineHeightOfChar ( cursor - > index ( ) , 0 , & lineY ) ;
// iPoint is the topright corner of the current character
TQPoint iPoint ( topLeft . x ( ) + cursor - > x ( ) + parag - > at ( cursor - > index ( ) ) - > width , topLeft . y ( ) + lineY ) ;
KoPoint dPoint ;
TQPoint vPoint ;
KoPoint hintDPoint = currentFrame ? currentFrame - > innerRect ( ) . topLeft ( ) : KoPoint ( ) ;
if ( internalToDocumentWithHint ( iPoint , dPoint , hintDPoint ) )
{
vPoint = viewMode - > normalToView ( m_doc - > zoomPoint ( dPoint ) ) ; // from doc to view contents
vPoint . rx ( ) - = canvas - > contentsX ( ) ;
vPoint . ry ( ) - = canvas - > contentsY ( ) ;
} // else ... ?
return vPoint ;
}
//////
bool KWFootNoteFrameSet : : isFootNote ( ) const
{
if ( ! m_footNoteVar ) {
kdWarning ( ) < < k_funcinfo < < " called too early? No footnote var. " < < endl ;
return false ;
}
return ( m_footNoteVar - > noteType ( ) = = FootNote ) ;
}
bool KWFootNoteFrameSet : : isEndNote ( ) const
{
if ( ! m_footNoteVar ) {
kdWarning ( ) < < k_funcinfo < < " called too early? No footnote var. " < < endl ;
return false ;
}
return ( m_footNoteVar - > noteType ( ) = = EndNote ) ;
}
void KWFootNoteFrameSet : : createInitialFrame ( int pageNum )
{
KWFrame * frame = new KWFrame ( this , 0 , m_doc - > pageManager ( ) - > topOfPage ( pageNum ) + 1 , 20 , 20 ) ;
frame - > setFrameBehavior ( KWFrame : : AutoExtendFrame ) ;
frame - > setNewFrameBehavior ( KWFrame : : NoFollowup ) ;
addFrame ( frame ) ;
}
void KWFootNoteFrameSet : : startEditing ( KWCanvas * canvas )
{
canvas - > editFrameSet ( this ) ;
// Ensure cursor is visible
KWTextFrameSetEdit * textedit = dynamic_cast < KWTextFrameSetEdit * > ( canvas - > currentFrameSetEdit ( ) - > currentTextEdit ( ) ) ;
if ( textedit )
textedit - > ensureCursorVisible ( ) ;
}
void KWFootNoteFrameSet : : setFootNoteVariable ( KWFootNoteVariable * var )
{
m_footNoteVar = var ;
}
void KWFootNoteFrameSet : : setCounterText ( const TQString & text )
{
KoTextParag * parag = textDocument ( ) - > firstParag ( ) ;
Q_ASSERT ( parag ) ;
if ( parag ) {
KoParagCounter counter ;
counter . setNumbering ( KoParagCounter : : NUM_FOOTNOTE ) ;
counter . setPrefix ( text ) ;
counter . setSuffix ( TQString ( ) ) ;
parag - > setCounter ( counter ) ;
}
}
KWordFrameSetIface * KWFootNoteFrameSet : : dcopObject ( )
{
if ( ! m_dcop )
m_dcop = new KWFootNoteFrameSetIface ( this ) ;
return m_dcop ;
}
# include "KWTextFrameSet.moc"