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)) fromEnd ? --*this : ++*this;
00408 }
00409
00412 EditableInlineBoxIterator() {}
00413
00417 bool isAdjacent() const { return adjacent; }
00418
00422 EditableInlineBoxIterator &operator ++()
00423 {
00424 adjacent = true;
00425 do {
00426 InlineBoxIterator::operator ++();
00427 } while (box && !isEditable(box));
00428 return *this;
00429 }
00430
00434 EditableInlineBoxIterator &operator --()
00435 {
00436 adjacent = true;
00437 do {
00438 InlineBoxIterator::operator --();
00439 } while (box && !isEditable(box));
00440 return *this;
00441 }
00442
00443 protected:
00448 bool isEditable(InlineBox *b)
00449 {
00450
00451
00452 Q_ASSERT(b);
00453 RenderObject *r = b->object();
00454 #if DEBUG_CARETMODE > 0
00455 if (b->isInlineFlowBox()) kdDebug(6200) << "b is inline flow box" << endl;
00456 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;
00457 #endif
00458
00459
00460
00461 bool result = r && r->element() && !r->isTableCol()
00462 && (m_part->isCaretMode() || m_part->isEditable()
00463 || r->style()->userInput() == UI_ENABLED);
00464 if (!result) adjacent = false;
00465 #if DEBUG_CARETMODE > 0
00466 kdDebug(6200) << result << endl;
00467 #endif
00468 return result;
00469 }
00470
00471 };
00472
00489 class EditableLineIterator : public LineIterator {
00490 public:
00499 EditableLineIterator(const LineIterator &it, bool fromEnd = false)
00500 : LineIterator(it)
00501 {
00502 if (flowBox && !isEditable(*this)) fromEnd ? operator--() : operator ++();
00503 if (!flowBox || !cb) {
00504 #if DEBUG_CARETMODE > 0
00505 kdDebug(6200) << "EditableLineIterator: findFlowBox failed" << endl;
00506 #endif
00507 cb = 0;
00508 }
00509 }
00510
00515 EditableLineIterator() {}
00516
00521 EditableLineIterator &operator ++()
00522 {
00523
00524
00525 do {
00526 LineIterator::operator ++();
00527 } while (cb && !isEditable(*this));
00528 return *this;
00529 }
00537
00538
00543 EditableLineIterator &operator --()
00544 {
00545
00546
00547 do {
00548 LineIterator::operator --();
00549 } while (cb && !isEditable(*this));
00550 return *this;
00551 }
00559
00560
00561 #if 0 // implement when it's needed
00562
00565 EditableLineIterator operator +(int summand) const;
00569 EditableLineIterator operator -(int summand) const;
00570
00574 EditableLineIterator &operator +=(int summand);
00578 EditableLineIterator &operator -=(int summand);
00579 #endif
00580
00581 protected:
00586 bool isEditable(LineIterator &it)
00587 {
00588 #if 0 // these shortcut evaluations are all invalid
00589 if (lines->m_part->isCaretMode() || lines->m_part->isEditable()) return true;
00590
00591
00592 if (!(*it)->firstChild()) {
00593 kdDebug(6200) << "cb " << cb->renderName() << "[" << cb << "](" << (cb->element() ? cb->element()->nodeName().string() : QString::null) << ") editable? " << (cb->style()->userInput() == UI_ENABLED) << endl;
00594 return cb->style()->userInput() == UI_ENABLED;
00595 }
00596 #endif
00597
00598 EditableInlineBoxIterator fbit = it;
00599 return *fbit;
00600 }
00601
00602 };
00603
00612 class TableRowIterator {
00613 protected:
00614 TableSectionIterator sec;
00615 int index;
00616 public:
00623 TableRowIterator(RenderTable *table, bool fromEnd = false,
00624 RenderTableSection::RowStruct *row = 0);
00625
00630 TableRowIterator(RenderTableSection *section, int index)
00631 : sec(section), index(index)
00632 {}
00633
00637 TableRowIterator() {}
00638
00642 RenderTableSection::RowStruct *operator *()
00643 {
00644 if (!*sec) return 0;
00645 return &(*sec)->grid[index];
00646 }
00647
00650 TableRowIterator &operator ++();
00651
00654 TableRowIterator &operator --();
00655
00656 protected:
00657 };
00658
00674 class ErgonomicEditableLineIterator : public EditableLineIterator {
00675 protected:
00676 int xCoor;
00677 public:
00682 ErgonomicEditableLineIterator(const LineIterator &it, int x)
00683 : EditableLineIterator(it), xCoor(x) {}
00684
00688 ErgonomicEditableLineIterator() {}
00689
00694 ErgonomicEditableLineIterator &operator ++();
00695
00700 ErgonomicEditableLineIterator &operator --();
00701
00702 protected:
00710 void determineTopologicalElement(RenderTableCell *oldCell,
00711 RenderObject *newObject, bool toBegin);
00712
00718 void calcAndStoreNewLine(RenderFlow *newBlock, bool toBegin);
00719
00720 #if 0
00721
00725 static bool belongToSameTable(const RenderTableCell *t1, const RenderTableCell *t2)
00726 {
00727 return t1 && t2 && t1->table() == t2->table();
00728 }
00729
00743 static RenderTableCell *findNearestTableCellInSection(KHTMLPart *part, int x,
00744 RenderTableSection *section, bool fromEnd = false, int startIndex = -1);
00745
00756 RenderObject *findObjectBeyond(RenderTable *table, bool toBegin);
00757 #endif
00758 };
00759
00767 class EditableCharacterIterator {
00768 protected:
00769 LinearDocument *ld;
00770 EditableLineIterator _it;
00771 EditableInlineBoxIterator ebit;
00772 DOM::NodeImpl *_node;
00773 long _offset;
00774 int _char;
00775
00776 public:
00777
00783 EditableCharacterIterator() {}
00784
00789 EditableCharacterIterator(LinearDocument *ld)
00790 : ld(ld), _it(ld->current()),
00791 ebit(_it, false, _it.currentInlineBox()), _char(-1)
00792 {
00793 _node = ld->node;
00794 _offset = ld->offset;
00795
00796
00797 if (_it == ld->end()) { _node = 0; return; }
00798
00799
00800
00801
00802 EditableInlineBoxIterator copy = ebit;
00803 for (; *ebit; ++ebit) {
00804 copy = ebit;
00805 InlineBox *b = *ebit;
00806
00807 if (b == _it.currentInlineBox() || b->object() == _node->renderer()) {
00808 _offset = QMIN(kMax(_offset, b->minOffset()), b->maxOffset());
00809 break;
00810 }
00811 }
00812
00813
00814
00815
00816 if (!*ebit) {
00817
00818 static long cache_offset = -1;
00819 ebit = copy;
00820 InlineBox *b = *ebit;
00821 _node = b->object()->element();
00822 long max_ofs = b->maxOffset();
00823 _offset = cache_offset == max_ofs ? b->minOffset() : max_ofs;
00824 cache_offset = _offset;
00825 #if DEBUG_CARETMODE > 0
00826 kdDebug(6200) << "There was no node! Fixup applied!" << endl;
00827 if (cache_offset == max_ofs) kdDebug(6200) << "offset fixup applied as well" << endl;
00828 #endif
00829 }
00830
00831 initFirstChar();
00832 }
00833
00837 int chr() const { return _char; }
00838
00842 QChar operator *() const { return QChar(_char >= 0 ? _char : ' '); }
00843
00846 long offset() const { return _offset; }
00851 DOM::NodeImpl *node() const { return _node; }
00858 InlineBox *box() const { return *ebit; }
00861 EditableCharacterIterator &operator ++();
00862
00865 EditableCharacterIterator &operator --();
00866
00867 protected:
00871 void initFirstChar();
00874 void peekNext()
00875 {
00876 EditableInlineBoxIterator copy = ebit;
00877 ++copy;
00878 InlineBox *b = *copy;
00879 if (b && b->isInlineTextBox())
00880 _char = static_cast<RenderText *>(b->object())->str->s[b->minOffset()].unicode();
00881 else
00882 _char = -1;
00883 }
00886 void peekPrev()
00887 {
00888 --ebit;
00889
00890 }
00891
00892 };
00893
00894
00895 }
00896
00897
00898 #endif