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 &
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
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