4
/* This file is part of the KDE project
5
Copyright (C) 2001-2005 David Faure <faure@kde.org>
7
This library is free software; you can redistribute it and/or
8
modify it under the terms of the GNU Library General Public
9
License as published by the Free Software Foundation; either
10
version 2 of the License, or (at your option) any later version.
12
This library is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
Library General Public License for more details.
17
You should have received a copy of the GNU Library General Public License
18
along with this library; see the file COPYING.LIB. If not, write to
19
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
* Boston, MA 02110-1301, USA.
25
#include "KoParagLayout.h"
27
#include "KoTextFormat.h"
28
#include "KoRichText.h" // for KoTextString
29
class KoTextFormatterBase;
30
class KoTextParagLineStart;
35
class KoTextCustomItem;
37
class KoSavingContext;
38
class KoStyleCollection;
40
struct KoTextParagSelection
45
#if defined(Q_TEMPLATEDLL)
47
template class QMap<int, KoTextParagSelection>;
48
template class QMap<int, KoTextParagLineStart*>;
52
class KOTEXT_EXPORT KoTextParag
54
friend class KoTextDocument;
55
friend class KoTextCursor;
58
KoTextParag( KoTextDocument *d, KoTextParag *pr = 0, KoTextParag *nx = 0, bool updateIds = TRUE );
59
virtual ~KoTextParag();
61
KoTextString *string() const;
62
KoTextStringChar *at( int i ) const;
66
// Abstraction over the trailing-space thing, so that it can be removed later
67
int lastCharPos() const { return str->length()-2; }
69
void setFormat( KoTextFormat *fm );
70
KoTextFormat *paragFormat() const;
72
KoTextDocument *document() const;
75
void setRect( const QRect& rect ) { r = rect; }
76
void setHeight( int h ) { r.setHeight( h ); }
77
void setWidth( int w ) { r.setWidth( w ); }
80
bool isVisible() const { return visible; }
82
KoTextParag *prev() const;
83
KoTextParag *next() const;
84
void setPrev( KoTextParag *s );
85
void setNext( KoTextParag *s );
87
void insert( int index, const QString &s );
88
void append( const QString &s, bool reallyAtEnd = FALSE );
89
void truncate( int index );
90
void remove( int index, int len );
93
void format( int start = -1, bool doMove = TRUE );
95
/// Call this to ensure that format() will be called on this paragraph later on
96
void invalidate( int chr /*ignored*/ = 0 );
97
/// Returns false if format() needs to be called on this paragraph
100
/// 'changed' tells the painting code what it needs to paint
101
bool hasChanged() const;
102
void setChanged( bool b, bool recursive = FALSE );
103
short int lineChanged(); // first line that has been changed.
104
void setLineChanged( short int line );
106
int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const;
107
KoTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const;
109
KoTextStringChar *lineStartOfLine( int line, int *index = 0 ) const;
110
int lineY( int l ) const;
111
int lineBaseLine( int l ) const;
112
int lineHeight( int l ) const;
113
void lineInfo( int l, int &y, int &h, int &bl ) const;
115
void setSelection( int id, int start, int end );
116
void removeSelection( int id );
117
int selectionStart( int id ) const;
118
int selectionEnd( int id ) const;
119
bool hasSelection( int id ) const;
120
bool hasAnySelection() const;
121
bool fullSelected( int id ) const;
123
//void setEndState( int s );
124
//int endState() const;
126
void setParagId( int i );
129
QMap<int, KoTextParagLineStart*> &lineStartList();
131
void setFormat( int index, int len, const KoTextFormat *f, bool useCollection = TRUE, int flags = -1 );
133
void setAlignment( uint a );
134
void setAlignmentDirect( uint a ) { align = a; }
135
uint alignment() const;
137
virtual void paint( QPainter &painter, const QColorGroup &cg, KoTextCursor *cursor, bool drawSelections,
138
int clipx, int clipy, int clipw, int cliph ); // kotextparag.cc
141
int topMargin() const;
142
int bottomMargin() const;
143
int leftMargin() const;
144
int firstLineMargin() const;
145
int rightMargin() const;
146
int lineSpacing( int line ) const;
147
int calculateLineSpacing( int line, int start, int last ) const;
149
void registerFloatingItem( KoTextCustomItem *i );
150
void unregisterFloatingItem( KoTextCustomItem *i );
152
void setFullWidth( bool b ) { fullWidth = b; }
153
bool isFullWidth() const { return fullWidth; }
155
int customItems() const;
157
void setDocumentRect( const QRect &r );
158
int documentWidth() const;
159
//int documentVisibleWidth() const;
160
int documentX() const;
161
int documentY() const;
162
KoTextFormatCollection *formatCollection() const;
163
//void setFormatter( KoTextFormatterBase *f );
164
KoTextFormatterBase *formatter() const;
165
//int minimumWidth() const;
166
int widthUsed() const;
168
int nextTabDefault( int i, int x );
169
int nextTab( int i, int x, int availableWidth );
170
int *tabArray() const;
171
void setTabArray( int *a );
172
void setTabStops( int tw );
174
/// Set whether '\n' should break the paragraph into multiple lines
176
void setNewLinesAllowed( bool b );
177
/// Return whether '\n' should break the paragraph into multiple lines
178
bool isNewLinesAllowed() const;
180
virtual void join( KoTextParag *s );
181
virtual void copyParagData( KoTextParag *parag );
183
//void setBreakable( bool b ) { breakable = b; }
184
//bool isBreakable() const { return breakable; }
186
void setMovedDown( bool b ) { movedDown = b; }
187
bool wasMovedDown() const { return movedDown; }
189
void setDirection( QChar::Direction d );
190
QChar::Direction direction() const;
192
/// Mark a paragraph as being part of the table of contents (kword only)
193
void setPartOfTableOfContents( bool b ) { m_toc = b; }
194
bool partOfTableOfContents() const { return m_toc; }
196
// For KoTextFormatter only
197
void insertLineStart( int index, KoTextParagLineStart *ls );
200
void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg );
201
void drawCursorDefault( QPainter &painter, KoTextCursor *cursor, int curx, int cury, int curh, const QColorGroup &cg );
202
void drawCursor( QPainter &painter, KoTextCursor *cursor, int curx, int cury, int curh, const QColorGroup &cg );
205
* We extend KoTextParag with more (zoom-aware) features,
206
* like linespacing, borders, counter, tabulators, etc.
207
* This also implements WYSIWYG text drawing.
210
KoTextDocument * textDocument() const { return document(); }
212
KoTextFormat * paragraphFormat() const
213
{ return static_cast<KoTextFormat *>( paragFormat() ); }
215
/** Sets all or some parameters from a paragLayout struct.
216
* @param flags selects which settings to apply, see KoParagLayout's enum. */
217
virtual void setParagLayout( const KoParagLayout &layout, int flags = KoParagLayout::All,
218
int marginIndex = -1 );
220
const KoParagLayout & paragLayout() { return m_layout; }
223
double margin( QStyleSheetItem::Margin m ) { return m_layout.margins[m]; }
224
const double * margins() const { return m_layout.margins; }
225
void setMargin( QStyleSheetItem::Margin m, double _i );
226
void setMargins( const double * _i );
228
/** Line spacing in pt if >=0, can also be one of the LS_* values */
229
double kwLineSpacing() const { return m_layout.lineSpacingValue(); }
231
void setLineSpacing( double _i );
233
KoParagLayout::SpacingType kwLineSpacingType() const { return m_layout.lineSpacingType; }
235
void setLineSpacingType( KoParagLayout::SpacingType _type );
238
/** Use this to change the paragraph alignment, not KoTextParag::setAlignment ! */
239
void setAlign( int align );
240
/** Return the real alignment: Auto is resolved to either Left or Right */
241
int resolveAlignment() const;
243
/// The part of the top margin that can be broken by a page break
244
/// Obviously the non-breakable part (e.g. border width) is topMargin()-breakableTopMargin()
245
int breakableTopMargin() const;
248
KoBorder leftBorder() const { return m_layout.leftBorder; }
249
KoBorder rightBorder() const { return m_layout.rightBorder; }
250
KoBorder topBorder() const { return m_layout.topBorder; }
251
KoBorder bottomBorder() const { return m_layout.bottomBorder; }
252
bool hasBorder() const { return m_layout.hasBorder(); }
253
bool joinBorder() const { return m_layout.joinBorder; }
255
void setLeftBorder( const KoBorder & _brd ) { m_layout.leftBorder = _brd; }
256
void setRightBorder( const KoBorder & _brd ) { m_layout.rightBorder = _brd; }
257
void setTopBorder( const KoBorder & _brd );
258
void setBottomBorder( const KoBorder & _brd );
259
void setJoinBorder( bool join );
261
// Paragraph background
262
QColor backgroundColor() { return m_layout.backgroundColor; }
263
void setBackgroundColor( const QColor& color);
265
// Counters are used to implement list and heading numbering/bullets.
266
void setCounter( const KoParagCounter & counter );
268
void setCounter( const KoParagCounter * pCounter )
270
if ( pCounter ) setCounter( *pCounter );
273
KoParagCounter *counter();
275
/** The space required to draw the complete counter label (i.e. the Counter for this
276
* paragraph, as well as the Counters for any paragraphs above us in the numbering
277
* hierarchy). @see drawLabel(). */
278
int counterWidth() const;
280
/** Style used by this paragraph */
281
KoParagStyle *style() const { return m_layout.style; }
282
/** Sets the style in this paragraph, but doesn't _apply_ it, only sets a reference */
283
void setStyle( KoParagStyle *style ) { m_layout.style = style; }
284
/** Applies the style directly (without undo/redo! See KoTextObject for undo/redo) */
285
void applyStyle( KoParagStyle *style );
287
/** Get tabulator positions */
288
const KoTabulatorList& tabList() const { return m_layout.tabList(); }
289
/** Set tabulator positions */
290
void setTabList( const KoTabulatorList &tabList );
292
/** Return the X for the shadow distance in pixels (zoomed) */
293
int shadowX( KoTextZoomHandler *zh ) const;
294
/** Return the Y for the shadow distance in pixels (zoomed) */
295
int shadowY( KoTextZoomHandler *zh ) const;
296
/** Return the Y for the shadow distance in pt */
297
double shadowDistanceY() const;
299
/** Set a @p custom item at position @p index, with format @p currentFormat (convenience method) */
300
void setCustomItem( int index, KoTextCustomItem * custom, KoTextFormat * currentFormat );
301
/** Remove the custom item from position @p index, but doesn't delete it */
302
void removeCustomItem( int index );
304
/** Find a custom item that we know is somewhere in this paragraph
305
* Returns the index in the paragraph */
306
int findCustomItem( const KoTextCustomItem * custom ) const;
308
/** Cache to find a tab by char index, QMap<char index, tab index> */
309
QMap<int, int>& tabCache() { return m_tabCache; }
311
/** @return the parag rect, in pixels. This takes care of some rounding problems */
312
QRect pixelRect( KoTextZoomHandler* zh ) const;
314
/** draw underline and double underline. Static because it's used
315
* for draw double/simple in variable.
317
static void drawFontEffects( QPainter * p, KoTextFormat *format, KoTextZoomHandler *zh, QFont font, const QColor & color, int startX, int baseLine, int bw, int y, int h, QChar firstChar );
319
/** a bit more clever than KoTextString::toString, e.g. with numbered lists */
320
QString toString( int from = 0, int length = 0xffffffff) const;
322
/// The app should call this during formatting - e.g. in formatVertically
323
void fixParagWidth( bool viewFormattingChars );
326
virtual void loadOasis( const QDomElement& e, KoOasisContext& context, KoStyleCollection *styleCollection, uint& pos );
328
/// By default the whole paragraph is saved. from/to allow to save only a portion of it.
329
/// The 'from' and 'to' characters are both included.
330
virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context,
331
int from, int to, bool saveAnchorsFramesets = false ) const;
333
void loadOasisSpan( const QDomElement& parent, KoOasisContext& context, uint& pos );
335
void applyListStyle( KoOasisContext& context, int restartNumbering, bool orderedList, bool heading, int level );
338
void printRTDebug( int );
342
void invalidateCounters();
343
bool lineHyphenated( int l ) const;
345
void paintLines( QPainter &painter, const QColorGroup &cg, KoTextCursor *cursor, bool drawSelections,
346
int clipx, int clipy, int clipw, int cliph );
348
void drawParagString( QPainter &painter, const QString &str, int start, int len, int startX,
349
int lastY, int baseLine, int bw, int h, bool drawSelections,
350
KoTextFormat *lastFormat, const QMemArray<int> &selectionStarts,
351
const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft, int line );
352
void drawParagStringInternal( QPainter &painter, const QString &s, int start, int len, int startX,
353
int lastY, int baseLine, int bw, int h, bool drawSelections,
354
KoTextFormat *lastFormat, const QMemArray<int> &selectionStarts,
355
const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft, int line, KoTextZoomHandler* zh, bool drawingShadow );
357
/// Bitfield for drawFormattingChars's "whichFormattingChars" param
358
enum { FormattingSpace = 1, FormattingBreak = 2, FormattingEndParag = 4, FormattingTabs = 8,
359
AllFormattingChars = FormattingSpace | FormattingBreak | FormattingEndParag | FormattingTabs };
361
/// Called by drawParagStringInternal to draw the formatting characters, if the
362
/// kotextdocument drawingflag for it was set.
363
/// The last arg is a bit special: drawParagStringInternal always sets it to "all",
364
/// but reimplementations can change its value.
365
virtual void drawFormattingChars( QPainter &painter, int start, int len,
366
int lastY_pix, int baseLine_pix, int h_pix, // in pixels
368
KoTextFormat *format, const QMemArray<int> &selectionStarts,
369
const QMemArray<int> &selectionEnds, const QColorGroup &cg,
370
bool rightToLeft, int line, KoTextZoomHandler* zh,
371
int whichFormattingChars );
374
KoParagLayout m_layout;
375
QMap<int, int> m_tabCache;
378
KoParagLayout loadParagLayout( KoOasisContext& context, KoStyleCollection *styleCollection, bool findStyle );
382
/////// End of kotext-specific additions
384
QMap<int, KoTextParagSelection> &selections() const;
385
QPtrList<KoTextCustomItem> &floatingItems() const;
386
/// Returns the height of the biggest character in that line
387
int heightForLineSpacing( int startChar, int lastChar ) const;
389
QMap<int, KoTextParagLineStart*> lineStarts;
396
bool newLinesAllowed : 1;
401
short int m_lineChanged;
405
QMap<int, KoTextParagSelection> *mSelections;
406
QPtrList<KoTextCustomItem> *mFloatingItems;
407
KoTextFormat *defFormat; // is this really used?
410
// Those things are used by QRT for the case of a paragraph without document
411
// We don't use this currently, and it's not worth making EVERY parag bigger
412
// just for a special case that's rarely used. Better have lightweight KoTextDocument
413
// replacement (with common base class), if we ever want efficient single-parag docs...
416
//KoTextFormatterBase *pFormatter;
417
//KoTextDocCommandHistory *commandHistory;
420
inline int KoTextParag::length() const
422
return str->length();
425
inline QRect KoTextParag::rect() const
430
inline KoTextStringChar *KoTextParag::at( int i ) const
432
return &str->at( i );
435
inline bool KoTextParag::isValid() const
440
inline bool KoTextParag::hasChanged() const
445
inline short int KoTextParag::lineChanged()
447
return m_lineChanged;
450
inline void KoTextParag::append( const QString &s, bool reallyAtEnd )
453
insert( str->length(), s );
455
insert( QMAX( str->length() - 1, 0 ), s );
458
inline KoTextParag *KoTextParag::prev() const
463
inline KoTextParag *KoTextParag::next() const
468
inline bool KoTextParag::hasAnySelection() const
470
return mSelections ? !selections().isEmpty() : FALSE;
473
/*inline void KoTextParag::setEndState( int s )
480
inline int KoTextParag::endState() const
485
inline void KoTextParag::setParagId( int i )
490
inline int KoTextParag::paragId() const
493
// kdWarning() << "invalid parag id!!!!!!!! (" << (void*)this << ")" << endl;
497
inline QMap<int, KoTextParagLineStart*> &KoTextParag::lineStartList()
502
inline KoTextString *KoTextParag::string() const
507
inline KoTextDocument *KoTextParag::document() const
512
inline void KoTextParag::setAlignment( uint a )
520
/*inline void KoTextParag::setListStyle( QStyleSheetItem::ListStyle ls )
526
inline QStyleSheetItem::ListStyle KoTextParag::listStyle() const
531
inline KoTextFormat *KoTextParag::paragFormat() const
536
inline void KoTextParag::registerFloatingItem( KoTextCustomItem *i )
538
floatingItems().append( i );
541
inline void KoTextParag::unregisterFloatingItem( KoTextCustomItem *i )
543
floatingItems().removeRef( i );
546
/*inline void KoTextParag::addCustomItem()
551
inline void KoTextParag::removeCustomItem()
556
inline int KoTextParag::customItems() const
558
return mFloatingItems ? mFloatingItems->count() : 0;
559
// was numCustomItems, but no need for a separate count
562
inline void KoTextParag::setNewLinesAllowed( bool b )
567
inline bool KoTextParag::isNewLinesAllowed() const
569
return newLinesAllowed;