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 #define DEBUG_CARETMODE 0
00027
00028 namespace khtml {
00029
00033 struct CaretViewContext {
00034 int freqTimerId;
00035 int x, y;
00036
00037 int width;
00038 int height;
00039 bool visible;
00040 bool displayed;
00041 bool caretMoved;
00042
00043 KHTMLPart::CaretDisplayPolicy displayNonFocused;
00044
00052 int origX;
00053
00054 bool keyReleasePending;
00055
00056 CaretViewContext() : freqTimerId(-1), x(0), y(0), width(1), height(16),
00057 visible(true), displayed(false), caretMoved(false),
00058 displayNonFocused(KHTMLPart::CaretInvisible), origX(0),
00059 keyReleasePending(false)
00060 {}
00061 };
00062
00066 struct EditorContext {
00067 bool override;
00068
00069
00070 EditorContext() : override(false)
00071 {}
00072 };
00073
00074 class LinearDocument;
00075
00085 class LineIterator
00086 {
00087 protected:
00088 LinearDocument *lines;
00089 RenderFlow *cb;
00090 InlineFlowBox *flowBox;
00091
00092 static InlineBox *currentBox;
00093
00094
00095
00096
00099 LineIterator() {}
00100
00107 LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset);
00108
00109 public:
00117 InlineFlowBox *operator *() const { return flowBox; }
00118
00123 LineIterator &operator ++();
00131 LineIterator operator ++(int);
00132
00137 LineIterator &operator --();
00145 LineIterator operator --(int);
00146
00152 LineIterator operator +(int summand) const;
00158 LineIterator operator -(int summand) const;
00159
00165 LineIterator &operator +=(int summand);
00171 LineIterator &operator -=(int summand);
00172
00176 bool operator ==(const LineIterator &it) const
00177 {
00178 return lines == it.lines
00179 && flowBox == it.flowBox && cb == it.cb;
00180 }
00181
00184 bool operator !=(const LineIterator &it) const
00185 {
00186 return !operator ==(it);
00187 }
00188
00198 static InlineBox *currentInlineBox() { return currentBox; }
00199
00200 protected:
00203 void nextBlock();
00206 void prevBlock();
00207
00208 friend class InlineBoxIterator;
00209 friend class EditableInlineBoxIterator;
00210 friend class LinearDocument;
00211 };
00212
00213
00234 class LinearDocument {
00235 public:
00236 typedef LineIterator Iterator;
00237
00247 LinearDocument(KHTMLPart *part, DOM::NodeImpl *node, long offset);
00248
00249 virtual ~LinearDocument();
00250
00259 bool isValid() const
00260 {
00261 return true;
00262 }
00263
00271 int count() const;
00272
00277 Iterator current();
00278
00282 const Iterator &end() const { return _end; }
00283
00287 Iterator preEnd();
00288
00292 Iterator begin();
00293
00298 const Iterator &preBegin() const { return _preBegin; }
00299
00300 protected:
00301 void initPreBeginIterator();
00302 void initEndIterator();
00303
00304 protected:
00305 RenderArena *arena;
00306
00307 DOM::NodeImpl *node;
00308 long offset;
00309
00310 Iterator _preBegin;
00311 Iterator _end;
00312
00313 KHTMLPart *m_part;
00314
00315 friend class LineIterator;
00316 friend class EditableLineIterator;
00317 friend class ErgonomicEditableLineIterator;
00318 friend class InlineBoxIterator;
00319 friend class EditableInlineBoxIterator;
00320 friend class EditableCharacterIterator;
00321 };
00322
00323
00334 class InlineBoxIterator {
00335 protected:
00336 RenderArena *arena;
00337 InlineBox *box;
00338
00339 public:
00342 InlineBoxIterator(RenderArena *arena, InlineFlowBox *flowBox, bool fromEnd = false);
00343
00347 InlineBoxIterator(LineIterator &lit, bool fromEnd = false,
00348 InlineBox *initBox = 0);
00349
00352 InlineBoxIterator() {}
00353
00358 InlineBox *operator *() const { return box; }
00359
00362 InlineBoxIterator &operator ++();
00363
00367 InlineBoxIterator &operator --();
00368 };
00369
00381 class EditableInlineBoxIterator : public InlineBoxIterator {
00382 protected:
00383 KHTMLPart *m_part;
00384 bool adjacent;
00385
00386 public:
00393 EditableInlineBoxIterator(KHTMLPart *part, RenderArena *arena,
00394 InlineFlowBox *flowBox, bool fromEnd = false)
00395 : InlineBoxIterator(arena, flowBox, fromEnd), m_part(part), adjacent(true)
00396 {
00397 if (box && !isEditable(box)) fromEnd ? --*this : ++*this;
00398 }
00399
00403 EditableInlineBoxIterator(LineIterator &lit, bool fromEnd = false,
00404 InlineBox *initBox = 0)
00405 : InlineBoxIterator(lit, fromEnd, initBox), m_part(lit.lines->m_part)
00406 {
00407 if (box && !isEditable(box))
00408 {
00409 if (fromEnd)
00410 --*this;
00411 else
00412 ++*this;
00413 }
00414 }
00415
00418 EditableInlineBoxIterator() {}
00419
00423 bool isAdjacent() const { return adjacent; }
00424
00428 EditableInlineBoxIterator &operator ++()
00429 {
00430 adjacent = true;
00431 do {
00432 InlineBoxIterator::operator ++();
00433 } while (box && !isEditable(box));
00434 return *this;
00435 }
00436
00440 EditableInlineBoxIterator &operator --()
00441 {
00442 adjacent = true;
00443 do {
00444 InlineBoxIterator::operator --();
00445 } while (box && !isEditable(box));
00446 return *this;
00447 }
00448
00449 protected:
00454 bool isEditable(InlineBox *b)
00455 {
00456
00457
00458 Q_ASSERT(b);
00459 RenderObject *r = b->object();
00460 #if DEBUG_CARETMODE > 0
00461 if (b->isInlineFlowBox()) kdDebug(6200) << "b is inline flow box" << endl;
00462 kdDebug(6200) << "isEditable r" << r << ": " << (r ? r->renderName() : QString::null) << (r && r->isText() ? " contains \"" + QString(((RenderText *)r)->str->s, QMIN(((RenderText *)r)->str->l,15)) + "\"" : QString::null) << endl;
00463 #endif
00464
00465
00466
00467 bool result = r && r->element() && !r->isTableCol()
00468 && (m_part->isCaretMode() || m_part->isEditable()
00469 || r->style()->userInput() == UI_ENABLED);
00470 if (!result) adjacent = false;
00471 #if DEBUG_CARETMODE > 0
00472 kdDebug(6200) << result << endl;
00473 #endif
00474 return result;
00475 }
00476
00477 };
00478
00495 class EditableLineIterator : public LineIterator {
00496 public:
00505 EditableLineIterator(const LineIterator &it, bool fromEnd = false)
00506 : LineIterator(it)
00507 {
00508 if (flowBox && !isEditable(*this))
00509 {
00510 if (fromEnd)
00511 operator--();
00512 else
00513 operator ++();
00514 }
00515 if (!flowBox || !cb) {
00516 #if DEBUG_CARETMODE > 0
00517 kdDebug(6200) << "EditableLineIterator: findFlowBox failed" << endl;
00518 #endif
00519 cb = 0;
00520 }
00521 }
00522
00527 EditableLineIterator() {}
00528
00533 EditableLineIterator &operator ++()
00534 {
00535
00536
00537 do {
00538 LineIterator::operator ++();
00539 } while (cb && !isEditable(*this));
00540 return *this;
00541 }
00549
00550
00555 EditableLineIterator &operator --()
00556 {
00557
00558
00559 do {
00560 LineIterator::operator --();
00561 } while (cb && !isEditable(*this));
00562 return *this;
00563 }
00571
00572
00573 #if 0 // implement when it's needed
00574
00577 EditableLineIterator operator +(int summand) const;
00581 EditableLineIterator operator -(int summand) const;
00582
00586 EditableLineIterator &operator +=(int summand);
00590 EditableLineIterator &operator -=(int summand);
00591 #endif
00592
00593 protected:
00598 bool isEditable(LineIterator &it)
00599 {
00600 #if 0 // these shortcut evaluations are all invalid
00601 if (lines->m_part->isCaretMode() || lines->m_part->isEditable()) return true;
00602
00603
00604 if (!(*it)->firstChild()) {
00605 kdDebug(6200) << "cb " << cb->renderName() << "[" << cb << "](" << (cb->element() ? cb->element()->nodeName().string() : QString::null) << ") editable? " << (cb->style()->userInput() == UI_ENABLED) << endl;
00606 return cb->style()->userInput() == UI_ENABLED;
00607 }
00608 #endif
00609
00610 EditableInlineBoxIterator fbit = it;
00611 return *fbit;
00612 }
00613
00614 };
00615
00624 class TableRowIterator {
00625 protected:
00626 TableSectionIterator sec;
00627 int index;
00628 public:
00635 TableRowIterator(RenderTable *table, bool fromEnd = false,
00636 RenderTableSection::RowStruct *row = 0);
00637
00642 TableRowIterator(RenderTableSection *section, int index)
00643 : sec(section), index(index)
00644 {}
00645
00649 TableRowIterator() {}
00650
00654 RenderTableSection::RowStruct *operator *()
00655 {
00656 if (!*sec) return 0;
00657 return &(*sec)->grid[index];
00658 }
00659
00662 TableRowIterator &operator ++();
00663
00666 TableRowIterator &operator --();
00667
00668 protected:
00669 };
00670
00686 class ErgonomicEditableLineIterator : public EditableLineIterator {
00687 protected:
00688 int xCoor;
00689 public:
00694 ErgonomicEditableLineIterator(const LineIterator &it, int x)
00695 : EditableLineIterator(it), xCoor(x) {}
00696
00700 ErgonomicEditableLineIterator() {}
00701
00706 ErgonomicEditableLineIterator &operator ++();
00707
00712 ErgonomicEditableLineIterator &operator --();
00713
00714 protected:
00722 void determineTopologicalElement(RenderTableCell *oldCell,
00723 RenderObject *newObject, bool toBegin);
00724
00730 void calcAndStoreNewLine(RenderFlow *newBlock, bool toBegin);
00731
00732 #if 0
00733
00737 static bool belongToSameTable(const RenderTableCell *t1, const RenderTableCell *t2)
00738 {
00739 return t1 && t2 && t1->table() == t2->table();
00740 }
00741
00755 static RenderTableCell *findNearestTableCellInSection(KHTMLPart *part, int x,
00756 RenderTableSection *section, bool fromEnd = false, int startIndex = -1);
00757
00768 RenderObject *findObjectBeyond(RenderTable *table, bool toBegin);
00769 #endif
00770 };
00771
00779 class EditableCharacterIterator {
00780 protected:
00781 LinearDocument *ld;
00782 EditableLineIterator _it;
00783 EditableInlineBoxIterator ebit;
00784 DOM::NodeImpl *_node;
00785 long _offset;
00786 int _char;
00787
00788 public:
00789
00795 EditableCharacterIterator() {}
00796
00801 EditableCharacterIterator(LinearDocument *ld)
00802 : ld(ld), _it(ld->current()),
00803 ebit(_it, false, _it.currentInlineBox()), _char(-1)
00804 {
00805 _node = ld->node;
00806 _offset = ld->offset;
00807
00808
00809 if (_it == ld->end()) { _node = 0; return; }
00810
00811
00812
00813
00814 EditableInlineBoxIterator copy = ebit;
00815 for (; *ebit; ++ebit) {
00816 copy = ebit;
00817 InlineBox *b = *ebit;
00818
00819 if (b == _it.currentInlineBox() || b->object() == _node->renderer()) {
00820 _offset = QMIN(kMax(_offset, b->minOffset()), b->maxOffset());
00821 break;
00822 }
00823 }
00824
00825
00826
00827
00828 if (!*ebit) {
00829
00830 static long cache_offset = -1;
00831 ebit = copy;
00832 InlineBox *b = *ebit;
00833 _node = b->object()->element();
00834 long max_ofs = b->maxOffset();
00835 _offset = cache_offset == max_ofs ? b->minOffset() : max_ofs;
00836 cache_offset = _offset;
00837 #if DEBUG_CARETMODE > 0
00838 kdDebug(6200) << "There was no node! Fixup applied!" << endl;
00839 if (cache_offset == max_ofs) kdDebug(6200) << "offset fixup applied as well" << endl;
00840 #endif
00841 }
00842
00843 initFirstChar();
00844 }
00845
00849 int chr() const { return _char; }
00850
00854 QChar operator *() const { return QChar(_char >= 0 ? _char : ' '); }
00855
00858 long offset() const { return _offset; }
00863 DOM::NodeImpl *node() const { return _node; }
00870 InlineBox *box() const { return *ebit; }
00873 EditableCharacterIterator &operator ++();
00874
00877 EditableCharacterIterator &operator --();
00878
00879 protected:
00883 void initFirstChar();
00886 void peekNext()
00887 {
00888 EditableInlineBoxIterator copy = ebit;
00889 ++copy;
00890 InlineBox *b = *copy;
00891 if (b && b->isInlineTextBox())
00892 _char = static_cast<RenderText *>(b->object())->str->s[b->minOffset()].unicode();
00893 else
00894 _char = -1;
00895 }
00898 void peekPrev()
00899 {
00900 --ebit;
00901
00902 }
00903
00904 };
00905
00906
00907 }
00908
00909
00910 #endif