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