khtml Library API Documentation

khtml_caret_p.h

00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2003-2004 Leo Savernik <l.savernik@aon.at>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #ifndef KHTML_CARET_P_H
00022 #define KHTML_CARET_P_H
00023 
00024 #include "rendering/render_table.h"
00025 
00026 #include <qvaluevector.h>
00027 
00028 #define DEBUG_CARETMODE 0
00029 
00030 class QFontMetrics;
00031 
00032 namespace DOM {
00033   class NodeImpl;
00034   class ElementImpl;
00035 }
00036 
00037 namespace khtml {
00038 
00054 enum CaretAdvancePolicy {
00055     LeafsOnly, IndicatedFlows, VisibleFlows
00056 };
00057 
00061 struct CaretViewContext {
00062     int freqTimerId;        // caret blink frequency timer id
00063     int x, y;           // caret position in viewport coordinates
00064                     // (y specifies the top, not the baseline)
00065     int width;          // width of caret in pixels
00066     int height;         // height of caret in pixels
00067     bool visible;       // true if currently visible.
00068     bool displayed;     // true if caret is to be displayed at all.
00069     bool caretMoved;        // set to true once caret has been moved in page
00070                     // how to display the caret when view is not focused
00071     KHTMLPart::CaretDisplayPolicy displayNonFocused;
00072 
00080     int origX;
00081 
00082     bool keyReleasePending; // true if keypress under caret mode awaits
00083                     // corresponding release event
00084     CaretViewContext() : freqTimerId(-1), x(0), y(0), width(1), height(16),
00085         visible(true), displayed(false), caretMoved(false),
00086     displayNonFocused(KHTMLPart::CaretInvisible), origX(0),
00087     keyReleasePending(false)
00088     {}
00089 };
00090 
00094 struct EditorContext {
00095     bool override;      // true if typed characters should override
00096                     // the existing ones.
00097 
00098     EditorContext() : override(false)
00099     {}
00100 };
00101 
00102 class LinearDocument;
00103 
00115 template<class T> class MassDeleter : public QValueVector<T *> {
00116 public:
00117   MassDeleter(size_t reserved = 1) { this->reserve(reserved); }
00118   ~MassDeleter()
00119   {
00120     typename QValueVector<T *>::Iterator nd = this->end();
00121     for (typename QValueVector<T *>::Iterator it = this->begin(); it != nd; ++it)
00122       delete *it;
00123   }
00124 };
00125 
00126 class CaretBoxLine;
00127 
00140 class CaretBox {
00141 protected:
00142   InlineBox *_box;      // associated inline box if available.
00143   short _w;         // width of box in pixels
00144   int _h;           // height of box in pixels
00145   int _x;           // x coordinate relative to containing block
00146   int _y;           // y coordinate relative to containing block
00147   RenderBox *cb;        // containing block
00148   bool _outside:1;      // true when representing the outside of the element
00149   bool outside_end:1;       // at ending outside of element rather than at beginning
00150   // 29 bits unused
00151 
00152 public:
00154   CaretBox() {}
00156   CaretBox(InlineBox *ibox, bool outside, bool outsideEnd) : _box(ibox),
00157     _w((short)ibox->width()), _h(ibox->height()), _x(ibox->xPos()),
00158         _y(ibox->yPos()), cb(0), _outside(outside), outside_end(outsideEnd)
00159   {
00160     RenderObject *r = ibox->object();
00161     if (r) cb = r->containingBlock();
00162   }
00164   CaretBox(int x, int y, int w, int h, RenderBox *cb, bool outside, bool outsideEnd) :
00165          _box(0), _w((short)w), _h(h), _x(x), _y(y), cb(cb), _outside(outside),
00166          outside_end(outsideEnd)
00167   {}
00168 
00169   int width() const { return _w; }
00170   int height() const { return _h; }
00171   int xPos() const { return _x; }
00172   int yPos() const { return _y; }
00173   RenderBox *enclosingObject() const { return cb; }
00174   InlineBox *inlineBox() const { return _box; }
00175 
00179   RenderBlock *containingBlock() const { return _box ? static_cast<RenderBlock *>(cb) : cb->containingBlock(); }
00180 
00189   bool isInline() const { return _box; }
00192   bool isInlineTextBox() const { return _box && _box->isInlineTextBox(); }
00195   bool isLineBreak() const
00196   {
00197     return _box && _box->object() && _box->object()->isBR();
00198   }
00202   bool isOutside() const { return _outside; }
00209   bool isOutsideEnd() const { return outside_end; }
00211   RenderObject *object() const { return _box ? _box->object() : cb; }
00212 
00215   long minOffset() const { return _box && !isLineBreak() ? _box->minOffset() : 0; }
00218   long maxOffset() const { return _box && !isLineBreak() ? _box->maxOffset() : 0; }
00219 
00220 #if DEBUG_CARETMODE > 0
00221   void dump(QTextStream &ts, const QString &ind) const;
00222 #endif
00223 
00224   friend class CaretBoxLine;
00225 };
00226 
00227 typedef MassDeleter<CaretBox> CaretBoxDeleter;
00228 
00236 class CaretBoxIterator {
00237 protected:
00238   CaretBoxLine *cbl;        // associated caret box line
00239   int index;            // current index
00240 
00241 public:
00242   // Let standard constructor/copy constructor/destructor/assignment operator
00243   // be defined by the compiler. They do exactly what we want.
00244 
00245   bool operator ==(const CaretBoxIterator &it) const
00246   {
00247     return cbl == it.cbl && index == it.index;
00248   }
00249 
00250   bool operator !=(const CaretBoxIterator &it) const
00251   {
00252     return !operator ==(it);
00253   }
00254 
00258   CaretBox *data() const;
00262   CaretBox *operator *() const { return data(); }
00263 
00266   CaretBoxIterator &operator ++() { index++; return *this; }
00269   CaretBoxIterator &operator --() { index--; return *this; }
00270 
00271   friend class CaretBoxLine;
00272   friend class EditableCaretBoxIterator;
00273 };
00274 
00299 class CaretBoxLine {
00300 protected:
00301   CaretBoxDeleter caret_boxes;
00302   // base flow box which caret boxes have been constructed for
00303   InlineFlowBox *basefb;
00304 
00305   CaretBoxLine() : caret_boxes(8), basefb(0) {}
00306   CaretBoxLine(InlineFlowBox *basefb) : caret_boxes(8), basefb(basefb) {}
00307 public:
00308 #if DEBUG_CARETMODE > 3
00309   ~CaretBoxLine() { kdDebug(6200) << k_funcinfo << "called" << endl; }
00310 #endif
00311 
00312   CaretBoxIterator begin()
00313   {
00314     CaretBoxIterator it;
00315     it.cbl = this;
00316     it.index = 0;
00317     return it;
00318   }
00319   CaretBoxIterator end()
00320   {
00321     CaretBoxIterator it;
00322     it.cbl = this;
00323     it.index = caret_boxes.size();
00324     return it;
00325   }
00326   CaretBoxIterator preBegin()
00327   {
00328     CaretBoxIterator it;
00329     it.cbl = this;
00330     it.index = -1;
00331     return it;
00332   }
00333   CaretBoxIterator preEnd()
00334   {
00335     CaretBoxIterator it;
00336     it.cbl = this;
00337     it.index = caret_boxes.size() - 1;
00338     return it;
00339   }
00340 
00347   InlineFlowBox *baseFlowBox() const { return basefb; }
00348 
00350   RenderBlock *containingBlock() const { return caret_boxes[0]->containingBlock(); }
00352   RenderBox *enclosingObject() const { return caret_boxes[0]->enclosingObject(); }
00353 
00358   bool isOutside() const
00359   {
00360     const CaretBox *cbox = caret_boxes[0];
00361     return !cbox->isInline() && cbox->isOutside();
00362   }
00363 
00368   bool isOutsideEnd() const { return caret_boxes[0]->isOutsideEnd(); }
00369 
00382   static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
00383     InlineFlowBox *baseFlowBox, InlineBox *seekBox, bool seekOutside,
00384         bool seekOutsideEnd, CaretBoxIterator &iter,
00385     RenderObject *seekObject = 0) /*KDE_NO_EXPORT*/;
00386 
00395   static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
00396     RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/;
00397 
00398 #if DEBUG_CARETMODE > 0
00399   void dump(QTextStream &ts, const QString &ind) const;
00400   QString information() const
00401   {
00402     QString result;
00403     QTextStream ts(&result, IO_WriteOnly);
00404     dump(ts, QString::null);
00405     return result;
00406   }
00407 #endif
00408 
00409 protected:
00411   struct SeekBoxParams {
00412     InlineBox *box;
00413     bool outside;
00414     bool outsideEnd;
00415     bool found;
00416     RenderObject *r;    // if box is 0, seek for equal render objects instead
00417     CaretBoxIterator &it;
00418 
00419     SeekBoxParams(InlineBox *box, bool outside, bool outsideEnd, RenderObject *obj, CaretBoxIterator &it)
00420         : box(box), outside(outside), outsideEnd(outsideEnd), found(false), r(obj), it(it)
00421     {}
00422 
00424     bool equalsBox(const InlineBox *box, bool outside, bool outsideEnd) const
00425     {
00426       return (this->box && this->box == box
00427               || this->r == box->object())
00428           && this->outside == outside
00429           && (!this->outside || this->outsideEnd == outsideEnd);
00430     }
00432     bool operator ==(const CaretBox *cbox) const
00433     {
00434       return equalsBox(cbox->inlineBox(), cbox->isOutside(), cbox->isOutsideEnd());
00435     }
00441     bool check(const CaretBoxIterator &chit)
00442     {
00443       if (*this == *chit) {
00444         Q_ASSERT(!found);
00445         found = true;
00446         it = chit;
00447       }
00448       return found;
00449     }
00450   };
00451 
00457   void addConvertedInlineBox(InlineBox *, SeekBoxParams &) /*KDE_NO_EXPORT*/;
00458 
00465   void addCreatedInlineBoxEdge(InlineBox *box, const QFontMetrics &fm,
00466     bool left, bool rtl) /*KDE_NO_EXPORT*/;
00473   void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const QFontMetrics &fm,
00474     bool left, bool rtl) /*KDE_NO_EXPORT*/;
00479   void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const QFontMetrics &fm) /*KDE_NO_EXPORT*/;
00480 
00481   friend class CaretBoxIterator;
00482 };
00483 
00484 typedef MassDeleter<CaretBoxLine> CaretBoxLineDeleter;
00485 
00486 inline CaretBox *CaretBoxIterator::data() const { return cbl->caret_boxes[index]; }
00487 
00497 class LineIterator
00498 {
00499 protected:
00500   LinearDocument *lines;    // associated document
00501   CaretBoxLine *cbl;        // current caret box line
00502 
00503   static CaretBoxIterator currentBox;   // current inline box
00504   static long currentOffset;
00505 
00506   // Note: cbl == 0 indicates a position beyond the beginning or the
00507   // end of a document.
00508 
00511   LineIterator() {}
00512 
00519   LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset);
00520 
00521 public:
00526   CaretBoxLine *operator *() const { return cbl; }
00527 
00530   LinearDocument *linearDocument() const { return lines; }
00531 
00536   LineIterator &operator ++() { advance(false); return *this; }
00537 
00542   LineIterator &operator --() { advance(true); return *this; }
00543 
00547   bool operator ==(const LineIterator &it) const
00548   {
00549     return lines == it.lines && cbl == it.cbl;
00550   }
00551 
00554   bool operator !=(const LineIterator &it) const
00555   {
00556     return !operator ==(it);
00557   }
00558 
00564   bool isOutsideEnd() { return cbl->isOutsideEnd(); }
00565 
00569   bool isOutside() const { return cbl->isOutside(); }
00570 
00574   void advance(bool toBegin);
00575 
00586   static CaretBoxIterator &currentCaretBox() { return currentBox; }
00587 
00596   static long currentModifiedOffset() { return currentOffset; }
00597 
00598 protected:
00601   void nextBlock();
00604   void prevBlock();
00605 
00606   friend class CaretBoxIterator;
00607   friend class EditableLineIterator;
00608   friend class EditableCaretBoxIterator;
00609   friend class EditableCharacterIterator;
00610   friend class LinearDocument;
00611 };
00612 
00633 class LinearDocument {
00634 public:
00635   typedef LineIterator Iterator;
00636 
00651   LinearDocument(KHTMLPart *part, DOM::NodeImpl *node, long offset,
00652         CaretAdvancePolicy advancePolicy, DOM::ElementImpl *baseElem);
00653 
00654   virtual ~LinearDocument();
00655 
00664   bool isValid() const      // FIXME: not yet impl'd
00665   {
00666     return true;
00667   }
00668 
00676   int count() const;
00677 
00682   Iterator current();
00683 
00687   const Iterator &end() const { return _end; }
00688 
00692   Iterator preEnd();
00693 
00697   Iterator begin();
00698 
00703   const Iterator &preBegin() const { return _preBegin; }
00704 
00708   CaretAdvancePolicy advancePolicy() const { return advPol; }
00709 
00717   RenderObject *baseObject() const { return base; }
00718 
00719 protected:
00720   void initPreBeginIterator();
00721   void initEndIterator();
00722 
00723 protected:
00724   CaretBoxLineDeleter cblDeleter;   // mass deleter for caret box lines
00725   DOM::NodeImpl *node;
00726   long offset;
00727 
00728   Iterator _preBegin;
00729   Iterator _end;
00730 
00731   KHTMLPart *m_part;
00732   CaretAdvancePolicy advPol;
00733   RenderObject *base;
00734 
00735   friend class LineIterator;
00736   friend class EditableLineIterator;
00737   friend class ErgonomicEditableLineIterator;
00738   friend class CaretBoxIterator;
00739   friend class EditableCaretBoxIterator;
00740   friend class EditableCharacterIterator;
00741 };
00742 
00754 class EditableCaretBoxIterator : public CaretBoxIterator {
00755   KHTMLPart *m_part;
00756   bool adjacent;
00757   CaretAdvancePolicy advpol;    // caret advance policy
00758 
00759 public:
00763   EditableCaretBoxIterator(LineIterator &lit, bool fromEnd = false,
00764         CaretBoxIterator *it = 0)
00765         : CaretBoxIterator(it ? *it : (fromEnd ? (*lit)->end() : (*lit)->preBegin())),
00766                 m_part(lit.lines->m_part), adjacent(false),
00767                 advpol(lit.lines->advancePolicy())
00768   {
00769     if (!it) {
00770       if (fromEnd) --*this; else ++*this;
00771     }
00772   }
00773 
00776   EditableCaretBoxIterator() {}
00777 
00781   bool isAdjacent() const { return adjacent; }
00782 
00785   EditableCaretBoxIterator &operator ++() { advance(false); return *this; }
00786 
00789   EditableCaretBoxIterator &operator --() { advance(true); return *this; }
00790 
00794   void advance(bool toBegin);
00795 
00796 protected:
00802   bool isEditable(const CaretBoxIterator &boxit, bool fromEnd);
00803 };
00804 
00820 class EditableLineIterator : public LineIterator {
00821 public:
00830   EditableLineIterator(const LineIterator &it, bool fromEnd = false)
00831         : LineIterator(it)
00832   {
00833     if (!cbl) return;
00834     if (!isEditable(*this)) advance(fromEnd);
00835   }
00836 
00841   EditableLineIterator() {}
00842 
00847   EditableLineIterator &operator ++() { advance(false); return *this; }
00848 
00853   EditableLineIterator &operator --() { advance(true); return *this; }
00854 
00858   void advance(bool toBegin);
00859 
00860 protected:
00867   bool isEditable(LineIterator &it)
00868   {
00869     EditableCaretBoxIterator fbit = it;
00870     return fbit != (*it)->end();
00871   }
00872 
00873 };
00874 
00883 class TableRowIterator {
00884 protected:
00885   TableSectionIterator sec; // current section
00886   int index;            // index of row within section
00887 public:
00894   TableRowIterator(RenderTable *table, bool fromEnd = false,
00895         RenderTableSection::RowStruct *row = 0);
00896 
00901   TableRowIterator(RenderTableSection *section, int index)
00902     : sec(section), index(index)
00903   {}
00904 
00908   TableRowIterator() {}
00909 
00913   RenderTableSection::RowStruct *operator *()
00914   {
00915     if (!*sec) return 0;
00916     return &(*sec)->grid[index];
00917   }
00918 
00921   TableRowIterator &operator ++();
00922 
00925   TableRowIterator &operator --();
00926 
00927 protected:
00928 };
00929 
00945 class ErgonomicEditableLineIterator : public EditableLineIterator {
00946 protected:
00947   int xCoor;        // x-coordinate to determine cell position
00948 public:
00953   ErgonomicEditableLineIterator(const LineIterator &it, int x)
00954     : EditableLineIterator(it), xCoor(x) {}
00955 
00959   ErgonomicEditableLineIterator() {}
00960 
00965   ErgonomicEditableLineIterator &operator ++();
00966 
00971   ErgonomicEditableLineIterator &operator --();
00972 
00973 protected:
00981   void determineTopologicalElement(RenderTableCell *oldCell,
00982         RenderObject *newObject, bool toBegin);
00983 
00989   void calcAndStoreNewLine(RenderBlock *newBlock, bool toBegin);
00990 
00991 };
00992 
01000 class EditableCharacterIterator {
01001 protected:
01002   EditableLineIterator _it;
01003   EditableCaretBoxIterator ebit;
01004   long _offset;     // offset within current caret box.
01005   int _char;
01006   bool _end:1;      // true when end of document has been reached
01007 
01008 public:
01009 
01015   EditableCharacterIterator() {}
01016 
01021   EditableCharacterIterator(LinearDocument *ld)
01022         : _it(ld->current()),
01023                 ebit(_it, false, &_it.currentCaretBox()),
01024             _offset(_it.currentModifiedOffset()), _char(-1), _end(false)
01025   {
01026     // ### temporary fix for illegal nodes
01027     if (_it == ld->end()) { _end = true; return; }
01028     initFirstChar();
01029   }
01030 
01034   int chr() const { return _char; }
01035 
01039   QChar operator *() const { return QChar(_char >= 0 ? _char : ' '); }
01040 
01043   bool isEnd() const { return _end; }
01046   long offset() const { return _offset; }
01049   RenderObject *renderer() const { return (*ebit)->object(); }
01054   CaretBox *caretBox() const { return *ebit; }
01061   InlineBox *inlineBox() const { return (*ebit)->inlineBox(); }
01065 //  bool boxIsOutside() const { return _it.isOutside(); }
01066 
01069   EditableCharacterIterator &operator ++();
01070 
01073   EditableCharacterIterator &operator --();
01074 
01075 protected:
01079   void initFirstChar();
01082   void peekNext()
01083   {
01084     EditableCaretBoxIterator copy = ebit;
01085     ++copy;
01086     if (copy == (*_it)->end()) { _char = -1; return; }
01087 
01088     CaretBox *box = *copy;
01089     InlineBox *b = box->inlineBox();
01090     if (b && !box->isOutside() && b->isInlineTextBox())
01091       _char = static_cast<RenderText *>(b->object())->str->s[b->minOffset()].unicode();
01092     else
01093       _char = -1;
01094   }
01097   void peekPrev()
01098   {
01099     --ebit;
01100   }
01101 
01102 };
01103 
01104 
01105 }/*namespace khtml*/
01106 
01107 
01108 #endif
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Jan 15 13:34:39 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003