diff options
Diffstat (limited to 'khtml/khtml_caret_p.h')
-rw-r--r-- | khtml/khtml_caret_p.h | 1109 |
1 files changed, 0 insertions, 1109 deletions
diff --git a/khtml/khtml_caret_p.h b/khtml/khtml_caret_p.h deleted file mode 100644 index 9524f2df7..000000000 --- a/khtml/khtml_caret_p.h +++ /dev/null @@ -1,1109 +0,0 @@ -/* This file is part of the KDE project - * - * Copyright (C) 2003-2004 Leo Savernik <l.savernik@aon.at> - * - * 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. - */ - -#ifndef KHTML_CARET_P_H -#define KHTML_CARET_P_H - -#include "rendering/render_table.h" - -#include <tqvaluevector.h> - -#define DEBUG_CARETMODE 0 - -class TQFontMetrics; - -namespace DOM { - class NodeImpl; - class ElementImpl; -} - -namespace khtml { - -/** caret advance policy. - * - * Used to determine which elements are taken into account when the caret is - * advanced. Later policies pose refinements of all former - * policies. - * @param LeafsOnly advance from leave render object to leaf render object - * (It will allow outside flow positions if a flow wouldn't be reachable - * otherwise). - * @param IndicatedFlows place caret also at the beginning/end of flows - * that have at least one visible border at any side. - * (It will allow not indicated flow positions if a flow wouldn't - * be reachable otherwise). - * @param VisibleFlows place caret also at the beginning/end of any flow - * that has a renderer. - */ -enum CaretAdvancePolicy { - LeafsOnly, IndicatedFlows, VisibleFlows -}; - -/** contextual information about the caret which is related to the view. - * An object of this class is only instantiated when it is needed. - */ -struct CaretViewContext { - int freqTimerId; // caret blink frequency timer id - int x, y; // caret position in viewport coordinates - // (y specifies the top, not the baseline) - int width; // width of caret in pixels - int height; // height of caret in pixels - bool visible; // true if currently visible. - bool displayed; // true if caret is to be displayed at all. - bool caretMoved; // set to true once caret has been moved in page - // how to display the caret when view is not focused - KHTMLPart::CaretDisplayPolicy displayNonFocused; - - /** For natural traversal of lines, the original x position is saved, and - * the actual x is set to the first character whose x position is - * greater than origX. - * - * origX is reset to x whenever the caret is moved horizontally or placed - * by the mouse. - */ - int origX; - - bool keyReleasePending; // true if keypress under caret mode awaits - // corresponding release event - CaretViewContext() : freqTimerId(-1), x(0), y(0), width(1), height(16), - visible(true), displayed(false), caretMoved(false), - displayNonFocused(KHTMLPart::CaretInvisible), origX(0), - keyReleasePending(false) - {} -}; - -/** contextual information about the editing state. - * An object of this class is only instantiated when it is needed. - */ -struct EditorContext { - bool override; // true if typed characters should override - // the existing ones. - - EditorContext() : override(false) - {} -}; - -class LinearDocument; - -/** - * Stores objects of a certain type, and calls delete on each of them - * when this data structure is destroyed. - * - * As this structure merely consists of a vector of pointers, all objects - * allocated can be traversed as seen fit. - * - * @author Leo Savernik - * @since 3.3 - * @internal - */ -template<class T> class MassDeleter : public TQValueVector<T *> { -public: - MassDeleter(size_t reserved = 1) { this->reserve(reserved); } - ~MassDeleter() - { - typename TQValueVector<T *>::Iterator nd = this->end(); - for (typename TQValueVector<T *>::Iterator it = this->begin(); it != nd; ++it) - delete *it; - } -}; - -class CaretBoxLine; - -/** - * Represents a rectangular box within which the caret is located. - * - * The caret box serves as a wrapper for inline boxes of all kind. It either - * wraps an InlineBox, InlineTextBox, or InlineFlowBox, or if no such boxes - * exist for a certain context, it contains the relevant information directly. - * - * This class will be constructed whenever a caret position has to be described. - * @since 3.3 - * @author Leo Savernik - * @internal - */ -class CaretBox { -protected: - InlineBox *_box; // associated inline box if available. - short _w; // width of box in pixels - int _h; // height of box in pixels - int _x; // x coordinate relative to containing block - int _y; // y coordinate relative to containing block - RenderBox *cb; // containing block - bool _outside:1; // true when representing the outside of the element - bool outside_end:1; // at ending outside of element rather than at beginning - // 29 bits unused - -public: - /** empty constructor for later assignment */ - CaretBox() {} - /** initializes the caret box from the given inline box */ - CaretBox(InlineBox *ibox, bool outside, bool outsideEnd) : _box(ibox), - _w((short)ibox->width()), _h(ibox->height()), _x(ibox->xPos()), - _y(ibox->yPos()), cb(0), _outside(outside), outside_end(outsideEnd) - { - RenderObject *r = ibox->object(); - if (r) cb = r->containingBlock(); - } - /** initializes the caret box from scratch */ - CaretBox(int x, int y, int w, int h, RenderBox *cb, bool outside, bool outsideEnd) : - _box(0), _w((short)w), _h(h), _x(x), _y(y), cb(cb), _outside(outside), - outside_end(outsideEnd) - {} - - int width() const { return _w; } - int height() const { return _h; } - int xPos() const { return _x; } - int yPos() const { return _y; } - RenderBox *enclosingObject() const { return cb; } - InlineBox *inlineBox() const { return _box; } - - /** returns the containing block of this caret box. If the caret box - * resembles a block itself, its containing block is returned. - */ - RenderBlock *containingBlock() const { return _box ? static_cast<RenderBlock *>(cb) : cb->containingBlock(); } - - /** returns the replaced render object if this caret box represents one, - * 0 otherwise. - */ - - - /** returns true if this caret box represents an inline element, or text box, - * otherwise false. - */ - bool isInline() const { return _box; } - /** returns true if this caret box represents an inline text box. - */ - bool isInlineTextBox() const { return _box && _box->isInlineTextBox(); } - /** returns true if this caret box represents a line break - */ - bool isLineBreak() const - { - return _box && _box->object() && _box->object()->isBR(); - } - /** returns true when this caret box represents an ouside position of an - * element. - */ - bool isOutside() const { return _outside; } - /** returns the position at which the outside is targeted at. - * - * This method's return value is meaningless if isOutside() is not true. - * @return true if the outside end is meant, false if the outside beginning - * is meant. - */ - bool isOutsideEnd() const { return outside_end; } - /** returns the associated render object. */ - RenderObject *object() const { return _box ? _box->object() : cb; } - - /** returns the minimum offset for this caret box. - */ - long minOffset() const { return _box && !isLineBreak() ? _box->minOffset() : 0; } - /** returns the maximum offset for this caret box. - */ - long maxOffset() const { return _box && !isLineBreak() ? _box->maxOffset() : 0; } - -#if DEBUG_CARETMODE > 0 - void dump(TQTextStream &ts, const TQString &ind) const; -#endif - - friend class CaretBoxLine; -}; - -typedef MassDeleter<CaretBox> CaretBoxDeleter; - -/** - * Iterates over the elements of a caret box line. - * - * @author Leo Savernik - * @internal - * @since 3.3 - */ -class CaretBoxIterator { -protected: - CaretBoxLine *cbl; // associated caret box line - int index; // current index - -public: - // Let standard constructor/copy constructor/destructor/assignment operator - // be defined by the compiler. They do exactly what we want. - - bool operator ==(const CaretBoxIterator &it) const - { - return cbl == it.cbl && index == it.index; - } - - bool operator !=(const CaretBoxIterator &it) const - { - return !operator ==(it); - } - - /** returns the current caret box. - * @return current caret box - */ - CaretBox *data() const; - /** shortcut for \c data - * @return current caret box - */ - CaretBox *operator *() const { return data(); } - - /** increments the iterator to point to the next caret box. - */ - CaretBoxIterator &operator ++() { index++; return *this; } - /** decrements the iterator to point to the previous caret box. - */ - CaretBoxIterator &operator --() { index--; return *this; } - - friend class CaretBoxLine; - friend class EditableCaretBoxIterator; -}; - -/** - * Resembles a line consisting of caret boxes. - * - * To the contrary of InlineFlowBoxes which are nested as needed to map the - * DOM to the rendered representation, it is sufficient for caret navigation - * to provide a linear list of unnested caret boxes. - * - * \code - * Example: The document fragment <p>a <i><b>c</b> f</i> g</p> will be - * represented by three caret box lines which each one consists of caret boxes - * as follows: - * CaretBoxLine 1: - * CaretBox(cb=<p>, _box=0, _outside=true, outside_end=false) - * CaretBoxLine 2: - * CaretBox(cb=<p>, _box=InlineTextBox("a "), _outside=false) - * CaretBox(cb=<p>, _box=InlineFlowBox(<i>), _outside=true, outside_end=false) - * CaretBox(cb=<p>, _box=InlineFlowBox(<b>), _outside=true, outside_end=false) - * CaretBox(cb=<p>, _box=InlineTextBox("c"), _outside=false) - * CaretBox(cb=<p>, _box=InlineFlowBox(<b>), _outside=true, outside_end=true) - * CaretBox(cb=<p>, _box=InlineTextBox(" f"), _outside=false) - * CaretBox(cb=<p>, _box=InlineFlowBox(<i>), _outside=true, outside_end=true) - * CaretBox(cb=<p>, _box=InlineTextBox(" g"), _outside=true, outside_end=true) - * CaretBoxLine 3: - * CaretBox(cb=<p>, _box=0, _outside=true, outside_end=true) - * \endcode - */ -class CaretBoxLine { -protected: - CaretBoxDeleter caret_boxes; - // base flow box which caret boxes have been constructed for - InlineFlowBox *basefb; - - CaretBoxLine() : caret_boxes(8), basefb(0) {} - CaretBoxLine(InlineFlowBox *basefb) : caret_boxes(8), basefb(basefb) {} -public: -#if DEBUG_CARETMODE > 3 - ~CaretBoxLine() { kdDebug(6200) << k_funcinfo << "called" << endl; } -#endif - - CaretBoxIterator begin() - { - CaretBoxIterator it; - it.cbl = this; - it.index = 0; - return it; - } - CaretBoxIterator end() - { - CaretBoxIterator it; - it.cbl = this; - it.index = caret_boxes.size(); - return it; - } - CaretBoxIterator preBegin() - { - CaretBoxIterator it; - it.cbl = this; - it.index = -1; - return it; - } - CaretBoxIterator preEnd() - { - CaretBoxIterator it; - it.cbl = this; - it.index = caret_boxes.size() - 1; - return it; - } - - /** returns the base inline flow box which the caret boxes of this - * caret box line have been constructed from. - * - * This is generally a root line box, but may be an inline flow box when the - * base is restricted to an inline element. - */ - InlineFlowBox *baseFlowBox() const { return basefb; } - - /** returns the containing block */ - RenderBlock *containingBlock() const { return caret_boxes[0]->containingBlock(); } - /** returns the enclosing object */ - RenderBox *enclosingObject() const { return caret_boxes[0]->enclosingObject(); } - - /** returns whether this caret box line is outside. - * @return true if this caret box represents an outside position of this - * line box' containing block, false otherwise. - */ - bool isOutside() const - { - const CaretBox *cbox = caret_boxes[0]; - return !cbox->isInline() && cbox->isOutside(); - } - - /** returns whether this caret box line is at the outside end. - * - * The result cannot be relied upon unless isOutside() returns true. - */ - bool isOutsideEnd() const { return caret_boxes[0]->isOutsideEnd(); } - - /** constructs a new caret box line out of the given inline flow box - * @param deleter deleter which handles alloc+dealloc of the object - * @param baseFlowBox basic flow box which to create a caret line box from - * @param seekBox seek this box within the constructed line - * @param seekOutside denoting whether position is outside of seekBox - * @param seekOutsideEnd whether at the outside end of seekBox - * @param iter returns an iterator that corresponds to seekBox. If no suitable - * caret box exists, it will return end() - * @param seekObject seek this render object within the constructed line. - * It will only be regarded if \c seekBox is 0. \c iter will then point - * to the first caret box whose render object matches. - */ - static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter, - InlineFlowBox *baseFlowBox, InlineBox *seekBox, bool seekOutside, - bool seekOutsideEnd, CaretBoxIterator &iter, - RenderObject *seekObject = 0) /*KDE_NO_EXPORT*/; - - /** constructs a new caret box line for the given render block. - * @param deleter deleter which handles alloc+dealloc of the object - * @param cb render block or render replaced - * @param outside true when line is to be constructed outside - * @param outsideEnd true when the ending outside is meant - * @param iter returns the iterator to the caret box representing the given - * position for \c cb - */ - static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter, - RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/; - -#if DEBUG_CARETMODE > 0 - void dump(TQTextStream &ts, const TQString &ind) const; - TQString information() const - { - TQString result; - TQTextStream ts(&result, IO_WriteOnly); - dump(ts, TQString::null); - return result; - } -#endif - -protected: - /** contains the seek parameters */ - struct SeekBoxParams { - InlineBox *box; - bool outside; - bool outsideEnd; - bool found; - RenderObject *r; // if box is 0, seek for equal render objects instead - CaretBoxIterator ⁢ - - SeekBoxParams(InlineBox *box, bool outside, bool outsideEnd, RenderObject *obj, CaretBoxIterator &it) - : box(box), outside(outside), outsideEnd(outsideEnd), found(false), r(obj), it(it) - {} - - /** compares whether this seek box matches the given specification */ - bool equalsBox(const InlineBox *box, bool outside, bool outsideEnd) const - { - return (this->box && this->box == box - || this->r == box->object()) - && this->outside == outside - && (!this->outside || this->outsideEnd == outsideEnd); - } - /** compares whether this seek box matches the given caret box */ - bool operator ==(const CaretBox *cbox) const - { - return equalsBox(cbox->inlineBox(), cbox->isOutside(), cbox->isOutsideEnd()); - } - /** checks whether this box matches the given iterator. - * - * On success, it sets \c found, and assigns the iterator to \c it. - * @return true on match - */ - bool check(const CaretBoxIterator &chit) - { - if (*this == *chit) { - Q_ASSERT(!found); - found = true; - it = chit; - } - return found; - } - }; - - /** recursively converts the given inline box into caret boxes and adds them - * to this caret box line. - * - * It will additionally look for the caret box specified in SeekBoxParams. - */ - void addConvertedInlineBox(InlineBox *, SeekBoxParams &) /*KDE_NO_EXPORT*/; - - /** creates and adds the edge of a generic inline box - * @param box inline box - * @param fm font metrics of inline box - * @param left true to add left edge, false to add right edge - * @param rtl true if direction is rtl - */ - void addCreatedInlineBoxEdge(InlineBox *box, const TQFontMetrics &fm, - bool left, bool rtl) /*KDE_NO_EXPORT*/; - /** creates and adds the edge of an inline flow box - * @param flowBox inline flow box - * @param fm font metrics of inline flow box - * @param left true to add left edge, false to add right edge - * @param rtl true if direction is rtl - */ - void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const TQFontMetrics &fm, - bool left, bool rtl) /*KDE_NO_EXPORT*/; - /** creates and adds the inside of an inline flow box - * @param flowBox inline flow box - * @param fm font metrics of inline flow box - */ - void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const TQFontMetrics &fm) /*KDE_NO_EXPORT*/; - - friend class CaretBoxIterator; -}; - -typedef MassDeleter<CaretBoxLine> CaretBoxLineDeleter; - -inline CaretBox *CaretBoxIterator::data() const { return cbl->caret_boxes[index]; } - -/** - * Iterates through the lines of a document. - * - * The line iterator becomes invalid when the associated LinearDocument object - * is destroyed. - * @since 3.2 - * @internal - * @author Leo Savernik - */ -class LineIterator -{ -protected: - LinearDocument *lines; // associated document - CaretBoxLine *cbl; // current caret box line - - static CaretBoxIterator currentBox; // current inline box - static long currentOffset; - - // Note: cbl == 0 indicates a position beyond the beginning or the - // end of a document. - - /** Default constructor, only for internal use - */ - LineIterator() {} - - /** Initializes a new iterator. - * - * Note: This constructor neither cares about the correctness of @p node - * nor about @p offset. It is the responsibility of the caller to ensure - * that both point to valid places. - */ - LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset); - -public: - /** dereferences current caret box line. - * - * @returns the caret line box or 0 if end of document - */ - CaretBoxLine *operator *() const { return cbl; } - - /** returns the associated linear document - */ - LinearDocument *linearDocument() const { return lines; } - - /** seek next line - * - * Guaranteed to crash if beyond beginning/end of document. - */ - LineIterator &operator ++() { advance(false); return *this; } - - /** seek previous line. - * - * Guaranteed to crash if beyond beginning/end of document. - */ - LineIterator &operator --() { advance(true); return *this; } - - /** compares two iterators. The comparator actually works only for - * comparing arbitrary iterators to begin() and end(). - */ - bool operator ==(const LineIterator &it) const - { - return lines == it.lines && cbl == it.cbl; - } - - /** compares two iterators - */ - bool operator !=(const LineIterator &it) const - { - return !operator ==(it); - } - - /** Returns whether this line represents the outside end of the containing - * block. - * - * This result can only be relied on when isOutside is true. - */ - bool isOutsideEnd() { return cbl->isOutsideEnd(); } - - /** Tells whether the offset is meant to be outside or inside the - * containing block. - */ - bool isOutside() const { return cbl->isOutside(); } - - /** advances to the line to come. - * @param toBegin true, move to previous line, false, move to next line. - */ - void advance(bool toBegin); - - /** Whenever a new line iterator is created, it gets a caret box created. - * For memory reasons, it's saved in a static instance, - * thus making this function not thread-safe. - * - * This value can only be trusted immediately after having instantiated - * a line iterator or one of its derivatives. - * @return an iterator onto the corresponing caret box within the - * line represented by the last instantiation of a line iterator, - * or 0 if there was none. - */ - static CaretBoxIterator ¤tCaretBox() { return currentBox; } - - /** Whenever a new line iterator is created, it calculates a modified offset - * that is to be used with respect to the current render object. - * This offset can be queried with this function. - * - * This value can only be trusted immediately after having instantiated - * a line iterator or one of its derivatives. - * @return the modified offset. - */ - static long currentModifiedOffset() { return currentOffset; } - -protected: - /** seeks next block. - */ - void nextBlock(); - /** seeks previous block. - */ - void prevBlock(); - - friend class CaretBoxIterator; - friend class EditableLineIterator; - friend class EditableCaretBoxIterator; - friend class EditableCharacterIterator; - friend class LinearDocument; -}; - -/** - * Represents the whole document in terms of lines. - * - * SGML documents are trees. But for navigation, this representation is - * not practical. Therefore this class serves as a helper to represent the - * document as a linear list of lines. Its usage somewhat resembles STL - * semantics like begin and end as well as iterators. - * - * The lines itself are represented as caret line boxes. - * - * LinearDocument instances are not meant to be kept over the lifetime of their - * associated document, but constructed from (node, offset) pairs whenever line - * traversal is needed. This is because the underlying InlineFlowBox objects - * may be destroyed and recreated (e. g. by resizing the window, adding/removing - * elements). - * - * @author Leo Savernik - * @since 3.2 - * @internal - */ -class LinearDocument { -public: - typedef LineIterator Iterator; - - /** - * Creates a new instance, and initializes it to the line specified by - * the parameters below. - * - * Creation will fail if @p node is invisible or defect. - * @param part part within which everything is taking place. - * @param node document node with which to start - * @param offset zero-based offset within this node. - * @param advancePolicy caret advance policy - * @param baseElem base element which the caret must not advance beyond - * (0 means whole document). The base element will be ignored if it - * cannot serve as a base (to see if this is the case, check whether - * LinearDocument::baseFlow()->element() != base) - */ - LinearDocument(KHTMLPart *part, DOM::NodeImpl *node, long offset, - CaretAdvancePolicy advancePolicy, DOM::ElementImpl *baseElem); - - virtual ~LinearDocument(); - - /** - * Tells whether this list contains any lines. - * - * @returns @p true if this document contains lines, @p false otherwise. Note - * that an empty document contains at least one line, so this method - * only returns @p false if the document could not be initialised for - * some reason. - */ - bool isValid() const // FIXME: not yet impl'd - { - return true; - } - - /** - * Returns the count of lines. - * - * Warning: This function is expensive. Call it once and cache the value. - * - * FIXME: It's not implemented yet (and maybe never will) - */ - int count() const; - - /** - * Returns a line iterator containing the current position as its starting - * value. - */ - Iterator current(); - - /** - * Returns a line iterator pointing right after the end of the document. - */ - const Iterator &end() const { return _end; } - - /** - * Returns a line iterator pointing to the very last line of the document. - */ - Iterator preEnd(); - - /** - * Returns a line iterator pointing to the very first line of the document. - */ - Iterator begin(); - - /** - * Returns a line iterator pointing just before the very first line of the - * document (this is somewhat an emulation of reverse iterators). - */ - const Iterator &preBegin() const { return _preBegin; } - - /** - * Returns the current caret advance policy - */ - CaretAdvancePolicy advancePolicy() const { return advPol; } - - /** - * Returns the base render object which the caret must not advance beyond. - * - * Note that HTML documents are usually restricted to the body element. - * - * @return the base render object or 0 if the whole document is valid. - */ - RenderObject *baseObject() const { return base; } - -protected: - void initPreBeginIterator(); - void initEndIterator(); - -protected: - CaretBoxLineDeleter cblDeleter; // mass deleter for caret box lines - DOM::NodeImpl *node; - long offset; - - Iterator _preBegin; - Iterator _end; - - KHTMLPart *m_part; - CaretAdvancePolicy advPol; - RenderObject *base; - - friend class LineIterator; - friend class EditableLineIterator; - friend class ErgonomicEditableLineIterator; - friend class CaretBoxIterator; - friend class EditableCaretBoxIterator; - friend class EditableCharacterIterator; -}; - -/** - * Iterates over the editable inner elements of a caret line box. - * - * The incrementor will traverse all caret boxes according to the associated - * linear document's caret advance policy. In contrast to \c CaretBoxIterator - * this iterator only regards caret boxes which are editable. - * - * @author Leo Savernik - * @internal - * @since 3.3 - */ -class EditableCaretBoxIterator : public CaretBoxIterator { - KHTMLPart *m_part; - bool adjacent; - CaretAdvancePolicy advpol; // caret advance policy - -public: - /** initializes a new iterator from the given line iterator, - * beginning with the given caret box iterator, if specified - */ - EditableCaretBoxIterator(LineIterator &lit, bool fromEnd = false, - CaretBoxIterator *it = 0) - : CaretBoxIterator(it ? *it : (fromEnd ? (*lit)->end() : (*lit)->preBegin())), - m_part(lit.lines->m_part), adjacent(false), - advpol(lit.lines->advancePolicy()) - { - if (!it) { - if (fromEnd) --*this; else ++*this; - } - } - - /** empty constructor. Use only to copy another iterator into this one. - */ - EditableCaretBoxIterator() {} - - /** returns @p true when the current caret box is adjacent to the - * previously iterated caret box, i. e. no intervening caret boxes. - */ - bool isAdjacent() const { return adjacent; } - - /** increments the iterator to point to the next editable caret box. - */ - EditableCaretBoxIterator &operator ++() { advance(false); return *this; } - - /** decrements the iterator to point to the previous editable caret box. - */ - EditableCaretBoxIterator &operator --() { advance(true); return *this; } - - /** advances to the editable caret box to come - * @param toBegin true, move towards beginning, false, move towards end. - */ - void advance(bool toBegin); - -protected: - /** finds out if the given box is editable. - * @param boxit iterator to given caret box - * @param fromEnd true when advancing towards the beginning - * @return @p true if box is editable - */ - bool isEditable(const CaretBoxIterator &boxit, bool fromEnd); -}; - -/** - * Iterates through the editable lines of a document. - * - * This iterator, opposing to @p LineIterator, only regards editable lines. - * Additionally, this iterator enforces the caret advance policy. - * - * The iterator can be compared to normal LineIterators, especially to - * @ref LinearDocument::preBegin and @ref LinearDocument::end - * - * The line iterator becomes invalid when the associated LinearDocument object - * is destroyed. - * @since 3.2 - * @internal - * @author Leo Savernik - */ -class EditableLineIterator : public LineIterator { -public: - /** Initializes a new iterator. - * - * The iterator is set to the first following editable line or to the - * end if no editable line follows. - * @param it a line iterator to initialize this from - * @param fromEnd @p true, traverse towards the beginning in search of an - * editable line - */ - EditableLineIterator(const LineIterator &it, bool fromEnd = false) - : LineIterator(it) - { - if (!cbl) return; - if (!isEditable(*this)) advance(fromEnd); - } - - /** empty constructor. - * - * Only use if you want to copy another iterator onto it later. - */ - EditableLineIterator() {} - - /** seek next line - * - * Guaranteed to crash if beyond beginning/end of document. - */ - EditableLineIterator &operator ++() { advance(false); return *this; } - - /** seek previous line. - * - * Guaranteed to crash if beyond beginning/end of document. - */ - EditableLineIterator &operator --() { advance(true); return *this; } - - /** advances to the line to come. - * @param toBegin true, move to previous line, false, move to next line. - */ - void advance(bool toBegin); - -protected: - /** finds out if the current line is editable. - * - * @param it check caret box line iterator points to - * @return @p true if line is editable - */ - bool isEditable(LineIterator &it) - { - EditableCaretBoxIterator fbit = it; - return fbit != (*it)->end(); - } - -}; - -/** Represents a render table as a linear list of rows. - * - * This iterator abstracts from table sections and treats tables as a linear - * representation of all rows they contain. - * @author Leo Savernik - * @internal - * @since 3.2 - */ -class TableRowIterator { -protected: - TableSectionIterator sec; // current section - int index; // index of row within section -public: - /** Constructs a new iterator. - * @param table table to iterate through. - * @param fromEnd @p true to iterate towards the beginning - * @param row pointer to row to start with, 0 starts at the first/last - * row. - */ - TableRowIterator(RenderTable *table, bool fromEnd = false, - RenderTableSection::RowStruct *row = 0); - - /** Constructs a new iterator. - * @param section table section to begin with - * @param index index within table section - */ - TableRowIterator(RenderTableSection *section, int index) - : sec(section), index(index) - {} - - /** empty constructor. This must be assigned another iterator before it is - * useable. - */ - TableRowIterator() {} - - /** returns the current table row. - * @return the row or 0 if the end of the table has been reached. - */ - RenderTableSection::RowStruct *operator *() - { - if (!*sec) return 0; - return &(*sec)->grid[index]; - } - - /** advances to the next row - */ - TableRowIterator &operator ++(); - - /** advances to the previous row - */ - TableRowIterator &operator --(); - -protected: -}; - -/** Iterates through the editable lines of a document, in a topological order. - * - * The differences between this and the EditableLineIterator lies in the way - * lines are inquired. While the latter steps through the lines in document - * order, the former takes into consideration ergonomics. - * - * This is especially useful for tables. EditableLineIterator traverses all - * table cells from left to right, top to bottom, while this one will - * actually snap to the cell in the right position, and traverse only - * upwards/downwards, thus providing a more intuitive navigation. - * - * @author Leo Savernik - * @internal - * @since 3.2 - */ -class ErgonomicEditableLineIterator : public EditableLineIterator { -protected: - int xCoor; // x-coordinate to determine cell position -public: - /** Initializes a new ergonomic editable line iterator from the given one. - * @param it line iterator - * @param x absolute x-coordinate for cell determination - */ - ErgonomicEditableLineIterator(const LineIterator &it, int x) - : EditableLineIterator(it), xCoor(x) {} - - /** Constructs an uninitialized iterator which must be assigned a line iterator before - * it can be used. - */ - ErgonomicEditableLineIterator() {} - - /** seek next line. - * - * The next line will be one that is visually situated below this line. - */ - ErgonomicEditableLineIterator &operator ++(); - - /** seek previous line. - * - * The previous line will be one that is visually situated above this line. - */ - ErgonomicEditableLineIterator &operator --(); - -protected: - /** determines the topologically next render object. - * @param oldCell table cell the original object was under. - * @param newObject object to determine whether and which transition - * between cells is to be handled. It does not have to be an object in the correct - * topological cell, a simple delivery from an editable line iterator suffices. - * @param toBegin if @p true, iterate towards the beginning - */ - void determineTopologicalElement(RenderTableCell *oldCell, - RenderObject *newObject, bool toBegin); - - /** initializes the iterator to point to the first previous/following editable - * line. - * @param newBlock take this as base block. - * @param toBegin @p true, iterate towards beginning. - */ - void calcAndStoreNewLine(RenderBlock *newBlock, bool toBegin); - -}; - -/** - * Provides iterating through the document in terms of characters. Only the - * editable characters are regarded. - * - * This iterator represents the document, which is structured as a tree itself, - * as a linear stream of characters. - */ -class EditableCharacterIterator { -protected: - EditableLineIterator _it; - EditableCaretBoxIterator ebit; - long _offset; // offset within current caret box. - int _char; - bool _end:1; // true when end of document has been reached - -public: - - /** empty constructor. - * - * Only use if you want to assign another iterator as no fields will - * be initialized. - */ - EditableCharacterIterator() {} - - /** constructs a new iterator from the given linear document. - * - * @param ld linear representation of document. - */ - EditableCharacterIterator(LinearDocument *ld) - : _it(ld->current()), - ebit(_it, false, &_it.currentCaretBox()), - _offset(_it.currentModifiedOffset()), _char(-1), _end(false) - { - // ### temporary fix for illegal nodes - if (_it == ld->end()) { _end = true; return; } - initFirstChar(); - } - - /** returns the current character, or -1 if not on a text node, or beyond - * the end. - */ - int chr() const { return _char; } - - /** returns the current character as a unicode symbol, substituting - * a blank for a non-text node. - */ - TQChar operator *() const { return TQChar(_char >= 0 ? _char : ' '); } - - /** returns true when the end of the document has been reached. - */ - bool isEnd() const { return _end; } - /** returns the current offset - */ - long offset() const { return _offset; } - /** returns the current render object. - */ - RenderObject *renderer() const { return (*ebit)->object(); } - /** returns the current caret box. - * - * Will crash if beyond end. - */ - CaretBox *caretBox() const { return *ebit; } - /** returns the current inline box. - * - * May be 0 if the current element has none, or if the end has been reached. - * Therefore, do *not* use this to test for the end condition, use node() - * instead. - */ - InlineBox *inlineBox() const { return (*ebit)->inlineBox(); } - /** returns whether the current line box represents the outside of its - * render object. - */ -// bool boxIsOutside() const { return _it.isOutside(); } - - /** moves to the next editable character. - */ - EditableCharacterIterator &operator ++(); - - /** moves to the previous editable character. - */ - EditableCharacterIterator &operator --(); - -protected: - /** initializes the _char member by reading the character at the current - * offset, peeking ahead as necessary. - */ - void initFirstChar(); - /** reads ahead the next node and updates the data structures accordingly - */ - void peekNext() - { - EditableCaretBoxIterator copy = ebit; - ++copy; - if (copy == (*_it)->end()) { _char = -1; return; } - - CaretBox *box = *copy; - InlineBox *b = box->inlineBox(); - if (b && !box->isOutside() && b->isInlineTextBox()) - _char = static_cast<RenderText *>(b->object())->str->s[b->minOffset()].unicode(); - else - _char = -1; - } - /** reads ahead the previous node and updates the data structures accordingly - */ - void peekPrev() - { - --ebit; - } - -}; - - -}/*namespace khtml*/ - - -#endif |