ActualTabWidth() takes a location parameter, not an offset. Fixed bug 249 for real

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16600 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2006-03-06 11:03:53 +00:00
parent 0cf867048b
commit ace32536d4
+7 -95
View File
@@ -1778,118 +1778,30 @@ BTextView::OffsetAt(BPoint point) const
point.x -= fTextRect.left; point.x -= fTextRect.left;
point.x = max_c(point.x, 0.0); point.x = max_c(point.x, 0.0);
// TODO: The following isn't efficient like the part after the #else, // TODO: The following code isn't very efficient because it always starts from the left end,
// but it's multi-byte characters safe. // so when the point is near the right end it's very slow.
#if 1
int32 offset = line->offset; int32 offset = line->offset;
int32 limit = (line + 1)->offset; int32 limit = (line + 1)->offset;
int32 saveOffset; int32 saveOffset;
float x = 0; float location = 0;
do { do {
saveOffset = offset; saveOffset = offset;
int32 nextInitial = NextInitialByte(offset); int32 nextInitial = NextInitialByte(offset);
float width = 0; float width = 0;
if (ByteAt(offset) == B_TAB) if (ByteAt(offset) == B_TAB)
width = ActualTabWidth(offset); width = ActualTabWidth(location);
else else
width = StyledWidth(saveOffset, nextInitial - saveOffset); width = StyledWidth(saveOffset, nextInitial - saveOffset);
if (x + width > point.x) { if (location + width > point.x) {
if (fabs(x + width - point.x) < fabs(x - point.x)) if (fabs(location + width - point.x) < fabs(location - point.x))
offset = nextInitial; offset = nextInitial;
break; break;
} }
x += width; location += width;
offset = nextInitial; offset = nextInitial;
} while (offset < limit); } while (offset < limit);
#else
// do a pseudo-binary search of the character widths on the line
// that PixelToLine() gave us
// note: the right half of a character returns its offset + 1
int32 offset = line->offset;
int32 saveOffset = offset;
int32 delta = 0;
int32 limit = (line + 1)->offset;
int32 length = limit - line->offset;
float sigmaWidth = 0.0;
float tabWidth = 0.0;
int32 numChars = length;
bool done = false;
bool foundTab = false;
do {
saveOffset = offset;
if (foundTab) {
// is the point in the right-half of the tab?
if (point.x >= (sigmaWidth - (tabWidth / 2)) &&
point.x < sigmaWidth)
break;
}
// any more tabs?
foundTab = fText->FindChar(B_TAB, offset, &numChars);
delta = numChars / 2;
delta = max_c(delta, 1);
if (numChars > 1) {
do {
float deltaWidth = StyledWidth(offset, delta);
float leftWidth = StyledWidth(offset + delta - 1, 1);
sigmaWidth += deltaWidth;
if (point.x >= (sigmaWidth - (leftWidth / 2))) {
// we're to the left of the point
float rightWidth = StyledWidth(offset + delta, 1);
if (point.x < (sigmaWidth + (rightWidth / 2))) {
// the next character is to the right, we're done!
offset += delta;
done = true;
break;
} else {
// still too far to the left, measure some more
offset += delta;
delta /= 2;
delta = max_c(delta, 1);
}
} else {
// oops, we overshot the point, go back some
sigmaWidth -= deltaWidth;
if (delta == 1) {
done = true;
break;
}
delta /= 2;
delta = min_c(delta, 1);
}
} while (offset < (numChars + saveOffset));
}
if (done || offset >= limit)
break;
if (foundTab) {
tabWidth = ActualTabWidth(sigmaWidth);
// is the point in the left-half of the tab?
if (point.x < (sigmaWidth + (tabWidth / 2)))
break;
sigmaWidth += tabWidth;
numChars++;
}
offset = saveOffset + numChars;
length -= numChars;
numChars = length;
} while (foundTab && length > 0);
#endif
if (offset == (line + 1)->offset) { if (offset == (line + 1)->offset) {
// special case: newlines aren't visible // special case: newlines aren't visible
// return the offset of the character preceding the newline // return the offset of the character preceding the newline