* added _TabExpandedStyledWidth(), which makes sure to expand all tab chars

during the width calculation
* used _TabExpandedStyledWidth() at all places that need to expand tabs,
  fixing #4822
* removed _StyledWidthUTF8Safe() as it didn't make sense - we now perform
  the same auto-scrolling horizontally as we do vertically


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33713 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe
2009-10-21 19:09:20 +00:00
parent ee739a2777
commit 32c8ab89a9
2 changed files with 64 additions and 50 deletions
+2 -2
View File
@@ -312,8 +312,8 @@ private:
float _StyledWidth(int32 fromOffset, int32 length, float _StyledWidth(int32 fromOffset, int32 length,
float* outAscent = NULL, float* outAscent = NULL,
float* outDescent = NULL) const; float* outDescent = NULL) const;
float _StyledWidthUTF8Safe(int32 fromOffset, float _TabExpandedStyledWidth(int32 offset,
int32 numChars, float* outAscent = NULL, int32 length, float* outAscent = NULL,
float* outDescent = NULL) const; float* outDescent = NULL) const;
float _ActualTabWidth(float location) const; float _ActualTabWidth(float location) const;
+62 -48
View File
@@ -1781,24 +1781,9 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
fStyles->SyncNullStyle(inOffset); fStyles->SyncNullStyle(inOffset);
height = _NullStyleHeight(); height = _NullStyleHeight();
} else { } else {
int32 offset = line->offset;
int32 length = inOffset - line->offset; int32 length = inOffset - line->offset;
int32 numBytes = length; result.x += _TabExpandedStyledWidth(line->offset, length);
bool foundTab = false;
do {
foundTab = fText->FindChar(B_TAB, offset, &numBytes);
float width = _StyledWidth(offset, numBytes);
result.x += width;
if (foundTab) {
result.x += _ActualTabWidth(result.x);
numBytes++;
}
offset += numBytes;
length -= numBytes;
numBytes = length;
} while (foundTab && length > 0);
} }
} }
@@ -1993,7 +1978,7 @@ BTextView::LineWidth(int32 lineNum) const
if (ByteAt((line + 1)->offset - 1) == B_ENTER) if (ByteAt((line + 1)->offset - 1) == B_ENTER)
length--; length--;
return _StyledWidth(line->offset, length); return _TabExpandedStyledWidth(line->offset, length);
} }
@@ -3839,8 +3824,8 @@ BTextView::_FindLineBreak(int32 fromOffset, float *outAscent, float *outDescent,
offset += fromOffset; offset += fromOffset;
int32 toOffset = (offset < limit) ? offset : limit; int32 toOffset = (offset < limit) ? offset : limit;
*inOutWidth = _StyledWidth(fromOffset, toOffset - fromOffset, outAscent, *inOutWidth = _TabExpandedStyledWidth(fromOffset, toOffset - fromOffset,
outDescent); outAscent, outDescent);
return offset < limit ? offset + 1 : limit; return offset < limit ? offset + 1 : limit;
} }
@@ -4037,6 +4022,49 @@ BTextView::_NextWordBoundary(int32 offset)
} }
/*! \brief Returns the width used by the characters starting at the given
offset with the given length, expanding all tab characters as needed.
*/
float
BTextView::_TabExpandedStyledWidth(int32 offset, int32 length, float* outAscent,
float* outDescent) const
{
float ascent = 0.0;
float descent = 0.0;
float maxAscent = 0.0;
float maxDescent = 0.0;
float width = 0.0;
int32 numBytes = length;
bool foundTab = false;
do {
foundTab = fText->FindChar(B_TAB, offset, &numBytes);
width += _StyledWidth(offset, numBytes, &ascent, &descent);
if (maxAscent < ascent)
maxAscent = ascent;
if (maxDescent < descent)
maxDescent = descent;
if (foundTab) {
width += _ActualTabWidth(width);
numBytes++;
}
offset += numBytes;
length -= numBytes;
numBytes = length;
} while (foundTab && length > 0);
if (outAscent != NULL)
*outAscent = maxAscent;
if (outDescent != NULL)
*outDescent = maxDescent;
return width;
}
/*! \brief Calculate the width of the text within the given limits. /*! \brief Calculate the width of the text within the given limits.
\param fromOffset The offset where to start. \param fromOffset The offset where to start.
\param length The length of the text to examine. \param length The length of the text to examine.
@@ -4047,8 +4075,8 @@ BTextView::_NextWordBoundary(int32 offset)
\return The width for the text within the given limits. \return The width for the text within the given limits.
*/ */
float float
BTextView::_StyledWidth(int32 fromOffset, int32 length, float *outAscent, BTextView::_StyledWidth(int32 fromOffset, int32 length, float* outAscent,
float *outDescent) const float* outDescent) const
{ {
if (length == 0) { if (length == 0) {
// determine height of char at given offset, but return empty width // determine height of char at given offset, but return empty width
@@ -4098,21 +4126,6 @@ BTextView::_StyledWidth(int32 fromOffset, int32 length, float *outAscent,
} }
// Unlike the _StyledWidth method, this one takes as parameter
// the number of chars, not the number of bytes.
float
BTextView::_StyledWidthUTF8Safe(int32 fromOffset, int32 numChars,
float *outAscent, float *outDescent) const
{
int32 toOffset = fromOffset;
while (numChars--)
toOffset = _NextInitialByte(toOffset);
const int32 length = toOffset - fromOffset;
return _StyledWidth(fromOffset, length, outAscent, outDescent);
}
/*! \brief Calculate the actual tab width for the given location. /*! \brief Calculate the actual tab width for the given location.
\param location The location to calculate the tab width of. \param location The location to calculate the tab width of.
\return The actual tab width for the given location \return The actual tab width for the given location
@@ -4741,24 +4754,25 @@ BTextView::_PerformAutoScrolling()
BRect bounds = Bounds(); BRect bounds = Bounds();
BPoint scrollBy(B_ORIGIN); BPoint scrollBy(B_ORIGIN);
BPoint constraint = fWhere; // R5 does a pretty soft auto-scroll, we try to do the same by
constraint.ConstrainTo(bounds); // simply scrolling the distance between cursor and border
// Scroll char by char horizontally
// TODO: Check how BeOS R5 behaves
float value = _StyledWidthUTF8Safe(OffsetAt(constraint), 1);
if (fWhere.x > bounds.right) { if (fWhere.x > bounds.right) {
if (bounds.right + value <= fTextRect.Width()) scrollBy.x = fWhere.x - bounds.right;
scrollBy.x = value;
} else if (fWhere.x < bounds.left) { } else if (fWhere.x < bounds.left) {
if (bounds.left - value >= 0) scrollBy.x = fWhere.x - bounds.left; // negative value
scrollBy.x = -value; }
// prevent from scrolling out of view
if (scrollBy.x != 0.0) {
float rightMax = floorf(fTextRect.right + fLayoutData->rightInset);
if (bounds.right + scrollBy.x > rightMax)
scrollBy.x = rightMax - bounds.right;
if (bounds.left + scrollBy.x < 0)
scrollBy.x = -bounds.left;
} }
if (CountLines() > 1) { if (CountLines() > 1) {
// scroll in Y only if multiple lines! // scroll in Y only if multiple lines!
// R5 does a pretty soft auto-scroll, we try to do the same by
// simply scrolling the distance between cursor and border
if (fWhere.y > bounds.bottom) { if (fWhere.y > bounds.bottom) {
scrollBy.y = fWhere.y - bounds.bottom; scrollBy.y = fWhere.y - bounds.bottom;
} else if (fWhere.y < bounds.top) { } else if (fWhere.y < bounds.top) {