Reviewed by Darin
Use the new CSS properties I added with my previous check-in. Also makes
some changes to caret positioning and drawing to make the proper editing
end-of-line behavior work correctly.
* khtml/editing/selection.cpp:
(khtml::Selection::layout): Caret drawing now takes affinity into account
when deciding where to paint the caret (finally!).
* khtml/editing/visible_position.cpp:
(khtml::VisiblePosition::previousVisiblePosition): Move off Position::rendersInDifferentPosition
to determine the result. Use a simpler test involving comparisons between
downstream positions while iterating. This is cheaper to do and easier to understand.
(khtml::VisiblePosition::nextVisiblePosition): Ditto.
* khtml/rendering/bidi.cpp:
(khtml::BidiIterator::current): Do not return non-breaking spaces for empty
text renderers and for non-text renderers. Return a null Qchar instead. Returning
non-breaking spaces was causing errors when the new -khtml-nbsp-mode was set to "space".
(khtml::RenderBlock::computeHorizontalPositionsForLine): Shrink line boxes that
contain with more spaces than can fit on the end of a line.
(khtml::RenderBlock::skipWhitespace): Factor this out from findNextLineBreak.
(khtml::RenderBlock::findNextLineBreak): Use new skipWhitespace function. Add
in code to check and use new CSS properties.
* khtml/rendering/break_lines.cpp:
(khtml::isBreakable): Consider a non-breaking space a breakable character based
on setting of new -khtml-nbsp-mode property.
* khtml/rendering/break_lines.h: Ditto.
* khtml/rendering/render_block.h: Declare skipWhitespace function.
* khtml/rendering/render_text.cpp:
(RenderText::caretRect): Do not draw the caret beyond the right edge of the
window when in white-space normal mode.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@7764 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/khtml/rendering/bidi.cpp b/WebCore/khtml/rendering/bidi.cpp
index 3cdaa54..10e9893 100644
--- a/WebCore/khtml/rendering/bidi.cpp
+++ b/WebCore/khtml/rendering/bidi.cpp
@@ -340,14 +340,14 @@
const QChar &BidiIterator::current() const
{
- static QChar nonBreakingSpace(0xA0);
+ static QChar nullCharacter;
if (!obj || !obj->isText())
- return nonBreakingSpace;
+ return nullCharacter;
RenderText* text = static_cast<RenderText*>(obj);
if (!text->text())
- return nonBreakingSpace;
+ return nullCharacter;
return text->text()[pos];
}
@@ -717,14 +717,24 @@
void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiState &bidi)
{
// First determine our total width.
+ int availableWidth = lineWidth(m_height);
int totWidth = lineBox->getFlowSpacingWidth();
BidiRun* r = 0;
for (r = sFirstBidiRun; r; r = r->nextRun) {
if (!r->box || r->obj->isPositioned())
continue; // Positioned objects are only participating to figure out their
// correct static x position. They have no effect on the width.
- if (r->obj->isText())
- r->box->setWidth(static_cast<RenderText *>(r->obj)->width(r->start, r->stop-r->start, m_firstLine));
+ if (r->obj->isText()) {
+ int textWidth = static_cast<RenderText *>(r->obj)->width(r->start, r->stop-r->start, m_firstLine);
+ if (!r->compact) {
+ RenderStyle *style = r->obj->style();
+ if (style->whiteSpace() == NORMAL && style->khtmlLineBreak() == AFTER_WHITE_SPACE) {
+ // shrink the box as needed to keep the line from overflowing the available width
+ textWidth = kMin(textWidth, availableWidth - totWidth + style->borderLeftWidth());
+ }
+ r->box->setWidth(textWidth);
+ }
+ }
else if (!r->obj->isInlineFlow()) {
r->obj->calcWidth();
r->box->setWidth(r->obj->width());
@@ -742,7 +752,6 @@
// objects horizontally. The total width of the line can be increased if we end up
// justifying text.
int x = leftOffset(m_height);
- int availableWidth = lineWidth(m_height);
switch(style()->textAlign()) {
case LEFT:
case KHTML_LEFT:
@@ -1723,23 +1732,16 @@
return false;
}
-BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi)
+static const ushort nonBreakingSpace = 0xa0;
+
+int RenderBlock::skipWhitespace(BidiIterator &it, BidiState &bidi)
{
int width = lineWidth(m_height);
- int w = 0;
- int tmpW = 0;
-#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "findNextLineBreak: line at " << m_height << " line width " << width << endl;
- kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;
-#endif
-
- // eliminate spaces at beginning of line
- // remove leading spaces. Any inline flows we encounter will be empty and should also
- // be skipped.
- while (!start.atEnd() && (start.obj->isInlineFlow() || (start.obj->style()->whiteSpace() != PRE && !start.obj->isBR() &&
- (start.current() == ' ' || start.current() == '\n' || start.obj->isFloatingOrPositioned())))) {
- if( start.obj->isFloatingOrPositioned() ) {
- RenderObject *o = start.obj;
+ while (!it.atEnd() && (it.obj->isInlineFlow() || (it.obj->style()->whiteSpace() != PRE && !it.obj->isBR() &&
+ (it.current() == ' ' || it.current() == '\n' ||
+ (it.obj->style()->nbspMode() == SPACE && it.current().unicode() == nonBreakingSpace) || it.obj->isFloatingOrPositioned())))) {
+ if (it.obj->isFloatingOrPositioned()) {
+ RenderObject *o = it.obj;
// add to special objects...
if (o->isFloating()) {
insertFloatingObject(o);
@@ -1757,9 +1759,24 @@
}
adjustEmbedding = true;
- start.increment(bidi);
+ it.increment(bidi);
adjustEmbedding = false;
}
+ return width;
+}
+
+BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi)
+{
+ int width = lineWidth(m_height);
+ int w = 0;
+ int tmpW = 0;
+#ifdef DEBUG_LINEBREAKS
+ kdDebug(6041) << "findNextLineBreak: line at " << m_height << " line width " << width << endl;
+ kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;
+#endif
+
+ // eliminate spaces at beginning of line
+ width = skipWhitespace(start, bidi);
if ( start.atEnd() ){
return start;
@@ -1967,11 +1984,12 @@
}
bool applyWordSpacing = false;
-
- bool breakWords = w == 0 && o->style()->whiteSpace() == NORMAL && o->style()->wordWrap() == BREAK_WORD;
+ bool isNormal = o->style()->whiteSpace() == NORMAL;
+ bool breakNBSP = isNormal && o->style()->nbspMode() == SPACE;
+ bool breakWords = w == 0 && isNormal && o->style()->wordWrap() == BREAK_WORD;
if (breakWords)
wrapW += t->width(pos, 1, f);
- if ((isPre && c == '\n') || (!isPre && isBreakable(str, pos, strlen)) || (breakWords && wrapW > width)) {
+ if ((isPre && c == '\n') || (!isPre && isBreakable(str, pos, strlen, breakNBSP)) || (breakWords && wrapW > width)) {
if (ignoringSpaces) {
if (!currentCharacterIsSpace) {
// Stop ignoring spaces and begin at this
@@ -2023,8 +2041,11 @@
}
if (o->style()->whiteSpace() == NORMAL) {
- if (w + tmpW > width)
+ if (w + tmpW > width) {
+ if (o->style()->khtmlLineBreak() == AFTER_WHITE_SPACE)
+ skipWhitespace(lBreak, bidi);
goto end; // Didn't fit. Jump to the end.
+ }
else if (pos > 1 && str[pos-1].unicode() == SOFT_HYPHEN)
// Subtract the width of the soft hyphen out since we fit on a line.
tmpW -= t->width(pos-1, 1, f);