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