• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KHTML

khtml_caret_p.h

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #ifndef KHTML_CARET_P_H
00022 #define KHTML_CARET_P_H
00023 
00024 #include "rendering/render_table.h"
00025 
00026 
00027 #define DEBUG_CARETMODE 0
00028 
00029 class QFontMetrics;
00030 
00031 namespace DOM {
00032   class NodeImpl;
00033   class ElementImpl;
00034 }
00035 
00036 namespace khtml {
00037 
00053 enum CaretAdvancePolicy {
00054     LeafsOnly, IndicatedFlows, VisibleFlows
00055 };
00056 
00060 struct CaretViewContext {
00061     int freqTimerId;        // caret blink frequency timer id
00062     int x, y;           // caret position in viewport coordinates
00063                     // (y specifies the top, not the baseline)
00064     int width;          // width of caret in pixels
00065     int height;         // height of caret in pixels
00066     bool visible;       // true if currently visible.
00067     bool displayed;     // true if caret is to be displayed at all.
00068     bool caretMoved;        // set to true once caret has been moved in page
00069                     // how to display the caret when view is not focused
00070     KHTMLPart::CaretDisplayPolicy displayNonFocused;
00071 
00079     int origX;
00080 
00081     bool keyReleasePending; // true if keypress under caret mode awaits
00082                     // corresponding release event
00083     CaretViewContext() : freqTimerId(-1), x(0), y(0), width(1), height(16),
00084         visible(true), displayed(false), caretMoved(false),
00085     displayNonFocused(KHTMLPart::CaretInvisible), origX(0),
00086     keyReleasePending(false)
00087     {}
00088 };
00089 
00090 class LinearDocument;
00091 
00102 template<class T> class MassDeleter : public QVector<T *> {
00103 public:
00104   MassDeleter(size_t reserved = 1) { this->reserve(reserved); }
00105   ~MassDeleter()
00106   {
00107     typename QVector<T *>::Iterator nd = this->end();
00108     for (typename QVector<T *>::Iterator it = this->begin(); it != nd; ++it)
00109       delete *it;
00110   }
00111 };
00112 
00113 class CaretBoxLine;
00114 
00126 class CaretBox {
00127 protected:
00128   InlineBox *_box;      // associated inline box if available.
00129   short _w;         // width of box in pixels
00130   int _h;           // height of box in pixels
00131   int _x;           // x coordinate relative to containing block
00132   int _y;           // y coordinate relative to containing block
00133   RenderBox *cb;        // containing block
00134   bool _outside:1;      // true when representing the outside of the element
00135   bool outside_end:1;       // at ending outside of element rather than at beginning
00136   // 29 bits unused
00137 
00138 public:
00140   CaretBox() {}
00142   CaretBox(InlineBox *ibox, bool outside, bool outsideEnd) : _box(ibox),
00143     _w((short)ibox->width()), _h(ibox->height()), _x(ibox->xPos()),
00144         _y(ibox->yPos()), cb(0), _outside(outside), outside_end(outsideEnd)
00145   {
00146     RenderObject *r = ibox->object();
00147     if (r) cb = r->containingBlock();
00148   }
00150   CaretBox(int x, int y, int w, int h, RenderBox *cb, bool outside, bool outsideEnd) :
00151          _box(0), _w((short)w), _h(h), _x(x), _y(y), cb(cb), _outside(outside),
00152          outside_end(outsideEnd)
00153   {}
00154 
00155   int width() const { return _w; }
00156   int height() const { return _h; }
00157   int xPos() const { return _x; }
00158   int yPos() const { return _y; }
00159   RenderBox *enclosingObject() const { return cb; }
00160   InlineBox *inlineBox() const { return _box; }
00161 
00165   RenderBlock *containingBlock() const { return _box ? static_cast<RenderBlock *>(cb) : cb->containingBlock(); }
00166 
00175   bool isInline() const { return _box; }
00178   bool isInlineTextBox() const { return _box && _box->isInlineTextBox(); }
00181   bool isLineBreak() const
00182   {
00183     return _box && _box->object() && _box->object()->isBR();
00184   }
00188   bool isOutside() const { return _outside; }
00195   bool isOutsideEnd() const { return outside_end; }
00197   RenderObject *object() const { return _box ? _box->object() : cb; }
00198 
00201   long minOffset() const { return _box && !isLineBreak() ? _box->minOffset() : 0; }
00204   long maxOffset() const { return _box && !isLineBreak() ? _box->maxOffset() : 0; }
00205 
00206 #if DEBUG_CARETMODE > 0
00207   void dump(QTextStream &ts, const QString &ind) const;
00208 #endif
00209 
00210   friend class CaretBoxLine;
00211 };
00212 
00213 typedef MassDeleter<CaretBox> CaretBoxDeleter;
00214 
00221 class CaretBoxIterator {
00222 protected:
00223   CaretBoxLine *cbl;        // associated caret box line
00224   int index;            // current index
00225 
00226 public:
00227   // Let standard constructor/copy constructor/destructor/assignment operator
00228   // be defined by the compiler. They do exactly what we want.
00229   CaretBoxIterator()
00230     : cbl( 0 ), index( 0 )
00231   {
00232   }
00233 
00234   bool operator ==(const CaretBoxIterator &it) const
00235   {
00236     return cbl == it.cbl && index == it.index;
00237   }
00238 
00239   bool operator !=(const CaretBoxIterator &it) const
00240   {
00241     return !operator ==(it);
00242   }
00243 
00247   CaretBox *data() const;
00251   CaretBox *operator *() const { return data(); }
00252 
00255   CaretBoxIterator &operator ++() { index++; return *this; }
00258   CaretBoxIterator &operator --() { index--; return *this; }
00259 
00260   friend class CaretBoxLine;
00261   friend class EditableCaretBoxIterator;
00262 };
00263 
00290 class CaretBoxLine {
00291 protected:
00292   CaretBoxDeleter caret_boxes;
00293   // base flow box which caret boxes have been constructed for
00294   InlineFlowBox *basefb;
00295 
00296   CaretBoxLine() : caret_boxes(8), basefb(0) {}
00297   CaretBoxLine(InlineFlowBox *basefb) : caret_boxes(8), basefb(basefb) {}
00298 public:
00299 #if DEBUG_CARETMODE > 3
00300   ~CaretBoxLine() { kDebug(6200) << "called"; }
00301 #endif
00302 
00303   CaretBoxIterator begin()
00304   {
00305     CaretBoxIterator it;
00306     it.cbl = this;
00307     it.index = 0;
00308     return it;
00309   }
00310   CaretBoxIterator end()
00311   {
00312     CaretBoxIterator it;
00313     it.cbl = this;
00314     it.index = caret_boxes.size();
00315     return it;
00316   }
00317   CaretBoxIterator preBegin()
00318   {
00319     CaretBoxIterator it;
00320     it.cbl = this;
00321     it.index = -1;
00322     return it;
00323   }
00324   CaretBoxIterator preEnd()
00325   {
00326     CaretBoxIterator it;
00327     it.cbl = this;
00328     it.index = caret_boxes.size() - 1;
00329     return it;
00330   }
00331 
00338   InlineFlowBox *baseFlowBox() const { return basefb; }
00339 
00341   RenderBlock *containingBlock() const { return caret_boxes[0]->containingBlock(); }
00343   RenderBox *enclosingObject() const { return caret_boxes[0]->enclosingObject(); }
00344 
00349   bool isOutside() const
00350   {
00351     const CaretBox *cbox = caret_boxes[0];
00352     return !cbox->isInline() && cbox->isOutside();
00353   }
00354 
00359   bool isOutsideEnd() const { return caret_boxes[0]->isOutsideEnd(); }
00360 
00373   static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
00374     InlineFlowBox *baseFlowBox, InlineBox *seekBox, bool seekOutside,
00375         bool seekOutsideEnd, CaretBoxIterator &iter,
00376     RenderObject *seekObject = 0) /*KDE_NO_EXPORT*/;
00377 
00386   static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
00387     RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/;
00388 
00389 #if DEBUG_CARETMODE > 0
00390   void dump(QTextStream &ts, const QString &ind) const;
00391   QString information() const
00392   {
00393     QString result;
00394     QTextStream ts(&result, QIODevice::WriteOnly);
00395     dump(ts, QString());
00396     return result;
00397   }
00398 #endif
00399 
00400 protected:
00402   struct SeekBoxParams {
00403     InlineBox *box;
00404     bool outside;
00405     bool outsideEnd;
00406     bool found;
00407     RenderObject *r;    // if box is 0, seek for equal render objects instead
00408     CaretBoxIterator &it;
00409 
00410     SeekBoxParams(InlineBox *box, bool outside, bool outsideEnd, RenderObject *obj, CaretBoxIterator &it)
00411         : box(box), outside(outside), outsideEnd(outsideEnd), found(false), r(obj), it(it)
00412     {}
00413 
00415     bool equalsBox(const InlineBox *box, bool outside, bool outsideEnd) const
00416     {
00417       return (this->box && this->box == box
00418               || this->r == box->object())
00419           && this->outside == outside
00420           && (!this->outside || this->outsideEnd == outsideEnd);
00421     }
00423     bool operator ==(const CaretBox *cbox) const
00424     {
00425       return equalsBox(cbox->inlineBox(), cbox->isOutside(), cbox->isOutsideEnd());
00426     }
00432     bool check(const CaretBoxIterator &chit)
00433     {
00434       if (*this == *chit) {
00435         Q_ASSERT(!found);
00436         found = true;
00437         it = chit;
00438       }
00439       return found;
00440     }
00441   };
00442 
00448   void addConvertedInlineBox(InlineBox *, SeekBoxParams &) /*KDE_NO_EXPORT*/;
00449 
00456   void addCreatedInlineBoxEdge(InlineBox *box, const QFontMetrics &fm,
00457     bool left, bool rtl) /*KDE_NO_EXPORT*/;
00464   void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const QFontMetrics &fm,
00465     bool left, bool rtl) /*KDE_NO_EXPORT*/;
00470   void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const QFontMetrics &fm) /*KDE_NO_EXPORT*/;
00471 
00472   friend class CaretBoxIterator;
00473 };
00474 
00475 typedef MassDeleter<CaretBoxLine> CaretBoxLineDeleter;
00476 
00477 inline CaretBox *CaretBoxIterator::data() const { return cbl->caret_boxes[index]; }
00478 
00487 class LineIterator
00488 {
00489 protected:
00490   LinearDocument *lines;    // associated document
00491   CaretBoxLine *cbl;        // current caret box line
00492 
00493   static CaretBoxIterator currentBox;   // current inline box
00494   static long currentOffset;
00495 
00496   // Note: cbl == 0 indicates a position beyond the beginning or the
00497   // end of a document.
00498 
00501   LineIterator() {}
00502 
00509   LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset);
00510 
00511 public:
00516   CaretBoxLine *operator *() const { return cbl; }
00517 
00520   LinearDocument *linearDocument() const { return lines; }
00521 
00526   LineIterator &operator ++() { advance(false); return *this; }
00527 
00532   LineIterator &operator --() { advance(true); return *this; }
00533 
00537   bool operator ==(const LineIterator &it) const
00538   {
00539     return lines == it.lines && cbl == it.cbl;
00540   }
00541 
00544   bool operator !=(const LineIterator &it) const
00545   {
00546     return !operator ==(it);
00547   }
00548 
00554   bool isOutsideEnd() { return cbl->isOutsideEnd(); }
00555 
00559   bool isOutside() const { return cbl->isOutside(); }
00560 
00564   void advance(bool toBegin);
00565 
00576   static CaretBoxIterator &currentCaretBox() { return currentBox; }
00577 
00586   static long currentModifiedOffset() { return currentOffset; }
00587 
00588 protected:
00591   void nextBlock();
00594   void prevBlock();
00595 
00596   friend class CaretBoxIterator;
00597   friend class EditableLineIterator;
00598   friend class EditableCaretBoxIterator;
00599   friend class EditableCharacterIterator;
00600   friend class LinearDocument;
00601 };
00602 
00622 class LinearDocument {
00623 public:
00624   typedef LineIterator Iterator;
00625 
00640   LinearDocument(KHTMLPart *part, DOM::NodeImpl *node, long offset,
00641         CaretAdvancePolicy advancePolicy, DOM::ElementImpl *baseElem);
00642 
00643   virtual ~LinearDocument();
00644 
00653   bool isValid() const      // FIXME: not yet impl'd
00654   {
00655     return true;
00656   }
00657 
00665   int count() const;
00666 
00671   Iterator current();
00672 
00676   const Iterator &end() const { return _end; }
00677 
00681   Iterator preEnd();
00682 
00686   Iterator begin();
00687 
00692   const Iterator &preBegin() const { return _preBegin; }
00693 
00697   CaretAdvancePolicy advancePolicy() const { return advPol; }
00698 
00706   RenderObject *baseObject() const { return base; }
00707 
00708 protected:
00709   void initPreBeginIterator();
00710   void initEndIterator();
00711 
00712 protected:
00713   CaretBoxLineDeleter cblDeleter;   // mass deleter for caret box lines
00714   DOM::NodeImpl *node;
00715   long offset;
00716 
00717   Iterator _preBegin;
00718   Iterator _end;
00719 
00720   KHTMLPart *m_part;
00721   CaretAdvancePolicy advPol;
00722   RenderObject *base;
00723 
00724   friend class LineIterator;
00725   friend class EditableLineIterator;
00726   friend class ErgonomicEditableLineIterator;
00727   friend class CaretBoxIterator;
00728   friend class EditableCaretBoxIterator;
00729   friend class EditableCharacterIterator;
00730 };
00731 
00742 class EditableCaretBoxIterator : public CaretBoxIterator {
00743   KHTMLPart *m_part;
00744   bool adjacent;
00745   CaretAdvancePolicy advpol;    // caret advance policy
00746 
00747 public:
00751   EditableCaretBoxIterator(LineIterator &lit, bool fromEnd = false,
00752         CaretBoxIterator *it = 0)
00753         : CaretBoxIterator(it ? *it : (fromEnd ? (*lit)->end() : (*lit)->preBegin())),
00754                 m_part(lit.lines->m_part), adjacent(false),
00755                 advpol(lit.lines->advancePolicy())
00756   {
00757     if (!it) {
00758       if (fromEnd) --*this; else ++*this;
00759     }
00760   }
00761 
00764   EditableCaretBoxIterator() {}
00765 
00769   bool isAdjacent() const { return adjacent; }
00770 
00773   EditableCaretBoxIterator &operator ++() { advance(false); return *this; }
00774 
00777   EditableCaretBoxIterator &operator --() { advance(true); return *this; }
00778 
00782   void advance(bool toBegin);
00783 
00784 protected:
00790   bool isEditable(const CaretBoxIterator &boxit, bool fromEnd);
00791 };
00792 
00807 class EditableLineIterator : public LineIterator {
00808 public:
00817   EditableLineIterator(const LineIterator &it, bool fromEnd = false)
00818         : LineIterator(it)
00819   {
00820     if (!cbl) return;
00821     if (!isEditable(*this)) advance(fromEnd);
00822   }
00823 
00828   EditableLineIterator() {}
00829 
00834   EditableLineIterator &operator ++() { advance(false); return *this; }
00835 
00840   EditableLineIterator &operator --() { advance(true); return *this; }
00841 
00845   void advance(bool toBegin);
00846 
00847 protected:
00853   bool isEditable(LineIterator &it)
00854   {
00855     EditableCaretBoxIterator fbit = it;
00856     return fbit != (*it)->end();
00857   }
00858 
00859 };
00860 
00868 class TableRowIterator {
00869 protected:
00870   TableSectionIterator sec; // current section
00871   int index;            // index of row within section
00872 public:
00879   TableRowIterator(RenderTable *table, bool fromEnd = false,
00880         RenderTableSection::RowStruct *row = 0);
00881 
00886   TableRowIterator(RenderTableSection *section, int index)
00887     : sec(section), index(index)
00888   {}
00889 
00893   TableRowIterator() {}
00894 
00898   RenderTableSection::RowStruct *operator *()
00899   {
00900     if (!*sec) return 0;
00901     return &(*sec)->grid[index];
00902   }
00903 
00906   TableRowIterator &operator ++();
00907 
00910   TableRowIterator &operator --();
00911 
00912 protected:
00913 };
00914 
00929 class ErgonomicEditableLineIterator : public EditableLineIterator {
00930 protected:
00931   int xCoor;        // x-coordinate to determine cell position
00932 public:
00937   ErgonomicEditableLineIterator(const LineIterator &it, int x)
00938     : EditableLineIterator(it), xCoor(x) {}
00939 
00943   ErgonomicEditableLineIterator() {}
00944 
00949   ErgonomicEditableLineIterator &operator ++();
00950 
00955   ErgonomicEditableLineIterator &operator --();
00956 
00957 protected:
00965   void determineTopologicalElement(RenderTableCell *oldCell,
00966         RenderObject *newObject, bool toBegin);
00967 
00973   void calcAndStoreNewLine(RenderBlock *newBlock, bool toBegin);
00974 
00975 };
00976 
00984 class EditableCharacterIterator {
00985 protected:
00986   EditableLineIterator _it;
00987   EditableCaretBoxIterator ebit;
00988   long _offset;     // offset within current caret box.
00989   int _char;
00990   bool _end:1;      // true when end of document has been reached
00991 
00992 public:
00993 
00999   EditableCharacterIterator() {}
01000 
01005   EditableCharacterIterator(LinearDocument *ld)
01006         : _it(ld->current()),
01007                 ebit(_it, false, &_it.currentCaretBox()),
01008             _offset(_it.currentModifiedOffset()), _char(-1), _end(false)
01009   {
01010     // ### temporary fix for illegal nodes
01011     if (_it == ld->end()) { _end = true; return; }
01012     initFirstChar();
01013   }
01014 
01018   int chr() const { return _char; }
01019 
01023   QChar operator *() const { return QChar(_char >= 0 ? _char : ' '); }
01024 
01027   bool isEnd() const { return _end; }
01030   long offset() const { return _offset; }
01033   RenderObject *renderer() const { return (*ebit)->object(); }
01038   CaretBox *caretBox() const { return *ebit; }
01045   InlineBox *inlineBox() const { return (*ebit)->inlineBox(); }
01049 //  bool boxIsOutside() const { return _it.isOutside(); }
01050 
01053   EditableCharacterIterator &operator ++();
01054 
01057   EditableCharacterIterator &operator --();
01058 
01059 protected:
01063   void initFirstChar();
01066   void peekNext()
01067   {
01068     EditableCaretBoxIterator copy = ebit;
01069     ++copy;
01070     if (copy == (*_it)->end()) { _char = -1; return; }
01071 
01072     CaretBox *box = *copy;
01073     InlineBox *b = box->inlineBox();
01074     if (b && !box->isOutside() && b->isInlineTextBox())
01075       _char = static_cast<RenderText *>(b->object())->str->s[b->minOffset()].unicode();
01076     else
01077       _char = -1;
01078   }
01081   void peekPrev()
01082   {
01083     --ebit;
01084   }
01085 
01086 };
01087 
01088 
01089 }/*namespace khtml*/
01090 
01091 
01092 #endif

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal