[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
kocienda
kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 08:35:03 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 88ca6d57f7c4be136e9a52254040acf48a0585d7
Author: kocienda <kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Apr 19 22:54:55 2004 +0000
WebCore:
Reviewed by Hyatt
* khtml/khtml_part.cpp:
(KHTMLPart::notifySelectionChanged): Clear the value
used for maintaining x position when doing vertical arrow
navigation. WebCoreBridge restores this value when needed.
(KHTMLPart::setXPosForVerticalArrowNavigation): New accessor.
(KHTMLPart::xPosForVerticalArrowNavigation): New accessor.
* khtml/khtml_part.h:
(KHTMLPart::): Add NoXPosForVerticalArrowNavigation constant.
* khtml/khtml_selection.cpp:
(KHTMLSelection::modify): Add cases for UP and DOWN navigation
(KHTMLSelection::xPosForVerticalArrowNavigation): New helper.
* khtml/khtml_selection.h: Add UP and DOWN constants to EDirection enum.
(KHTMLSelection::):
* khtml/khtmlpart_p.h: Declare storage for m_xPosForVerticalArrowNavigation,
the value used for maintaining x position when doing vertical arrow
navigation.
* khtml/rendering/render_block.cpp:
(khtml::RenderBlock::positionForCoordinates): Improved this function to
handle deficiencies exposed when trying to implement new behavior.
* khtml/rendering/render_br.cpp:
(RenderBR::positionForCoordinates): Added implementation of this virtual function.
* khtml/rendering/render_br.h: Declare implementation for positionForCoordinates virtual function.
* khtml/rendering/render_replaced.cpp:
(RenderReplaced::positionForCoordinates): Improved this function to
handle deficiencies exposed when trying to implement new behavior.
* khtml/rendering/render_text.cpp:
(InlineTextBox::offsetForPosition): Remove left/right "bounds" check here.
(RenderText::positionForCoordinates): Improved this function to
handle deficiencies exposed when trying to implement new behavior.
* khtml/xml/dom_position.cpp:
(inlineBoxForRenderer): Moved to top of file so all code in the file can see this static function.
(renderersOnDifferentLine): Ditto.
(nextRenderedEditable): Ditto.
(previousRenderedEditable): Ditto.
(DOMPosition::previousLinePosition): New function. Implements the guts of up/down navigation.
(DOMPosition::nextLinePosition): Ditto.
* khtml/xml/dom_position.h: Added declarations for nextLinePosition and previousLinePosition.
* kwq/WebCoreBridge.h: Add WebSelectUp and WebSelectDown constants.
* kwq/WebCoreBridge.mm:
(-[WebCoreBridge alterCurrentSelection:direction:granularity:]): Handles saving and restoring the
x position used for doing vertical arrow navigation.
WebKit:
Reviewed by Hyatt
* WebView.subproj/WebView.m:
(-[WebView moveDown:]): Added implementation.
(-[WebView moveUp:]): Added implementation.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6426 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 57d106f..3731d22 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,49 @@
+2004-04-19 Ken Kocienda <kocienda at apple.com>
+
+ Reviewed by Hyatt
+
+ * khtml/khtml_part.cpp:
+ (KHTMLPart::notifySelectionChanged): Clear the value
+ used for maintaining x position when doing vertical arrow
+ navigation. WebCoreBridge restores this value when needed.
+ (KHTMLPart::setXPosForVerticalArrowNavigation): New accessor.
+ (KHTMLPart::xPosForVerticalArrowNavigation): New accessor.
+ * khtml/khtml_part.h:
+ (KHTMLPart::): Add NoXPosForVerticalArrowNavigation constant.
+ * khtml/khtml_selection.cpp:
+ (KHTMLSelection::modify): Add cases for UP and DOWN navigation
+ (KHTMLSelection::xPosForVerticalArrowNavigation): New helper.
+ * khtml/khtml_selection.h: Add UP and DOWN constants to EDirection enum.
+ (KHTMLSelection::):
+ * khtml/khtmlpart_p.h: Declare storage for m_xPosForVerticalArrowNavigation,
+ the value used for maintaining x position when doing vertical arrow
+ navigation.
+ * khtml/rendering/render_block.cpp:
+ (khtml::RenderBlock::positionForCoordinates): Improved this function to
+ handle deficiencies exposed when trying to implement new behavior.
+ * khtml/rendering/render_br.cpp:
+ (RenderBR::positionForCoordinates): Added implementation of this virtual function.
+ * khtml/rendering/render_br.h: Declare implementation for positionForCoordinates virtual function.
+ * khtml/rendering/render_replaced.cpp:
+ (RenderReplaced::positionForCoordinates): Improved this function to
+ handle deficiencies exposed when trying to implement new behavior.
+ * khtml/rendering/render_text.cpp:
+ (InlineTextBox::offsetForPosition): Remove left/right "bounds" check here.
+ (RenderText::positionForCoordinates): Improved this function to
+ handle deficiencies exposed when trying to implement new behavior.
+ * khtml/xml/dom_position.cpp:
+ (inlineBoxForRenderer): Moved to top of file so all code in the file can see this static function.
+ (renderersOnDifferentLine): Ditto.
+ (nextRenderedEditable): Ditto.
+ (previousRenderedEditable): Ditto.
+ (DOMPosition::previousLinePosition): New function. Implements the guts of up/down navigation.
+ (DOMPosition::nextLinePosition): Ditto.
+ * khtml/xml/dom_position.h: Added declarations for nextLinePosition and previousLinePosition.
+ * kwq/WebCoreBridge.h: Add WebSelectUp and WebSelectDown constants.
+ * kwq/WebCoreBridge.mm:
+ (-[WebCoreBridge alterCurrentSelection:direction:granularity:]): Handles saving and restoring the
+ x position used for doing vertical arrow navigation.
+
2004-04-16 Ken Kocienda <kocienda at apple.com>
Reviewed by Hyatt
diff --git a/WebCore/khtml/editing/SelectionController.cpp b/WebCore/khtml/editing/SelectionController.cpp
index 6107244..96d50e2 100644
--- a/WebCore/khtml/editing/SelectionController.cpp
+++ b/WebCore/khtml/editing/SelectionController.cpp
@@ -317,6 +317,18 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
break;
}
break;
+ case UP:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().previousLinePosition(xPosForVerticalArrowNavigation());
+ break;
+ case DOWN:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().nextLinePosition(xPosForVerticalArrowNavigation());
+ break;
}
if (pos.isEmpty())
@@ -335,6 +347,29 @@ void KHTMLSelection::expandToElement(ETextGranularity select)
validate(select);
}
+int KHTMLSelection::xPosForVerticalArrowNavigation() const
+{
+ int x = 0;
+
+ if (state() == NONE)
+ return x;
+
+ KHTMLPart *part = startPosition().node()->getDocument()->part();
+ if (!part)
+ return x;
+
+ if (part->xPosForVerticalArrowNavigation() == KHTMLPart::NoXPosForVerticalArrowNavigation) {
+ int y, w, h;
+ startPosition().node()->renderer()->caretPos(startPosition().offset(), true, x, y, w, h);
+ part->setXPosForVerticalArrowNavigation(x);
+ }
+ else {
+ x = part->xPosForVerticalArrowNavigation();
+ }
+
+ return x;
+}
+
void KHTMLSelection::clear()
{
setBaseNode(0);
diff --git a/WebCore/khtml/editing/SelectionController.h b/WebCore/khtml/editing/SelectionController.h
index a52f542..f96e49a 100644
--- a/WebCore/khtml/editing/SelectionController.h
+++ b/WebCore/khtml/editing/SelectionController.h
@@ -53,7 +53,7 @@ public:
enum EState { NONE, CARET, RANGE };
enum EAlter { MOVE, EXTEND };
- enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+ enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT, UP, DOWN };
enum ETextGranularity { CHARACTER, WORD, LINE };
EState state() const { return m_state; }
@@ -129,6 +129,7 @@ private:
bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
void calculateStartAndEnd(ETextGranularity select=CHARACTER);
+ int xPosForVerticalArrowNavigation() const;
DOM::NodeImpl *m_baseNode; // base node for the selection
long m_baseOffset; // offset into base node where selection is
diff --git a/WebCore/khtml/editing/selection.cpp b/WebCore/khtml/editing/selection.cpp
index 6107244..96d50e2 100644
--- a/WebCore/khtml/editing/selection.cpp
+++ b/WebCore/khtml/editing/selection.cpp
@@ -317,6 +317,18 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
break;
}
break;
+ case UP:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().previousLinePosition(xPosForVerticalArrowNavigation());
+ break;
+ case DOWN:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().nextLinePosition(xPosForVerticalArrowNavigation());
+ break;
}
if (pos.isEmpty())
@@ -335,6 +347,29 @@ void KHTMLSelection::expandToElement(ETextGranularity select)
validate(select);
}
+int KHTMLSelection::xPosForVerticalArrowNavigation() const
+{
+ int x = 0;
+
+ if (state() == NONE)
+ return x;
+
+ KHTMLPart *part = startPosition().node()->getDocument()->part();
+ if (!part)
+ return x;
+
+ if (part->xPosForVerticalArrowNavigation() == KHTMLPart::NoXPosForVerticalArrowNavigation) {
+ int y, w, h;
+ startPosition().node()->renderer()->caretPos(startPosition().offset(), true, x, y, w, h);
+ part->setXPosForVerticalArrowNavigation(x);
+ }
+ else {
+ x = part->xPosForVerticalArrowNavigation();
+ }
+
+ return x;
+}
+
void KHTMLSelection::clear()
{
setBaseNode(0);
diff --git a/WebCore/khtml/editing/selection.h b/WebCore/khtml/editing/selection.h
index a52f542..f96e49a 100644
--- a/WebCore/khtml/editing/selection.h
+++ b/WebCore/khtml/editing/selection.h
@@ -53,7 +53,7 @@ public:
enum EState { NONE, CARET, RANGE };
enum EAlter { MOVE, EXTEND };
- enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+ enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT, UP, DOWN };
enum ETextGranularity { CHARACTER, WORD, LINE };
EState state() const { return m_state; }
@@ -129,6 +129,7 @@ private:
bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
void calculateStartAndEnd(ETextGranularity select=CHARACTER);
+ int xPosForVerticalArrowNavigation() const;
DOM::NodeImpl *m_baseNode; // base node for the selection
long m_baseOffset; // offset into base node where selection is
diff --git a/WebCore/khtml/khtml_part.cpp b/WebCore/khtml/khtml_part.cpp
index cab37de..cb13fca 100644
--- a/WebCore/khtml/khtml_part.cpp
+++ b/WebCore/khtml/khtml_part.cpp
@@ -2585,10 +2585,24 @@ void KHTMLPart::notifySelectionChanged(bool endTyping)
if (endTyping)
TypingCommand::closeTyping(lastEditCommand());
-
+
+ // Always clear the x position used for vertical arrow navigation.
+ // It will be restored by the vertical arrow navigation code if necessary.
+ d->m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
+
emitSelectionChanged();
}
+void KHTMLPart::setXPosForVerticalArrowNavigation(int x)
+{
+ d->m_xPosForVerticalArrowNavigation = x;
+}
+
+int KHTMLPart::xPosForVerticalArrowNavigation() const
+{
+ return d->m_xPosForVerticalArrowNavigation;
+}
+
void KHTMLPart::timerEvent(QTimerEvent *e)
{
if (e->timerId() == d->m_caretBlinkTimer &&
diff --git a/WebCore/khtml/khtml_part.h b/WebCore/khtml/khtml_part.h
index 69c28f5..0173e6a 100644
--- a/WebCore/khtml/khtml_part.h
+++ b/WebCore/khtml/khtml_part.h
@@ -181,6 +181,7 @@ class KHTMLPart : public KParts::ReadOnlyPart
public:
enum GUIProfile { DefaultGUI, BrowserViewGUI /* ... */ };
+ enum { NoXPosForVerticalArrowNavigation = INT_MIN };
/**
* Constructs a new KHTMLPart.
@@ -604,6 +605,16 @@ public:
void paintCaret(QPainter *p, const QRect &rect) const;
/**
+ * Set info for vertical arrow navigation.
+ */
+ void setXPosForVerticalArrowNavigation(int x);
+
+ /**
+ * Get info for vertical arrow navigation.
+ */
+ int xPosForVerticalArrowNavigation() const;
+
+ /**
* Returns the text for a part of the document.
*/
QString text(const DOM::Range &) const;
diff --git a/WebCore/khtml/khtml_selection.cpp b/WebCore/khtml/khtml_selection.cpp
index 6107244..96d50e2 100644
--- a/WebCore/khtml/khtml_selection.cpp
+++ b/WebCore/khtml/khtml_selection.cpp
@@ -317,6 +317,18 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
break;
}
break;
+ case UP:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().previousLinePosition(xPosForVerticalArrowNavigation());
+ break;
+ case DOWN:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().nextLinePosition(xPosForVerticalArrowNavigation());
+ break;
}
if (pos.isEmpty())
@@ -335,6 +347,29 @@ void KHTMLSelection::expandToElement(ETextGranularity select)
validate(select);
}
+int KHTMLSelection::xPosForVerticalArrowNavigation() const
+{
+ int x = 0;
+
+ if (state() == NONE)
+ return x;
+
+ KHTMLPart *part = startPosition().node()->getDocument()->part();
+ if (!part)
+ return x;
+
+ if (part->xPosForVerticalArrowNavigation() == KHTMLPart::NoXPosForVerticalArrowNavigation) {
+ int y, w, h;
+ startPosition().node()->renderer()->caretPos(startPosition().offset(), true, x, y, w, h);
+ part->setXPosForVerticalArrowNavigation(x);
+ }
+ else {
+ x = part->xPosForVerticalArrowNavigation();
+ }
+
+ return x;
+}
+
void KHTMLSelection::clear()
{
setBaseNode(0);
diff --git a/WebCore/khtml/khtml_selection.h b/WebCore/khtml/khtml_selection.h
index a52f542..f96e49a 100644
--- a/WebCore/khtml/khtml_selection.h
+++ b/WebCore/khtml/khtml_selection.h
@@ -53,7 +53,7 @@ public:
enum EState { NONE, CARET, RANGE };
enum EAlter { MOVE, EXTEND };
- enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+ enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT, UP, DOWN };
enum ETextGranularity { CHARACTER, WORD, LINE };
EState state() const { return m_state; }
@@ -129,6 +129,7 @@ private:
bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
void calculateStartAndEnd(ETextGranularity select=CHARACTER);
+ int xPosForVerticalArrowNavigation() const;
DOM::NodeImpl *m_baseNode; // base node for the selection
long m_baseOffset; // offset into base node where selection is
diff --git a/WebCore/khtml/khtmlpart_p.h b/WebCore/khtml/khtmlpart_p.h
index 5cfbf32..8d11d37 100644
--- a/WebCore/khtml/khtmlpart_p.h
+++ b/WebCore/khtml/khtmlpart_p.h
@@ -366,6 +366,7 @@ public:
TristateFlag m_inEditMode;
khtml::EditCommand m_lastEditCommand;
+ int m_xPosForVerticalArrowNavigation;
int m_focusNodeNumber;
diff --git a/WebCore/khtml/rendering/render_block.cpp b/WebCore/khtml/rendering/render_block.cpp
index 70cb877..33dde28 100644
--- a/WebCore/khtml/rendering/render_block.cpp
+++ b/WebCore/khtml/rendering/render_block.cpp
@@ -2078,31 +2078,43 @@ DOMPosition RenderBlock::positionForCoordinates(int _x, int _y)
// look for the closest line box in the root box which is at the passed-in y coordinate
for (RootInlineBox *root = firstRootBox(); root; root = root->nextRootBox()) {
top = absy + root->topOverflow();
+ // set the bottom based on whether there is a next root box
if (root->nextRootBox())
bottom = absy + root->nextRootBox()->topOverflow();
else
bottom = absy + root->bottomOverflow();
- if (_y >= top && _y < bottom) {
- InlineBox *closestBox = root->firstChild();
- int min = INT_MAX;
- bool start = true;
- for (InlineBox *box = root->firstChild(); box; box = box->nextOnLine()) {
- int cmp;
- cmp = abs(_x - (absx + box->m_x));
- if (cmp < min) {
- closestBox = box;
- min = cmp;
- start = true;
- }
- cmp = abs(_x - (absx + box->m_x + box->m_width));
- if (cmp < min) {
- closestBox = box;
- min = cmp;
- start = false;
+ // check if this root line box is located at this y coordinate
+ if (_y >= top && _y < bottom && root->firstChild()) {
+ InlineBox *closestBox = 0;
+ bool useClosestBoxLeftEdge = true;
+
+ if (_x <= absx + root->firstChild()->m_x) {
+ // if the x coordinate is to the left of the root box's first child,
+ // make the first child closest
+ closestBox = root->firstChild();
+ }
+ else if (_x >= absx + root->lastChild()->m_x + root->lastChild()->m_width) {
+ // if the x coordinate is to the right of the root box's last child,
+ // make the last child closest
+ closestBox = root->lastChild();
+ useClosestBoxLeftEdge = false;
+ }
+ else {
+ // look for the closest child for this root;
+ // check only the right edges, since the left edge of the first
+ // box has already been checked
+ for (InlineBox *box = root->firstChild(); box; box = box->nextOnLine()) {
+ if (_x < absx + box->m_x + box->m_width) {
+ closestBox = box;
+ useClosestBoxLeftEdge = false;
+ break;
+ }
}
}
- if (closestBox)
- return positionForBox(start ? closestBox->firstLeafChild() : closestBox->lastLeafChild(), start);
+ if (closestBox) {
+ RenderObject *renderer = useClosestBoxLeftEdge ? closestBox->firstLeafChild()->object() : closestBox->lastLeafChild()->object();
+ return renderer->positionForCoordinates(_x, _y);
+ }
}
}
return DOMPosition(element(), 0);
diff --git a/WebCore/khtml/rendering/render_br.cpp b/WebCore/khtml/rendering/render_br.cpp
index 3f5704e..e77e6e5 100644
--- a/WebCore/khtml/rendering/render_br.cpp
+++ b/WebCore/khtml/rendering/render_br.cpp
@@ -20,9 +20,10 @@
*
*/
#include "render_br.h"
+#include "xml/dom_position.h"
using namespace khtml;
-
+using DOM::DOMPosition;
RenderBR::RenderBR(DOM::NodeImpl* node)
: RenderText(node, new DOM::DOMStringImpl(QChar('\n'))), m_x(0), m_y(0), m_height(0),
@@ -97,6 +98,11 @@ unsigned long RenderBR::caretMaxRenderedOffset() const
return 1;
}
+DOMPosition RenderBR::positionForCoordinates(int _x, int _y)
+{
+ return DOMPosition(element(), 0);
+}
+
void RenderBR::caretPos(int offset, bool override, int &_x, int &_y, int &_w, int &_h)
{
// EDIT FIXME: This does not work yet. Some other changes are need before
diff --git a/WebCore/khtml/rendering/render_br.h b/WebCore/khtml/rendering/render_br.h
index 9e11c12..70dbff0 100644
--- a/WebCore/khtml/rendering/render_br.h
+++ b/WebCore/khtml/rendering/render_br.h
@@ -24,6 +24,10 @@
#include "render_text.h"
+namespace DOM {
+ class DOMPosition;
+};
+
/*
* The whole class here is a hack to get <br> working, as long as we don't have support for
* CSS2 :before and :after pseudo elements
@@ -63,6 +67,7 @@ public:
virtual long caretMaxOffset() const;
virtual unsigned long caretMaxRenderedOffset() const;
+ virtual DOM::DOMPosition positionForCoordinates(int _x, int _y);
virtual void caretPos(int offset, bool override, int &_x, int &_y, int &_w, int &_h);
private:
diff --git a/WebCore/khtml/rendering/render_replaced.cpp b/WebCore/khtml/rendering/render_replaced.cpp
index 0e0b2a3..6ec4711 100644
--- a/WebCore/khtml/rendering/render_replaced.cpp
+++ b/WebCore/khtml/rendering/render_replaced.cpp
@@ -25,6 +25,7 @@
#include "render_arena.h"
#include "render_canvas.h"
+#include "render_line.h"
#include <assert.h>
#include <qwidget.h>
@@ -129,18 +130,30 @@ unsigned long RenderReplaced::caretMaxRenderedOffset() const
DOMPosition RenderReplaced::positionForCoordinates(int _x, int _y)
{
+ InlineBox *box = inlineBoxWrapper();
+ if (!box)
+ return DOMPosition(element(), 0);
+
+ RootInlineBox *root = box->root();
+
int absx, absy;
absolutePosition(absx, absy);
+
+ int top = absy + root->topOverflow();
+ int bottom = absy + root->bottomOverflow();
+
+ if (_y < top)
+ return DOMPosition(element(), caretMinOffset()); // coordinates are above
- bool pointIsInside = (_x >= absx && _x < absx + width() &&
- _y >= absy && _y < absx + height());
+ if (_y >= bottom)
+ return DOMPosition(element(), caretMaxOffset()); // coordinates are below
- if (pointIsInside && element()) {
+ if (element()) {
if (_x <= absx + (width() / 2))
return DOMPosition(element(), 0);
return DOMPosition(element(), 1);
}
-
+
return RenderBox::positionForCoordinates(_x, _y);
}
diff --git a/WebCore/khtml/rendering/render_text.cpp b/WebCore/khtml/rendering/render_text.cpp
index 4f03423..7db9f66 100644
--- a/WebCore/khtml/rendering/render_text.cpp
+++ b/WebCore/khtml/rendering/render_text.cpp
@@ -205,14 +205,6 @@ unsigned long InlineTextBox::caretMaxRenderedOffset() const
int InlineTextBox::offsetForPosition(int _x, int _tx, const Font *f, const RenderText *text)
{
- if (_x < _tx + m_x)
- // we're to the left
- return -1;
-
- if (_x >= _tx + m_x + m_width)
- // we're to the right
- return -1;
-
#if APPLE_CHANGES
return f->checkSelectionPoint(text->str->s, text->str->l, m_start, m_len, m_toAdd, _x - (_tx + m_x), m_reversed);
#else
@@ -455,21 +447,37 @@ DOMPosition RenderText::positionForCoordinates(int _x, int _y)
int absx, absy;
absolutePosition(absx, absy);
- int top = absy + firstTextBox()->root()->topOverflow();
- int bottom = absy + lastTextBox()->root()->bottomOverflow();
+ if (firstTextBox() && _y < absy + firstTextBox()->root()->bottomOverflow() && _x < absx + firstTextBox()->m_x) {
+ // at the y coordinate of the first line or above
+ // and the x coordinate is to the left than the first text box left edge
+ return DOMPosition(element(), lastTextBox()->m_start);
+ }
+
+ if (lastTextBox() && _y >= absy + lastTextBox()->root()->topOverflow() && _x >= absx + lastTextBox()->m_x + lastTextBox()->m_width) {
+ // at the y coordinate of the last line or below
+ // and the x coordinate is to the right than the last text box right edge
+ return DOMPosition(element(), lastTextBox()->m_start + lastTextBox()->m_len);
+ }
- if (_y < top)
- return DOMPosition(element(), caretMinOffset()); // coordinates are above
-
- if (_y >= bottom)
- return DOMPosition(element(), caretMaxOffset()); // coordinates are below
-
for (InlineTextBox *box = firstTextBox(); box; box = box->nextTextBox()) {
if (_y >= absy + box->root()->topOverflow() && _y < absy + box->root()->bottomOverflow()) {
- const Font *f = htmlFont(box == firstTextBox());
- int offset = box->offsetForPosition(_x, absx, f, this);
- if (offset != -1)
- return DOMPosition(element(), offset + box->m_start);
+ if (_x < absx + box->m_x + box->m_width) {
+ // and the x coordinate is to the left of the right edge of this box
+ // check to see if position goes in this box
+ const Font *f = htmlFont(box == firstTextBox());
+ int offset = box->offsetForPosition(_x, absx, f, this);
+ if (offset != -1) {
+ return DOMPosition(element(), offset + box->m_start);
+ }
+ }
+ else if (!box->prevOnLine() && _x < absx + box->m_x)
+ // box is first on line
+ // and the x coordinate is to the left than the first text box left edge
+ return DOMPosition(element(), box->m_start);
+ else if (!box->nextOnLine() && _x >= absx + box->m_x + box->m_width)
+ // box is last on line
+ // and the x coordinate is to the right than the last text box right edge
+ return DOMPosition(element(), box->m_start + box->m_len);
}
}
diff --git a/WebCore/khtml/xml/dom_position.cpp b/WebCore/khtml/xml/dom_position.cpp
index 553f37c..f5aef10 100644
--- a/WebCore/khtml/xml/dom_position.cpp
+++ b/WebCore/khtml/xml/dom_position.cpp
@@ -26,6 +26,7 @@
#include "dom_position.h"
#include "htmltags.h"
+#include "rendering/render_block.h"
#include "rendering/render_line.h"
#include "rendering/render_object.h"
#include "rendering/render_style.h"
@@ -46,6 +47,7 @@ using khtml::InlineFlowBox;
using khtml::InlineTextBox;
using khtml::RenderObject;
using khtml::RenderText;
+using khtml::RootInlineBox;
#if !APPLE_CHANGES
#define ASSERT(assertion) ((void)0)
@@ -55,6 +57,70 @@ using khtml::RenderText;
#define ERROR(formatAndArgs...) ((void)0)
#endif
+static InlineBox *inlineBoxForRenderer(RenderObject *renderer, long offset)
+{
+ if (!renderer)
+ return 0;
+
+ if (renderer->isBR() && static_cast<RenderText *>(renderer)->firstTextBox())
+ return static_cast<RenderText *>(renderer)->firstTextBox();
+
+ if (renderer->isText()) {
+ RenderText *textRenderer = static_cast<khtml::RenderText *>(renderer);
+ if (textRenderer->isBR() && textRenderer->firstTextBox())
+ return textRenderer->firstTextBox();
+
+ for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+ if (offset >= box->m_start && offset <= box->m_start + box->m_len) {
+ return box;
+ }
+ else if (offset < box->m_start) {
+ // The offset we're looking for is before this node
+ // this means the offset must be in content that is
+ // not rendered.
+ return box->prevTextBox() ? box->prevTextBox() : textRenderer->firstTextBox();
+ }
+ }
+ }
+ else {
+ return renderer->inlineBoxWrapper();
+ }
+
+ return 0;
+}
+
+static bool renderersOnDifferentLine(RenderObject *r1, long o1, RenderObject *r2, long o2)
+{
+ InlineBox *b1 = inlineBoxForRenderer(r1, o1);
+ InlineBox *b2 = inlineBoxForRenderer(r2, o2);
+ return (b1 && b2 && b1->root() != b2->root());
+}
+
+static NodeImpl *nextRenderedEditable(NodeImpl *node)
+{
+ while (1) {
+ node = node->nextEditable();
+ if (!node)
+ return 0;
+ if (inlineBoxForRenderer(node->renderer(), 0))
+ return node;
+ }
+ return 0;
+}
+
+static NodeImpl *previousRenderedEditable(NodeImpl *node)
+{
+ while (1) {
+ node = node->previousEditable();
+ if (!node)
+ return 0;
+ if (inlineBoxForRenderer(node->renderer(), 0))
+ return node;
+ }
+ return 0;
+}
+
+
DOMPosition::DOMPosition(NodeImpl *node, long offset)
: m_node(0), m_offset(offset)
{
@@ -232,6 +298,115 @@ DOMPosition DOMPosition::nextCharacterPosition() const
return *this;
}
+DOMPosition DOMPosition::previousLinePosition(int x) const
+{
+ if (!node())
+ return DOMPosition();
+
+ if (!node()->renderer())
+ return *this;
+
+ InlineBox *box = inlineBoxForRenderer(node()->renderer(), offset());
+ if (!box)
+ return *this;
+
+ NodeImpl *previousLineNode = 0;
+ RootInlineBox *root = box->root()->prevRootBox();
+ if (root) {
+ previousLineNode = node();
+ }
+ else {
+ // This containing editable block does not have a previous line.
+ // Need to move back to previous containing editable block in this root editable
+ // block and find the last root line box in that block.
+ NodeImpl *startBlock = node()->containingEditableBlock();
+ NodeImpl *n = node()->previousEditable();
+ while (n && startBlock == n->containingEditableBlock())
+ n = n->previousEditable();
+ if (n) {
+ while (n && !DOMPosition(n, n->caretMaxOffset()).inRenderedContent())
+ n = n->previousEditable();
+ if (n && n->inSameRootEditableBlock(node())) {
+ box = inlineBoxForRenderer(n->renderer(), n->caretMaxOffset());
+ ASSERT(box);
+ // previous root line box found
+ root = box->root();
+ previousLineNode = n;
+ }
+ }
+ }
+
+ if (!root)
+ return *this;
+ ASSERT(previousLineNode);
+
+ int absx, absy;
+ previousLineNode->renderer()->containingBlock()->absolutePosition(absx, absy);
+ int y = absy + root->topOverflow() + ((root->bottomOverflow() - root->topOverflow()) / 2);
+
+ RenderObject::NodeInfo nodeInfo(true, true);
+ previousLineNode->getDocument()->renderer()->layer()->nodeAtPoint(nodeInfo, x, y);
+
+ if (!nodeInfo.innerNode() || !nodeInfo.innerNode()->renderer())
+ return *this;
+
+ return nodeInfo.innerNode()->renderer()->positionForCoordinates(x, y);
+}
+
+DOMPosition DOMPosition::nextLinePosition(int x) const
+{
+ if (!node())
+ return DOMPosition();
+
+ if (!node()->renderer())
+ return *this;
+
+ InlineBox *box = inlineBoxForRenderer(node()->renderer(), offset());
+ if (!box)
+ return *this;
+
+ NodeImpl *nextLineNode = 0;
+ RootInlineBox *root = box->root()->nextRootBox();
+ if (root) {
+ nextLineNode = node();
+ }
+ else {
+ // This containing editable block does not have a next line.
+ // Need to move forward to next containing editable block in this root editable
+ // block and find the first root line box in that block.
+ NodeImpl *startBlock = node()->containingEditableBlock();
+ NodeImpl *n = node()->nextEditable();
+ while (n && startBlock == n->containingEditableBlock())
+ n = n->nextEditable();
+ if (n) {
+ while (n && !DOMPosition(n, n->caretMinOffset()).inRenderedContent())
+ n = n->nextEditable();
+ if (n && n->inSameRootEditableBlock(node())) {
+ box = inlineBoxForRenderer(n->renderer(), n->caretMinOffset());
+ ASSERT(box);
+ // previous root line box found
+ root = box->root();
+ nextLineNode = n;
+ }
+ }
+ }
+
+ if (!root)
+ return *this;
+ ASSERT(nextLineNode);
+
+ int absx, absy;
+ nextLineNode->renderer()->containingBlock()->absolutePosition(absx, absy);
+ int y = absy + root->topOverflow() + ((root->bottomOverflow() - root->topOverflow()) / 2);
+
+ RenderObject::NodeInfo nodeInfo(true, true);
+ nextLineNode->getDocument()->renderer()->layer()->nodeAtPoint(nodeInfo, x, y);
+ if (!nodeInfo.innerNode() || !nodeInfo.innerNode()->renderer())
+ return *this;
+
+ return nodeInfo.innerNode()->renderer()->positionForCoordinates(x, y);
+}
+
DOMPosition DOMPosition::equivalentUpstreamPosition() const
{
if (!node())
@@ -377,74 +552,6 @@ bool DOMPosition::inRenderedContent() const
return false;
}
-
-static InlineBox *inlineBoxForRenderer(RenderObject *renderer, long offset)
-{
- if (!renderer)
- return 0;
-
- if (renderer->isBR() && static_cast<RenderText *>(renderer)->firstTextBox())
- return static_cast<RenderText *>(renderer)->firstTextBox();
-
- if (renderer->isText()) {
- RenderText *textRenderer = static_cast<khtml::RenderText *>(renderer);
- if (textRenderer->isBR() && textRenderer->firstTextBox())
- return textRenderer->firstTextBox();
-
- for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- if (offset >= box->m_start && offset <= box->m_start + box->m_len) {
- return box;
- }
- else if (offset < box->m_start) {
- // The offset we're looking for is before this node
- // this means the offset must be in content that is
- // not rendered.
- return box->prevTextBox() ? box->prevTextBox() : textRenderer->firstTextBox();
- }
- }
- }
- else {
- return renderer->inlineBoxWrapper();
- }
-
- return 0;
-}
-
-static bool renderersOnDifferentLine(RenderObject *r1, long o1, RenderObject *r2, long o2)
-{
- InlineBox *b1 = inlineBoxForRenderer(r1, o1);
- InlineBox *b2 = inlineBoxForRenderer(r2, o2);
-
- if (b1 && b2 && b1->root() != b2->root())
- return true;
-
- return false;
-}
-
-static NodeImpl *nextRenderedEditable(NodeImpl *node)
-{
- while (1) {
- node = node->nextEditable();
- if (!node)
- return 0;
- if (inlineBoxForRenderer(node->renderer(), 0))
- return node;
- }
- return 0;
-}
-
-static NodeImpl *previousRenderedEditable(NodeImpl *node)
-{
- while (1) {
- node = node->previousEditable();
- if (!node)
- return 0;
- if (inlineBoxForRenderer(node->renderer(), 0))
- return node;
- }
- return 0;
-}
-
bool DOMPosition::inRenderedText() const
{
if (!node()->isTextNode())
diff --git a/WebCore/khtml/xml/dom_position.h b/WebCore/khtml/xml/dom_position.h
index ecf4980..b94c867 100644
--- a/WebCore/khtml/xml/dom_position.h
+++ b/WebCore/khtml/xml/dom_position.h
@@ -51,6 +51,8 @@ public:
DOMPosition nextRenderedEditablePosition() const;
DOMPosition previousCharacterPosition() const;
DOMPosition nextCharacterPosition() const;
+ DOMPosition previousLinePosition(int x) const;
+ DOMPosition nextLinePosition(int x) const;
DOMPosition equivalentUpstreamPosition() const;
DOMPosition equivalentDownstreamPosition() const;
bool atStartOfContainingEditableBlock() const;
diff --git a/WebCore/khtml/xml/dom_selection.cpp b/WebCore/khtml/xml/dom_selection.cpp
index 6107244..96d50e2 100644
--- a/WebCore/khtml/xml/dom_selection.cpp
+++ b/WebCore/khtml/xml/dom_selection.cpp
@@ -317,6 +317,18 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
break;
}
break;
+ case UP:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().previousLinePosition(xPosForVerticalArrowNavigation());
+ break;
+ case DOWN:
+ if (alter == EXTEND)
+ ERROR("unimplemented");
+ else
+ pos = startPosition().nextLinePosition(xPosForVerticalArrowNavigation());
+ break;
}
if (pos.isEmpty())
@@ -335,6 +347,29 @@ void KHTMLSelection::expandToElement(ETextGranularity select)
validate(select);
}
+int KHTMLSelection::xPosForVerticalArrowNavigation() const
+{
+ int x = 0;
+
+ if (state() == NONE)
+ return x;
+
+ KHTMLPart *part = startPosition().node()->getDocument()->part();
+ if (!part)
+ return x;
+
+ if (part->xPosForVerticalArrowNavigation() == KHTMLPart::NoXPosForVerticalArrowNavigation) {
+ int y, w, h;
+ startPosition().node()->renderer()->caretPos(startPosition().offset(), true, x, y, w, h);
+ part->setXPosForVerticalArrowNavigation(x);
+ }
+ else {
+ x = part->xPosForVerticalArrowNavigation();
+ }
+
+ return x;
+}
+
void KHTMLSelection::clear()
{
setBaseNode(0);
diff --git a/WebCore/khtml/xml/dom_selection.h b/WebCore/khtml/xml/dom_selection.h
index a52f542..f96e49a 100644
--- a/WebCore/khtml/xml/dom_selection.h
+++ b/WebCore/khtml/xml/dom_selection.h
@@ -53,7 +53,7 @@ public:
enum EState { NONE, CARET, RANGE };
enum EAlter { MOVE, EXTEND };
- enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+ enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT, UP, DOWN };
enum ETextGranularity { CHARACTER, WORD, LINE };
EState state() const { return m_state; }
@@ -129,6 +129,7 @@ private:
bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
void calculateStartAndEnd(ETextGranularity select=CHARACTER);
+ int xPosForVerticalArrowNavigation() const;
DOM::NodeImpl *m_baseNode; // base node for the selection
long m_baseOffset; // offset into base node where selection is
diff --git a/WebCore/kwq/WebCoreBridge.h b/WebCore/kwq/WebCoreBridge.h
index 970cc66..13a69bc 100644
--- a/WebCore/kwq/WebCoreBridge.h
+++ b/WebCore/kwq/WebCoreBridge.h
@@ -95,7 +95,9 @@ typedef enum {
WebSelectForward,
WebSelectBackward,
WebSelectRight,
- WebSelectLeft
+ WebSelectLeft,
+ WebSelectUp,
+ WebSelectDown,
} WebSelectionDirection;
typedef enum {
diff --git a/WebCore/kwq/WebCoreBridge.mm b/WebCore/kwq/WebCoreBridge.mm
index e3bbaa2..1317fb0 100644
--- a/WebCore/kwq/WebCoreBridge.mm
+++ b/WebCore/kwq/WebCoreBridge.mm
@@ -1339,7 +1339,18 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
selection.modify(static_cast<KHTMLSelection::EAlter>(alteration),
static_cast<KHTMLSelection::EDirection>(direction),
static_cast<KHTMLSelection::ETextGranularity>(granularity));
+
+ // save vertical navigation x position if necessary
+ int xPos = _part->xPosForVerticalArrowNavigation();
+ if (direction != WebSelectUp && direction != WebSelectDown)
+ xPos = KHTMLPart::NoXPosForVerticalArrowNavigation;
+
+ // setting the selection always clears saved vertical navigation x position
_part->setSelection(selection);
+
+ // restore vertical navigation x position if necessary
+ if (xPos != KHTMLPart::NoXPosForVerticalArrowNavigation)
+ _part->setXPosForVerticalArrowNavigation(xPos);
}
- (void)setSelectedDOMRange:(DOMRange *)range
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 7b05940..f5039a2 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,11 @@
+2004-04-19 Ken Kocienda <kocienda at apple.com>
+
+ Reviewed by Hyatt
+
+ * WebView.subproj/WebView.m:
+ (-[WebView moveDown:]): Added implementation.
+ (-[WebView moveUp:]): Added implementation.
+
2004-04-19 Chris Blumenberg <cblu at apple.com>
Added support for pasting frames via WebArchives.
diff --git a/WebKit/WebView.subproj/WebView.m b/WebKit/WebView.subproj/WebView.m
index d5f1b81..1722273 100644
--- a/WebKit/WebView.subproj/WebView.m
+++ b/WebKit/WebView.subproj/WebView.m
@@ -2264,7 +2264,7 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
- (void)moveDown:(id)sender
{
if ([self _currentSelectionIsEditable]) {
- ERROR("unimplemented");
+ [self _alterCurrentSelection:WebSelectByMoving direction:WebSelectDown granularity:WebSelectByCharacter];
return;
}
[[self nextResponder] tryToPerform:@selector(moveDown:) with:sender];
@@ -2273,7 +2273,7 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
- (void)moveDownAndModifySelection:(id)sender
{
if ([self _currentSelectionIsEditable]) {
- ERROR("unimplemented");
+ [self _alterCurrentSelection:WebSelectByExtending direction:WebSelectDown granularity:WebSelectByCharacter];
return;
}
[[self nextResponder] tryToPerform:@selector(moveDownAndModifySelection:) with:sender];
@@ -2390,7 +2390,7 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
- (void)moveUp:(id)sender
{
if ([self _currentSelectionIsEditable]) {
- ERROR("unimplemented");
+ [self _alterCurrentSelection:WebSelectByMoving direction:WebSelectUp granularity:WebSelectByCharacter];
return;
}
[[self nextResponder] tryToPerform:@selector(moveUp:) with:sender];
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list