00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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;
00063 int x, y;
00064
00065 int width;
00066 int height;
00067 bool visible;
00068 bool displayed;
00069 bool caretMoved;
00070
00071 KHTMLPart::CaretDisplayPolicy displayNonFocused;
00072
00080 int origX;
00081
00082 bool keyReleasePending;
00083
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;
00096
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;
00143 short _w;
00144 int _h;
00145 int _x;
00146 int _y;
00147 RenderBox *cb;
00148 bool _outside:1;
00149 bool outside_end:1;
00150
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;
00239 int index;
00240
00241 public:
00242
00243
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
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) ;
00386
00395 static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
00396 RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) ;
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;
00417 CaretBoxIterator ⁢
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 &) ;
00458
00465 void addCreatedInlineBoxEdge(InlineBox *box, const QFontMetrics &fm,
00466 bool left, bool rtl) ;
00473 void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const QFontMetrics &fm,
00474 bool left, bool rtl) ;
00479 void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const QFontMetrics &fm) ;
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;
00501 CaretBoxLine *cbl;
00502
00503 static CaretBoxIterator currentBox;
00504 static long currentOffset;
00505
00506
00507
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 ¤tCaretBox() { 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
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;
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;
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;
00886 int index;
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;
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;
01005 int _char;
01006 bool _end:1;
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
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
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 }
01106
01107
01108 #endif