diff options
Diffstat (limited to 'lib/kotext/KoTextParag.h')
-rw-r--r-- | lib/kotext/KoTextParag.h | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/lib/kotext/KoTextParag.h b/lib/kotext/KoTextParag.h new file mode 100644 index 00000000..1b65b8c3 --- /dev/null +++ b/lib/kotext/KoTextParag.h @@ -0,0 +1,583 @@ +#ifndef KOTEXTPARAG_H +#define KOTEXTPARAG_H + +/* This file is part of the KDE project + Copyright (C) 2001-2005 David Faure <[email protected]> + + 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. +*/ + +// -*- c++ -*- + +#include "KoParagLayout.h" + +#include "KoTextFormat.h" +#include "KoRichText.h" // for KoTextString +class KoTextFormatterBase; +class KoTextParagLineStart; +class KoTextString; +class KoTextDocument; +class KoParagCounter; +class KoParagStyle; +class KoTextCustomItem; +class KoOasisContext; +class KoSavingContext; +class KoStyleCollection; + +struct KoTextParagSelection +{ + int start, end; +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +template class QMap<int, KoTextParagSelection>; +template class QMap<int, KoTextParagLineStart*>; +// MOC_SKIP_END +#endif + +class KOTEXT_EXPORT KoTextParag +{ + friend class KoTextDocument; + friend class KoTextCursor; + +public: + KoTextParag( KoTextDocument *d, KoTextParag *pr = 0, KoTextParag *nx = 0, bool updateIds = TRUE ); + virtual ~KoTextParag(); + + KoTextString *string() const; + KoTextStringChar *at( int i ) const; + int leftGap() const; + int length() const; + + // Abstraction over the trailing-space thing, so that it can be removed later + int lastCharPos() const { return str->length()-2; } + + void setFormat( KoTextFormat *fm ); + KoTextFormat *paragFormat() const; + + KoTextDocument *document() const; + + QRect rect() const; + void setRect( const QRect& rect ) { r = rect; } + void setHeight( int h ) { r.setHeight( h ); } + void setWidth( int w ) { r.setWidth( w ); } + void show(); + void hide(); + bool isVisible() const { return visible; } + + KoTextParag *prev() const; + KoTextParag *next() const; + void setPrev( KoTextParag *s ); + void setNext( KoTextParag *s ); + + void insert( int index, const QString &s ); + void append( const QString &s, bool reallyAtEnd = FALSE ); + void truncate( int index ); + void remove( int index, int len ); + + void move( int &dy ); + void format( int start = -1, bool doMove = TRUE ); + + /// Call this to ensure that format() will be called on this paragraph later on + void invalidate( int chr /*ignored*/ = 0 ); + /// Returns false if format() needs to be called on this paragraph + bool isValid() const; + + /// 'changed' tells the painting code what it needs to paint + bool hasChanged() const; + void setChanged( bool b, bool recursive = FALSE ); + short int lineChanged(); // first line that has been changed. + void setLineChanged( short int line ); + + int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const; + KoTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const; + int lines() const; + KoTextStringChar *lineStartOfLine( int line, int *index = 0 ) const; + int lineY( int l ) const; + int lineBaseLine( int l ) const; + int lineHeight( int l ) const; + void lineInfo( int l, int &y, int &h, int &bl ) const; + + void setSelection( int id, int start, int end ); + void removeSelection( int id ); + int selectionStart( int id ) const; + int selectionEnd( int id ) const; + bool hasSelection( int id ) const; + bool hasAnySelection() const; + bool fullSelected( int id ) const; + + //void setEndState( int s ); + //int endState() const; + + void setParagId( int i ); + int paragId() const; + + QMap<int, KoTextParagLineStart*> &lineStartList(); + + void setFormat( int index, int len, const KoTextFormat *f, bool useCollection = TRUE, int flags = -1 ); + + void setAlignment( uint a ); + void setAlignmentDirect( uint a ) { align = a; } + uint alignment() const; + + virtual void paint( QPainter &painter, const QColorGroup &cg, KoTextCursor *cursor, bool drawSelections, + int clipx, int clipy, int clipw, int cliph ); // kotextparag.cc + + + int topMargin() const; + int bottomMargin() const; + int leftMargin() const; + int firstLineMargin() const; + int rightMargin() const; + int lineSpacing( int line ) const; + int calculateLineSpacing( int line, int start, int last ) const; + + void registerFloatingItem( KoTextCustomItem *i ); + void unregisterFloatingItem( KoTextCustomItem *i ); + + void setFullWidth( bool b ) { fullWidth = b; } + bool isFullWidth() const { return fullWidth; } + + int customItems() const; + + void setDocumentRect( const QRect &r ); + int documentWidth() const; + //int documentVisibleWidth() const; + int documentX() const; + int documentY() const; + KoTextFormatCollection *formatCollection() const; + //void setFormatter( KoTextFormatterBase *f ); + KoTextFormatterBase *formatter() const; + //int minimumWidth() const; + int widthUsed() const; + + int nextTabDefault( int i, int x ); + int nextTab( int i, int x, int availableWidth ); + int *tabArray() const; + void setTabArray( int *a ); + void setTabStops( int tw ); + + /// Set whether '\n' should break the paragraph into multiple lines + /// Not used + void setNewLinesAllowed( bool b ); + /// Return whether '\n' should break the paragraph into multiple lines + bool isNewLinesAllowed() const; + + virtual void join( KoTextParag *s ); + virtual void copyParagData( KoTextParag *parag ); + + //void setBreakable( bool b ) { breakable = b; } + //bool isBreakable() const { return breakable; } + + void setMovedDown( bool b ) { movedDown = b; } + bool wasMovedDown() const { return movedDown; } + + void setDirection( QChar::Direction d ); + QChar::Direction direction() const; + + /// Mark a paragraph as being part of the table of contents (kword only) + void setPartOfTableOfContents( bool b ) { m_toc = b; } + bool partOfTableOfContents() const { return m_toc; } + + // For KoTextFormatter only + void insertLineStart( int index, KoTextParagLineStart *ls ); + +protected: + void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ); + void drawCursorDefault( QPainter &painter, KoTextCursor *cursor, int curx, int cury, int curh, const QColorGroup &cg ); + void drawCursor( QPainter &painter, KoTextCursor *cursor, int curx, int cury, int curh, const QColorGroup &cg ); + +/** + * We extend KoTextParag with more (zoom-aware) features, + * like linespacing, borders, counter, tabulators, etc. + * This also implements WYSIWYG text drawing. + */ +public: + KoTextDocument * textDocument() const { return document(); } + + KoTextFormat * paragraphFormat() const + { return static_cast<KoTextFormat *>( paragFormat() ); } + + /** Sets all or some parameters from a paragLayout struct. + * @param flags selects which settings to apply, see KoParagLayout's enum. */ + virtual void setParagLayout( const KoParagLayout &layout, int flags = KoParagLayout::All, + int marginIndex = -1 ); + + const KoParagLayout & paragLayout() { return m_layout; } + + // Margins + double margin( QStyleSheetItem::Margin m ) { return m_layout.margins[m]; } + const double * margins() const { return m_layout.margins; } + void setMargin( QStyleSheetItem::Margin m, double _i ); + void setMargins( const double * _i ); + + /** Line spacing in pt if >=0, can also be one of the LS_* values */ + double kwLineSpacing() const { return m_layout.lineSpacingValue(); } + + void setLineSpacing( double _i ); + + KoParagLayout::SpacingType kwLineSpacingType() const { return m_layout.lineSpacingType; } + + void setLineSpacingType( KoParagLayout::SpacingType _type ); + + + /** Use this to change the paragraph alignment, not KoTextParag::setAlignment ! */ + void setAlign( int align ); + /** Return the real alignment: Auto is resolved to either Left or Right */ + int resolveAlignment() const; + + /// The part of the top margin that can be broken by a page break + /// Obviously the non-breakable part (e.g. border width) is topMargin()-breakableTopMargin() + int breakableTopMargin() const; + + // Borders + KoBorder leftBorder() const { return m_layout.leftBorder; } + KoBorder rightBorder() const { return m_layout.rightBorder; } + KoBorder topBorder() const { return m_layout.topBorder; } + KoBorder bottomBorder() const { return m_layout.bottomBorder; } + bool hasBorder() const { return m_layout.hasBorder(); } + bool joinBorder() const { return m_layout.joinBorder; } + + void setLeftBorder( const KoBorder & _brd ) { m_layout.leftBorder = _brd; } + void setRightBorder( const KoBorder & _brd ) { m_layout.rightBorder = _brd; } + void setTopBorder( const KoBorder & _brd ); + void setBottomBorder( const KoBorder & _brd ); + void setJoinBorder( bool join ); + + // Paragraph background + QColor backgroundColor() { return m_layout.backgroundColor; } + void setBackgroundColor( const QColor& color); + + // Counters are used to implement list and heading numbering/bullets. + void setCounter( const KoParagCounter & counter ); + void setNoCounter(); + void setCounter( const KoParagCounter * pCounter ); + KoParagCounter *counter(); + + /** The space required to draw the complete counter label (i.e. the Counter for this + * paragraph, as well as the Counters for any paragraphs above us in the numbering + * hierarchy). @see drawLabel(). */ + int counterWidth() const; + + /** Style used by this paragraph */ + KoParagStyle *style() const { return m_layout.style; } + /** Sets the style in this paragraph, but doesn't _apply_ it, only sets a reference */ + void setStyle( KoParagStyle *style ) { m_layout.style = style; } + /** Applies the style directly (without undo/redo! See KoTextObject for the full command) */ + void applyStyle( KoParagStyle *style ); + + /** Get tabulator positions */ + const KoTabulatorList& tabList() const { return m_layout.tabList(); } + /** Set tabulator positions */ + void setTabList( const KoTabulatorList &tabList ); + + /** Return the X for the shadow distance in pixels (zoomed) */ + int shadowX( KoTextZoomHandler *zh ) const; + /** Return the Y for the shadow distance in pixels (zoomed) */ + int shadowY( KoTextZoomHandler *zh ) const; + /** Return the Y for the shadow distance in pt */ + double shadowDistanceY() const; + + /** Set a @p custom item at position @p index, with format @p currentFormat (convenience method) */ + void setCustomItem( int index, KoTextCustomItem * custom, KoTextFormat * currentFormat ); + /** Remove the custom item from position @p index, but doesn't delete it */ + void removeCustomItem( int index ); + + /** Find a custom item that we know is somewhere in this paragraph + * Returns the index in the paragraph */ + int findCustomItem( const KoTextCustomItem * custom ) const; + + /** Cache to find a tab by char index, QMap<char index, tab index> */ + QMap<int, int>& tabCache() { return m_tabCache; } + + /** @return the parag rect, in pixels. This takes care of some rounding problems */ + QRect pixelRect( KoTextZoomHandler* zh ) const; + + /** draw underline and double underline. Static because it's used + * for draw double/simple in variable. + */ + 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 ); + + /** a bit more clever than KoTextString::toString, e.g. with numbered lists */ + QString toString( int from = 0, int length = 0xffffffff) const; + + /// The app should call this during formatting - e.g. in formatVertically + void fixParagWidth( bool viewFormattingChars ); + + /// Load from XML + virtual void loadOasis( const QDomElement& e, KoOasisContext& context, KoStyleCollection *styleCollection, uint& pos ); + /// Save to XML + /// By default the whole paragraph is saved. from/to allow to save only a portion of it. + /// The 'from' and 'to' characters are both included. + virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, + int from, int to, bool saveAnchorsFramesets = false ) const; + + /** + * Load a section of text from a oasis based xml tree. + * @param parent the xml element that has content as children. + * @param context the context + * @param stripLeadingSpace whether to remove leading literal whitespace + */ + void loadOasisSpan( const QDomElement& parent, KoOasisContext& context, uint& pos, bool stripLeadingSpace = false ); + + /** + * Load a section of text from a oasis based xml tree. + * @param parent the xml element that has content as children. + * @param context the context + * @param stripLeadingSpace whether to remove leading literal whitespace + * @param hasTrailingSpace whether there was trailing literal whitespace in the span's text + */ + void loadOasisSpan( const QDomElement& parent, KoOasisContext& context, uint& pos, bool stripLeadingSpace, bool *hasTrailingSpace ); + + void applyListStyle( KoOasisContext& context, int restartNumbering, bool orderedList, bool heading, int level ); + +#ifndef NDEBUG + void printRTDebug( int ); +#endif + +protected: + void invalidateCounters(); + bool lineHyphenated( int l ) const; + + void paintLines( QPainter &painter, const QColorGroup &cg, KoTextCursor *cursor, bool drawSelections, + int clipx, int clipy, int clipw, int cliph ); + + void drawParagString( QPainter &painter, const QString &str, int start, int len, int startX, + int lastY, int baseLine, int bw, int h, bool drawSelections, + KoTextFormat *lastFormat, const QMemArray<int> &selectionStarts, + const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft, int line ); + void drawParagStringInternal( QPainter &painter, const QString &s, int start, int len, int startX, + int lastY, int baseLine, int bw, int h, bool drawSelections, + KoTextFormat *lastFormat, const QMemArray<int> &selectionStarts, + const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft, int line, KoTextZoomHandler* zh, bool drawingShadow ); + + /// Bitfield for drawFormattingChars's "whichFormattingChars" param + enum { FormattingSpace = 1, FormattingBreak = 2, FormattingEndParag = 4, FormattingTabs = 8, + AllFormattingChars = FormattingSpace | FormattingBreak | FormattingEndParag | FormattingTabs }; + + /// Called by drawParagStringInternal to draw the formatting characters, if the + /// kotextdocument drawingflag for it was set. + /// The last arg is a bit special: drawParagStringInternal always sets it to "all", + /// but reimplementations can change its value. + virtual void drawFormattingChars( QPainter &painter, int start, int len, + int lastY_pix, int baseLine_pix, int h_pix, // in pixels + bool drawSelections, + KoTextFormat *format, const QMemArray<int> &selectionStarts, + const QMemArray<int> &selectionEnds, const QColorGroup &cg, + bool rightToLeft, int line, KoTextZoomHandler* zh, + int whichFormattingChars ); + +protected: + KoParagLayout m_layout; + QMap<int, int> m_tabCache; + +private: + KoParagLayout loadParagLayout( KoOasisContext& context, KoStyleCollection *styleCollection, bool findStyle ); + + + + /////// End of kotext-specific additions +private: + QMap<int, KoTextParagSelection> &selections() const; + QPtrList<KoTextCustomItem> &floatingItems() const; + /// Returns the height of the biggest character in that line + int heightForLineSpacing( int startChar, int lastChar ) const; + + QMap<int, KoTextParagLineStart*> lineStarts; + QRect r; + KoTextParag *p, *n; + KoTextDocument *doc; + bool m_invalid : 1; + bool changed : 1; + bool fullWidth : 1; + bool newLinesAllowed : 1; + bool visible : 1; + bool movedDown : 1; + bool m_toc : 1; + uint align : 4; + short int m_lineChanged; + int id; + int m_wused; + KoTextString *str; + QMap<int, KoTextParagSelection> *mSelections; + QPtrList<KoTextCustomItem> *mFloatingItems; + KoTextFormat *defFormat; // is this really used? + int *tArray; + + // Those things are used by QRT for the case of a paragraph without document + // We don't use this currently, and it's not worth making EVERY parag bigger + // just for a special case that's rarely used. Better have lightweight KoTextDocument + // replacement (with common base class), if we ever want efficient single-parag docs... + //int tabStopWidth; + //QRect docRect; + //KoTextFormatterBase *pFormatter; + //KoTextDocCommandHistory *commandHistory; +}; + +inline int KoTextParag::length() const +{ + return str->length(); +} + +inline QRect KoTextParag::rect() const +{ + return r; +} + +inline KoTextStringChar *KoTextParag::at( int i ) const +{ + return &str->at( i ); +} + +inline bool KoTextParag::isValid() const +{ + return !m_invalid; +} + +inline bool KoTextParag::hasChanged() const +{ + return changed; +} + +inline short int KoTextParag::lineChanged() +{ + return m_lineChanged; +} + +inline void KoTextParag::append( const QString &s, bool reallyAtEnd ) +{ + if ( reallyAtEnd ) + insert( str->length(), s ); + else + insert( QMAX( str->length() - 1, 0 ), s ); +} + +inline KoTextParag *KoTextParag::prev() const +{ + return p; +} + +inline KoTextParag *KoTextParag::next() const +{ + return n; +} + +inline bool KoTextParag::hasAnySelection() const +{ + return mSelections ? !selections().isEmpty() : FALSE; +} + +/*inline void KoTextParag::setEndState( int s ) +{ + if ( s == state ) + return; + state = s; +} + +inline int KoTextParag::endState() const +{ + return state; +}*/ + +inline void KoTextParag::setParagId( int i ) +{ + id = i; +} + +inline int KoTextParag::paragId() const +{ + //if ( id == -1 ) + // kdWarning() << "invalid parag id!!!!!!!! (" << (void*)this << ")" << endl; + return id; +} + +inline QMap<int, KoTextParagLineStart*> &KoTextParag::lineStartList() +{ + return lineStarts; +} + +inline KoTextString *KoTextParag::string() const +{ + return str; +} + +inline KoTextDocument *KoTextParag::document() const +{ + return doc; +} + +inline void KoTextParag::setAlignment( uint a ) +{ + if ( a == align ) + return; + align = a; + invalidate( 0 ); +} + +/*inline void KoTextParag::setListStyle( QStyleSheetItem::ListStyle ls ) +{ + lstyle = ls; + invalidate( 0 ); +} + +inline QStyleSheetItem::ListStyle KoTextParag::listStyle() const +{ + return lstyle; +}*/ + +inline KoTextFormat *KoTextParag::paragFormat() const +{ + return defFormat; +} + +inline void KoTextParag::registerFloatingItem( KoTextCustomItem *i ) +{ + floatingItems().append( i ); +} + +inline void KoTextParag::unregisterFloatingItem( KoTextCustomItem *i ) +{ + floatingItems().removeRef( i ); +} + +/*inline void KoTextParag::addCustomItem() +{ + numCustomItems++; +} + +inline void KoTextParag::removeCustomItem() +{ + numCustomItems--; +}*/ + +inline int KoTextParag::customItems() const +{ + return mFloatingItems ? mFloatingItems->count() : 0; + // was numCustomItems, but no need for a separate count +} + +inline void KoTextParag::setNewLinesAllowed( bool b ) +{ + newLinesAllowed = b; +} + +inline bool KoTextParag::isNewLinesAllowed() const +{ + return newLinesAllowed; +} + +#endif |