khtml Library API Documentation

khtml_caret_p.h

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., 59 Temple Place - Suite 330, 00018 * Boston, MA 02111-1307, USA. 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; // caret blink frequency timer id 00063 int x, y; // caret position in viewport coordinates 00064 // (y specifies the top, not the baseline) 00065 int width; // width of caret in pixels 00066 int height; // height of caret in pixels 00067 bool visible; // true if currently visible. 00068 bool displayed; // true if caret is to be displayed at all. 00069 bool caretMoved; // set to true once caret has been moved in page 00070 // how to display the caret when view is not focused 00071 KHTMLPart::CaretDisplayPolicy displayNonFocused; 00072 00080 int origX; 00081 00082 bool keyReleasePending; // true if keypress under caret mode awaits 00083 // corresponding release event 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; // true if typed characters should override 00096 // the existing ones. 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; // associated inline box if available. 00143 short _w; // width of box in pixels 00144 int _h; // height of box in pixels 00145 int _x; // x coordinate relative to containing block 00146 int _y; // y coordinate relative to containing block 00147 RenderBox *cb; // containing block 00148 bool _outside:1; // true when representing the outside of the element 00149 bool outside_end:1; // at ending outside of element rather than at beginning 00150 // 29 bits unused 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; // associated caret box line 00239 int index; // current index 00240 00241 public: 00242 // Let standard constructor/copy constructor/destructor/assignment operator 00243 // be defined by the compiler. They do exactly what we want. 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 // base flow box which caret boxes have been constructed for 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) /*KDE_NO_EXPORT*/; 00386 00395 static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter, 00396 RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/; 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; // if box is 0, seek for equal render objects instead 00417 CaretBoxIterator &it; 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 &) /*KDE_NO_EXPORT*/; 00458 00465 void addCreatedInlineBoxEdge(InlineBox *box, const QFontMetrics &fm, 00466 bool left, bool rtl) /*KDE_NO_EXPORT*/; 00473 void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const QFontMetrics &fm, 00474 bool left, bool rtl) /*KDE_NO_EXPORT*/; 00479 void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const QFontMetrics &fm) /*KDE_NO_EXPORT*/; 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; // associated document 00501 CaretBoxLine *cbl; // current caret box line 00502 00503 static CaretBoxIterator currentBox; // current inline box 00504 static long currentOffset; 00505 00506 // Note: cbl == 0 indicates a position beyond the beginning or the 00507 // end of a document. 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 &currentCaretBox() { 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 // FIXME: not yet impl'd 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; // mass deleter for caret box lines 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; // caret advance policy 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; // current section 00886 int index; // index of row within section 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; // x-coordinate to determine cell position 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; // offset within current caret box. 01005 int _char; 01006 bool _end:1; // true when end of document has been reached 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 // ### temporary fix for illegal nodes 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 // bool boxIsOutside() const { return _it.isOutside(); } 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 }/*namespace khtml*/ 01106 01107 01108 #endif
KDE Logo
This file is part of the documentation for khtml Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:44:53 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003