Fixed artifacts when highlighing text, added Hiroshi Lockheimer to the authors list (BTextView is based on his SteEngine), reformatted the code some more to comply with our guidelines
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5563 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,7 +20,9 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: TextView.cpp
|
||||
// Author: Marc Flerackers ([email protected]e)
|
||||
// Authors: Hiroshi Lockheimer (TextView is based on his STEEngine)
|
||||
// Marc Flerackers ([email protected])
|
||||
// Stefano Ceccherini ([email protected])
|
||||
// Description: BTextView displays and manages styled text.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -66,6 +68,7 @@ struct flattened_text_run {
|
||||
uint16 _reserved_; /* 0 */
|
||||
};
|
||||
|
||||
|
||||
struct flattened_text_run_array {
|
||||
uchar magic[4]; /* 41 6c 69 21 */
|
||||
uchar version[4]; /* 00 00 00 00 */
|
||||
@@ -73,6 +76,12 @@ struct flattened_text_run_array {
|
||||
flattened_text_run styles[1];
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
B_SEPARATOR_CHARACTER,
|
||||
B_OTHER_CHARACTER
|
||||
} separatorCharacters;
|
||||
|
||||
// _BTextTrackState_ class -----------------------------------------------------
|
||||
class _BTextTrackState_ {
|
||||
|
||||
@@ -89,8 +98,7 @@ public:
|
||||
|
||||
// Globals ---------------------------------------------------------------------
|
||||
static property_info
|
||||
prop_list[] =
|
||||
{
|
||||
prop_list[] = {
|
||||
{
|
||||
"Selection",
|
||||
{ B_GET_PROPERTY, 0 },
|
||||
@@ -237,23 +245,25 @@ BTextView::BTextView(BRect frame, const char *name, BRect textRect,
|
||||
BTextView::BTextView(BMessage *archive)
|
||||
: BView(archive)
|
||||
{
|
||||
const char *text;
|
||||
int32 flag, flag2;
|
||||
float value;
|
||||
BRect rect;
|
||||
bool toggle;
|
||||
|
||||
if (archive->FindRect("_trect", &rect) != B_OK)
|
||||
rect.Set(0, 0, 0, 0);
|
||||
|
||||
InitObject(rect, NULL, NULL);
|
||||
|
||||
const char *text = NULL;
|
||||
|
||||
if (archive->FindString("_text", &text) == B_OK)
|
||||
SetText(text);
|
||||
|
||||
int32 flag, flag2;
|
||||
|
||||
if (archive->FindInt32("_align", &flag) == B_OK)
|
||||
SetAlignment((alignment)flag);
|
||||
|
||||
float value;
|
||||
|
||||
if (archive->FindFloat("_tab", &value) == B_OK)
|
||||
SetTabWidth(value);
|
||||
|
||||
@@ -267,6 +277,8 @@ BTextView::BTextView(BMessage *archive)
|
||||
archive->FindInt32("_sel", &flag2) == B_OK)
|
||||
Select(flag, flag2);
|
||||
|
||||
bool toggle;
|
||||
|
||||
if (archive->FindBool("_stylable", &toggle) == B_OK)
|
||||
SetStylable(toggle);
|
||||
|
||||
@@ -297,7 +309,7 @@ BTextView::BTextView(BMessage *archive)
|
||||
const void *flattenedRunArray = NULL;
|
||||
if (archive->FindData("_runs", B_RAW_TYPE, &flattenedRunArray, &runSize) == B_OK) {
|
||||
|
||||
text_run_array *runArray = UnflattenRunArray(runArray, (int32*)&runSize);
|
||||
text_run_array *runArray = UnflattenRunArray(runArray, (int32 *)&runSize);
|
||||
SetRunArray(0, TextLength(), runArray);
|
||||
free(runArray);
|
||||
}
|
||||
@@ -348,11 +360,12 @@ BTextView::Archive(BMessage *data, bool deep) const
|
||||
|
||||
ssize_t runSize = 0;
|
||||
text_run_array *runArray = RunArray(0, TextLength());
|
||||
|
||||
void *flattened = FlattenRunArray(runArray, (int32*)&runSize);
|
||||
|
||||
if (flattened != NULL) {
|
||||
data->AddData("_runs", B_RAW_TYPE, flattened, runSize);
|
||||
|
||||
free(flattened);
|
||||
}
|
||||
free(runArray);
|
||||
|
||||
return err;
|
||||
@@ -421,7 +434,7 @@ BTextView::MouseDown(BPoint where)
|
||||
bool shiftDown = modifiers() & B_SHIFT_KEY;
|
||||
|
||||
// should we initiate a drag?
|
||||
if ((fSelStart != fSelEnd) && (!shiftDown)) {
|
||||
if (fSelStart != fSelEnd && !shiftDown) {
|
||||
BPoint loc;
|
||||
ulong buttons;
|
||||
GetMouse(&loc, &buttons);
|
||||
@@ -429,7 +442,7 @@ BTextView::MouseDown(BPoint where)
|
||||
// since dragging works also with the primary button.
|
||||
if (buttons == B_SECONDARY_MOUSE_BUTTON) {
|
||||
// was the click within the selection range?
|
||||
if ((mouseOffset >= fSelStart) && (mouseOffset <= fSelEnd)) {
|
||||
if (mouseOffset >= fSelStart && mouseOffset <= fSelEnd) {
|
||||
InitiateDrag();
|
||||
return;
|
||||
}
|
||||
@@ -441,8 +454,8 @@ BTextView::MouseDown(BPoint where)
|
||||
get_click_speed(&clickSpeed);
|
||||
|
||||
// is this a double/triple click, or is it a new click?
|
||||
if ( (clickSpeed > (system_time() - fClickTime)) &&
|
||||
(mouseOffset == fClickOffset) ) {
|
||||
if ( clickSpeed > (system_time() - fClickTime) &&
|
||||
mouseOffset == fClickOffset ) {
|
||||
if (fClickCount > 1) {
|
||||
// triple click
|
||||
fClickCount = 0;
|
||||
@@ -452,8 +465,7 @@ BTextView::MouseDown(BPoint where)
|
||||
fClickCount = 2;
|
||||
fClickTime = system_time();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// new click
|
||||
fClickOffset = mouseOffset;
|
||||
fClickCount = 1;
|
||||
@@ -480,8 +492,7 @@ BTextView::MouseDown(BPoint where)
|
||||
if (mouseOffset > anchor) {
|
||||
start = anchor;
|
||||
end = mouseOffset;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
start = mouseOffset;
|
||||
end = anchor;
|
||||
}
|
||||
@@ -534,7 +545,7 @@ BTextView::MouseDown(BPoint where)
|
||||
if (vDelta != 0)
|
||||
ScrollBar(B_VERTICAL)->SetValue(ScrollBar(B_VERTICAL)->Value() + vDelta);
|
||||
}
|
||||
if ((hDelta != 0) || (vDelta != 0))
|
||||
if (hDelta != 0 || vDelta != 0)
|
||||
Window()->UpdateIfNeeded();
|
||||
}
|
||||
|
||||
@@ -557,7 +568,7 @@ BTextView::MouseMoved(BPoint where, uint32 code, const BMessage *message)
|
||||
{
|
||||
switch (code) {
|
||||
case B_ENTERED_VIEW:
|
||||
if ((fActive) && (message == NULL))
|
||||
if (fActive && message == NULL)
|
||||
SetViewCursor(B_CURSOR_I_BEAM);
|
||||
break;
|
||||
|
||||
@@ -588,8 +599,7 @@ BTextView::WindowActivated(bool state)
|
||||
if (state && IsFocus()) {
|
||||
if (!fActive)
|
||||
Activate();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (fActive)
|
||||
Deactivate();
|
||||
}
|
||||
@@ -656,7 +666,7 @@ BTextView::KeyDown(const char *bytes, int32 numBytes)
|
||||
void
|
||||
BTextView::Pulse()
|
||||
{
|
||||
if ((fActive) && (fEditable) && (fSelStart == fSelEnd)) {
|
||||
if (fActive && fEditable && fSelStart == fSelEnd) {
|
||||
if (system_time() > (fCaretTime + 500000.0))
|
||||
InvertCaret();
|
||||
}
|
||||
@@ -678,8 +688,7 @@ BTextView::MakeFocus(bool focusState)
|
||||
if (focusState && Window()->IsActive()) {
|
||||
if (!fActive)
|
||||
Activate();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (fActive)
|
||||
Deactivate();
|
||||
}
|
||||
@@ -794,9 +803,6 @@ BTextView::ResolveSpecifier(BMessage *message, int32 index,
|
||||
BHandler *target = NULL;
|
||||
|
||||
switch (propInfo.FindMatch(message, 0, specifier, form, property)) {
|
||||
case B_ERROR:
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
@@ -806,6 +812,9 @@ BTextView::ResolveSpecifier(BMessage *message, int32 index,
|
||||
case 6:
|
||||
target = this;
|
||||
break;
|
||||
case B_ERROR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!target)
|
||||
@@ -911,7 +920,7 @@ BTextView::SetText(const char *inText, int32 inLength,
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
BTextView::SetText (BFile *inFile, int32 startOffset, int32 inLength,
|
||||
BTextView::SetText(BFile *inFile, int32 startOffset, int32 inLength,
|
||||
const text_run_array *inRuns)
|
||||
{
|
||||
// TODO:
|
||||
@@ -1052,7 +1061,7 @@ void
|
||||
BTextView::GetText(int32 offset, int32 length, char *buffer) const
|
||||
{
|
||||
int32 textLen = fText->Length();
|
||||
if ((offset < 0) || (offset > (textLen - 1))) {
|
||||
if (offset < 0 || offset > (textLen - 1)) {
|
||||
buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
@@ -1132,7 +1141,8 @@ BTextView::Paste(BClipboard *clipboard)
|
||||
BMessage *clip = NULL;
|
||||
|
||||
if (clipboard->Lock()) {
|
||||
if ((clip = clipboard->Data()) != NULL) {
|
||||
clip = clipboard->Data();
|
||||
if (clip != NULL) {
|
||||
const char *text = NULL;
|
||||
ssize_t len = 0;
|
||||
|
||||
@@ -1203,7 +1213,7 @@ BTextView::Select(int32 startOffset, int32 endOffset)
|
||||
return;
|
||||
|
||||
// is the new selection any different from the current selection?
|
||||
if ((startOffset == fSelStart) && (endOffset == fSelEnd))
|
||||
if (startOffset == fSelStart && endOffset == fSelEnd)
|
||||
return;
|
||||
|
||||
fStyles->InvalidateNullStyle();
|
||||
@@ -1224,8 +1234,7 @@ BTextView::Select(int32 startOffset, int32 endOffset)
|
||||
Highlight(fSelStart, fSelEnd);
|
||||
}
|
||||
fSelStart = fSelEnd = startOffset;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (fActive) {
|
||||
// draw only those ranges that are different
|
||||
long start, end;
|
||||
@@ -1234,8 +1243,7 @@ BTextView::Select(int32 startOffset, int32 endOffset)
|
||||
if (startOffset > fSelStart) {
|
||||
start = fSelStart;
|
||||
end = startOffset;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
start = startOffset;
|
||||
end = fSelStart;
|
||||
}
|
||||
@@ -1247,8 +1255,7 @@ BTextView::Select(int32 startOffset, int32 endOffset)
|
||||
if (endOffset > fSelEnd) {
|
||||
start = fSelEnd;
|
||||
end = endOffset;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
start = endOffset;
|
||||
end = fSelEnd;
|
||||
}
|
||||
@@ -1299,7 +1306,7 @@ BTextView::SetFontAndColor(const BFont *inFont, uint32 inMode,
|
||||
fStyles->SetStyleRange(fSelStart, fSelEnd, fText->Length(),
|
||||
inMode, &newFont, inColor);
|
||||
|
||||
if ((inMode & doFont) || (inMode & doSize))
|
||||
if (inMode & doFont || inMode & doSize)
|
||||
// recalc the line breaks and redraw with new style
|
||||
Refresh(fSelStart, fSelEnd, fSelStart != fSelEnd, false);
|
||||
else
|
||||
@@ -1339,7 +1346,7 @@ BTextView::SetFontAndColor(int32 startOffset, int32 endOffset,
|
||||
fStyles->SetStyleRange(startOffset, endOffset, fText->Length(),
|
||||
inMode, &newFont, inColor);
|
||||
|
||||
if ((inMode & doFont) || (inMode & doSize))
|
||||
if (inMode & doFont || inMode & doSize)
|
||||
// recalc the line breaks and redraw with new style
|
||||
Refresh(startOffset, endOffset, startOffset != endOffset, false);
|
||||
else
|
||||
@@ -1413,7 +1420,7 @@ BTextView::RunArray(int32 startOffset, int32 endOffset,
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
text_run_array *res = (text_run_array*)malloc(sizeof(int32) +
|
||||
text_run_array *res = (text_run_array *)malloc(sizeof(int32) +
|
||||
(sizeof(text_run) * result->count));
|
||||
|
||||
res->count = result->count;
|
||||
@@ -1455,14 +1462,13 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
|
||||
result.y = line->origin + fTextRect.top;
|
||||
|
||||
// special case: go down one line if inOffset is a newline
|
||||
if ((inOffset == textLength) && ((*fText)[textLength - 1] == '\n')) {
|
||||
if (inOffset == textLength && (*fText)[textLength - 1] == '\n') {
|
||||
float ascent, descent;
|
||||
StyledWidth(inOffset, 1, &ascent, &descent);
|
||||
|
||||
result.y += height;
|
||||
height = ascent + descent;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int32 offset = line->offset;
|
||||
int32 length = inOffset - line->offset;
|
||||
int32 numChars = length;
|
||||
@@ -1480,7 +1486,7 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
|
||||
offset += numChars;
|
||||
length -= numChars;
|
||||
numChars = length;
|
||||
} while ((foundTab) && (length > 0));
|
||||
} while (foundTab && length > 0);
|
||||
}
|
||||
|
||||
// convert from text rect coordinates
|
||||
@@ -1501,10 +1507,8 @@ BTextView::OffsetAt(BPoint point) const
|
||||
// should we even bother?
|
||||
if (point.y >= fTextRect.bottom)
|
||||
return fText->Length();
|
||||
else {
|
||||
if (point.y < fTextRect.top)
|
||||
else if (point.y < fTextRect.top)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 lineNum = LineAt(point);
|
||||
STELinePtr line = (*fLines)[lineNum];
|
||||
@@ -1540,8 +1544,8 @@ BTextView::OffsetAt(BPoint point) const
|
||||
|
||||
if (foundTab) {
|
||||
// is the point in the right-half of the tab?
|
||||
if ((point.x >= (sigmaWidth - (tabWidth / 2))) &&
|
||||
(point.x < sigmaWidth))
|
||||
if (point.x >= (sigmaWidth - (tabWidth / 2)) &&
|
||||
point.x < sigmaWidth)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1565,15 +1569,13 @@ BTextView::OffsetAt(BPoint point) const
|
||||
offset += delta;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// still too far to the left, measure some more
|
||||
offset += delta;
|
||||
delta /= 2;
|
||||
delta = (delta < 1) ? 1 : delta;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// oops, we overshot the point, go back some
|
||||
sigmaWidth -= deltaWidth;
|
||||
|
||||
@@ -1589,7 +1591,7 @@ BTextView::OffsetAt(BPoint point) const
|
||||
} while (offset < (numChars + saveOffset));
|
||||
}
|
||||
|
||||
if (done || (offset >= limit))
|
||||
if (done || offset >= limit)
|
||||
break;
|
||||
|
||||
if (foundTab) {
|
||||
@@ -1606,18 +1608,18 @@ BTextView::OffsetAt(BPoint point) const
|
||||
offset = saveOffset + numChars;
|
||||
length -= numChars;
|
||||
numChars = length;
|
||||
} while ((foundTab) && (length > 0));
|
||||
} while (foundTab && length > 0);
|
||||
|
||||
if (offset == (line + 1)->offset) {
|
||||
// special case: newlines aren't visible
|
||||
// return the offset of the character preceding the newline
|
||||
if ((*fText)[offset - 1] == '\n')
|
||||
return (--offset);
|
||||
return --offset;
|
||||
|
||||
// special case: return the offset preceding any spaces that
|
||||
// aren't at the end of the buffer
|
||||
if ((offset != fText->Length()) && ((*fText)[offset - 1] == ' '))
|
||||
return (--offset);
|
||||
if (offset != fText->Length() && (*fText)[offset - 1] == ' ')
|
||||
return --offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
@@ -1632,8 +1634,6 @@ BTextView::OffsetAt(int32 line) const
|
||||
return (*fLines)[line]->offset;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
enum { B_SEPARATOR_CHARACTER, B_OTHER_CHARACTER };
|
||||
|
||||
void
|
||||
BTextView::FindWord(int32 inOffset, int32 *outFromOffset,
|
||||
int32 *outToOffset)
|
||||
@@ -1662,29 +1662,7 @@ BTextView::FindWord(int32 inOffset, int32 *outFromOffset,
|
||||
bool
|
||||
BTextView::CanEndLine(int32 offset)
|
||||
{
|
||||
switch ((*fText)[offset]) {
|
||||
case '\0':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case ' ':
|
||||
case '&':
|
||||
case '*':
|
||||
case '+':
|
||||
case '-':
|
||||
case '/':
|
||||
case '<':
|
||||
case '=':
|
||||
case '>':
|
||||
case '\\':
|
||||
case '^':
|
||||
case '|':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return (CharClassification(offset) == B_SEPARATOR_CHARACTER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
float
|
||||
@@ -1719,7 +1697,7 @@ BTextView::TextHeight(int32 startLine, int32 endLine) const
|
||||
float height = (*fLines)[endLine + 1]->origin -
|
||||
(*fLines)[startLine]->origin;
|
||||
|
||||
if ((endLine == numLines - 1) && ((*fText)[fText->Length() - 1] == '\n'))
|
||||
if (endLine == numLines - 1 && (*fText)[fText->Length() - 1] == '\n')
|
||||
height += (*fLines)[endLine + 1]->origin - (*fLines)[endLine]->origin;
|
||||
|
||||
return height;
|
||||
@@ -1739,6 +1717,7 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset,
|
||||
float endLineHeight = 0.0;
|
||||
BPoint startPt = PointAt(startOffset, &startLineHeight);
|
||||
BPoint endPt = PointAt(endOffset, &endLineHeight);
|
||||
|
||||
BRect selRect;
|
||||
|
||||
if (startPt.y == endPt.y) {
|
||||
@@ -1748,8 +1727,7 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset,
|
||||
selRect.right = endPt.x - 1.0;
|
||||
selRect.bottom = endPt.y + endLineHeight - 1.0;
|
||||
outRegion->Include(selRect);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// more than one line in the specified offset range
|
||||
selRect.left = (startPt.x < fTextRect.left) ? fTextRect.left : startPt.x;
|
||||
selRect.top = startPt.y;
|
||||
@@ -1757,10 +1735,10 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset,
|
||||
selRect.bottom = startPt.y + startLineHeight - 1.0;
|
||||
outRegion->Include(selRect);
|
||||
|
||||
if ((startPt.y + startLineHeight) < endPt.y) {
|
||||
if (startPt.y + startLineHeight < endPt.y) {
|
||||
// more than two lines in the range
|
||||
selRect.left = fTextRect.left;
|
||||
selRect.top = startPt.y + startLineHeight;
|
||||
selRect.top = startPt.y + startLineHeight + 1.0;
|
||||
selRect.right = fTextRect.right;
|
||||
selRect.bottom = endPt.y - 1.0;
|
||||
outRegion->Include(selRect);
|
||||
@@ -1783,12 +1761,12 @@ BTextView::ScrollToOffset(int32 inOffset)
|
||||
BPoint point = PointAt(inOffset, &lineHeight);
|
||||
|
||||
if (ScrollBar(B_HORIZONTAL) != NULL) {
|
||||
if ((point.x < bounds.left) || (point.x >= bounds.right))
|
||||
if (point.x < bounds.left || point.x >= bounds.right)
|
||||
ScrollBar(B_HORIZONTAL)->SetValue(point.x - (bounds.IntegerWidth() / 2));
|
||||
}
|
||||
|
||||
if (ScrollBar(B_VERTICAL) != NULL) {
|
||||
if ((point.y < bounds.top) || ((point.y + lineHeight) >= bounds.bottom))
|
||||
if (point.y < bounds.top || (point.y + lineHeight) >= bounds.bottom)
|
||||
ScrollBar(B_VERTICAL)->SetValue(point.y - (bounds.IntegerHeight() / 2));
|
||||
}
|
||||
}
|
||||
@@ -1809,11 +1787,9 @@ BTextView::Highlight(int32 startOffset, int32 endOffset)
|
||||
BRegion selRegion;
|
||||
GetTextRegion(startOffset, endOffset, &selRegion);
|
||||
|
||||
ConstrainClippingRegion(&selRegion);
|
||||
InvertRect(selRegion.Frame());
|
||||
ConstrainClippingRegion(NULL);
|
||||
|
||||
Flush(); ////
|
||||
SetDrawingMode(B_OP_INVERT);
|
||||
FillRegion(&selRegion, B_SOLID_HIGH);
|
||||
SetDrawingMode(B_OP_COPY);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
@@ -1899,7 +1875,7 @@ BTextView::MakeEditable(bool editable)
|
||||
|
||||
if (Window() != NULL) {
|
||||
if (fActive) {
|
||||
if ((!fEditable) && (fCaretVisible))
|
||||
if (!fEditable && fCaretVisible)
|
||||
InvertCaret();
|
||||
}
|
||||
}
|
||||
@@ -2089,7 +2065,7 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize)
|
||||
int32 size = sizeof(flattened_text_run_array) + (inArray->count - 1) *
|
||||
sizeof(flattened_text_run_array);
|
||||
|
||||
flattened_text_run_array *array = (flattened_text_run_array*)malloc(size);
|
||||
flattened_text_run_array *array = (flattened_text_run_array *)malloc(size);
|
||||
|
||||
array->magic[0] = 0x41;
|
||||
array->magic[1] = 0x6c;
|
||||
@@ -2124,7 +2100,7 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize)
|
||||
text_run_array *
|
||||
BTextView::UnflattenRunArray(const void *data, int32 *outSize)
|
||||
{
|
||||
flattened_text_run_array *array = (flattened_text_run_array*)data;
|
||||
flattened_text_run_array *array = (flattened_text_run_array *)data;
|
||||
|
||||
if (array->magic[0] != 0x41 || array->magic[1] != 0x6c ||
|
||||
array->magic[2] != 0x69 || array->magic[3] != 0x21 ||
|
||||
@@ -2139,7 +2115,7 @@ BTextView::UnflattenRunArray(const void *data, int32 *outSize)
|
||||
|
||||
int32 size = sizeof(text_run_array) + (array->count - 1) * sizeof(text_run);
|
||||
|
||||
text_run_array *run_array = (text_run_array*)malloc(size);
|
||||
text_run_array *run_array = (text_run_array *)malloc(size);
|
||||
|
||||
run_array->count = array->count;
|
||||
|
||||
@@ -2200,7 +2176,7 @@ BTextView::DeleteText(int32 fromOffset, int32 toOffset)
|
||||
//_ASSERT ( _CrtCheckMemory () );
|
||||
|
||||
// sanity checking
|
||||
if ((fromOffset >= toOffset) || (fromOffset < 0) || (toOffset < 0))
|
||||
if (fromOffset >= toOffset || fromOffset < 0 || toOffset < 0)
|
||||
return;
|
||||
|
||||
// set nullStyle to style at beginning of range
|
||||
@@ -2236,6 +2212,9 @@ void
|
||||
BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap,
|
||||
BPoint *point, BHandler **handler)
|
||||
{
|
||||
if (drag == NULL)
|
||||
return;
|
||||
|
||||
// What is this for ?
|
||||
drag->AddInt32("be_actions", B_TRASH_TARGET);
|
||||
|
||||
@@ -2254,6 +2233,11 @@ BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap,
|
||||
drag->AddPointer("be:originator", this);
|
||||
|
||||
free(styles);
|
||||
|
||||
if (bitmap != NULL)
|
||||
*bitmap = NULL;
|
||||
if (handler != NULL)
|
||||
*handler = NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BTextView::_ReservedTextView3() {}
|
||||
@@ -2293,7 +2277,6 @@ BTextView::InitObject(BRect textRect, const BFont *initialFont,
|
||||
void
|
||||
BTextView::HandleBackspace()
|
||||
{
|
||||
|
||||
if (fUndo) {
|
||||
_BTypingUndoBuffer_ *undoBuffer = dynamic_cast<_BTypingUndoBuffer_ *>(fUndo);
|
||||
if (!undoBuffer) {
|
||||
@@ -2335,13 +2318,11 @@ BTextView::HandleArrowKey(uint32 inArrowKey)
|
||||
if (shiftDown) {
|
||||
if (selStart > 0)
|
||||
selStart = PreviousInitialByte(selStart);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (selStart == selEnd) {
|
||||
if (selStart > 0)
|
||||
selEnd = selStart = PreviousInitialByte(selStart);
|
||||
}
|
||||
else
|
||||
} else
|
||||
selEnd = selStart;
|
||||
}
|
||||
scrollToOffset = selStart;
|
||||
@@ -2351,8 +2332,7 @@ BTextView::HandleArrowKey(uint32 inArrowKey)
|
||||
if (shiftDown) {
|
||||
if (selEnd < fText->Length())
|
||||
selEnd = NextInitialByte(selEnd);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (selStart == selEnd) {
|
||||
if (selStart < fText->Length())
|
||||
selStart = selEnd = NextInitialByte(selEnd);
|
||||
@@ -2413,8 +2393,7 @@ BTextView::HandleDelete()
|
||||
return;
|
||||
else
|
||||
fSelEnd = NextInitialByte(fSelEnd);
|
||||
}
|
||||
else
|
||||
} else
|
||||
Highlight(fSelStart, fSelEnd);
|
||||
|
||||
DeleteText(fSelStart, fSelEnd);
|
||||
@@ -2507,8 +2486,8 @@ BTextView::Refresh(int32 fromOffset, int32 toOffset, bool erase,
|
||||
float newHeight = fTextRect.Height();
|
||||
|
||||
// if the line breaks have changed, force an erase
|
||||
if ( (fromLine != saveFromLine) || (toLine != saveToLine) ||
|
||||
(newHeight != saveHeight) )
|
||||
if ( fromLine != saveFromLine || toLine != saveToLine ||
|
||||
newHeight != saveHeight )
|
||||
erase = true;
|
||||
|
||||
if (newHeight != saveHeight) {
|
||||
@@ -2526,8 +2505,8 @@ BTextView::Refresh(int32 fromOffset, int32 toOffset, bool erase,
|
||||
toLine = (toLine > toVisible) ? toVisible : toLine;
|
||||
|
||||
int32 drawOffset = fromOffset;
|
||||
if ( (LineHeight(fromLine) != saveLineHeight) ||
|
||||
(newHeight < saveHeight) || (fromLine < saveFromLine) )
|
||||
if ( LineHeight(fromLine) != saveLineHeight ||
|
||||
newHeight < saveHeight || fromLine < saveFromLine )
|
||||
drawOffset = (*fLines)[fromLine]->offset;
|
||||
|
||||
DrawLines(fromLine, toLine, drawOffset, erase);
|
||||
@@ -2536,7 +2515,7 @@ BTextView::Refresh(int32 fromOffset, int32 toOffset, bool erase,
|
||||
BRect eraseRect = bounds;
|
||||
eraseRect.top = fTextRect.top + (*fLines)[fLines->NumLines()]->origin;
|
||||
eraseRect.bottom = fTextRect.top + saveHeight;
|
||||
if ((eraseRect.bottom > eraseRect.top) && (eraseRect.Intersects(bounds))) {
|
||||
if (eraseRect.bottom > eraseRect.top && eraseRect.Intersects(bounds)) {
|
||||
SetLowColor(ViewColor());
|
||||
FillRect(eraseRect, B_SOLID_LOW);
|
||||
}
|
||||
@@ -2572,7 +2551,7 @@ BTextView::RecalLineBreaks(int32 *startLine, int32 *endLine)
|
||||
&descent, &width);
|
||||
|
||||
// we want to advance at least by one character
|
||||
if ((toOffset == fromOffset) && (fromOffset < textLength))
|
||||
if (toOffset == fromOffset && fromOffset < textLength)
|
||||
toOffset = NextInitialByte(toOffset);
|
||||
|
||||
// set the ascent of this line
|
||||
@@ -2580,23 +2559,22 @@ BTextView::RecalLineBreaks(int32 *startLine, int32 *endLine)
|
||||
|
||||
lineIndex++;
|
||||
STELine saveLine = *nextLine;
|
||||
if ( (lineIndex > fLines->NumLines()) ||
|
||||
(toOffset < nextLine->offset) ) {
|
||||
if ( lineIndex > fLines->NumLines() ||
|
||||
toOffset < nextLine->offset ) {
|
||||
// the new line comes before the old line start, add a line
|
||||
STELine newLine;
|
||||
newLine.offset = toOffset;
|
||||
newLine.origin = curLine->origin + ascent + descent;
|
||||
newLine.ascent = 0;
|
||||
fLines->InsertLine(&newLine, lineIndex);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// update the exising line
|
||||
nextLine->offset = toOffset;
|
||||
nextLine->origin = curLine->origin + ascent + descent;
|
||||
|
||||
// remove any lines that start before the current line
|
||||
while ( (lineIndex < fLines->NumLines()) &&
|
||||
(toOffset >= ((*fLines)[lineIndex] + 1)->offset) )
|
||||
while ( lineIndex < fLines->NumLines() &&
|
||||
toOffset >= ((*fLines)[lineIndex] + 1)->offset )
|
||||
fLines->RemoveLines(lineIndex + 1);
|
||||
|
||||
nextLine = (*fLines)[lineIndex];
|
||||
@@ -2607,9 +2585,8 @@ BTextView::RecalLineBreaks(int32 *startLine, int32 *endLine)
|
||||
lineIndex + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((lineIndex > 0) && (lineIndex == *startLine))
|
||||
} else {
|
||||
if (lineIndex > 0 && lineIndex == *startLine)
|
||||
*startLine = lineIndex - 1;
|
||||
}
|
||||
}
|
||||
@@ -2705,14 +2682,13 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
done = true;
|
||||
delta++;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// include all trailing spaces and tabs,
|
||||
// but not spaces after tabs
|
||||
if ((theChar != ' ') && (theChar != '\t'))
|
||||
if (theChar != ' ' && theChar != '\t')
|
||||
break;
|
||||
else {
|
||||
if ((theChar == ' ') && (foundTab))
|
||||
if (theChar == ' ' && foundTab)
|
||||
break;
|
||||
else {
|
||||
if (theChar == '\t')
|
||||
@@ -2744,18 +2720,18 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
bool foundNewline = done;
|
||||
done = true;
|
||||
int32 pos = delta - 1;
|
||||
if (((*fText)[offset + pos] != ' ') &&
|
||||
((*fText)[offset + pos] != '\t') &&
|
||||
((*fText)[offset + pos] != '\n'))
|
||||
if ((*fText)[offset + pos] != ' ' &&
|
||||
(*fText)[offset + pos] != '\t' &&
|
||||
(*fText)[offset + pos] != '\n')
|
||||
break;
|
||||
|
||||
strWidth -= (deltaWidth + tabWidth);
|
||||
|
||||
for ( ; ((offset + pos) > offset); pos--) {
|
||||
uchar theChar = (*fText)[offset + pos];
|
||||
if ((theChar != ' ') &&
|
||||
(theChar != '\t') &&
|
||||
(theChar != '\n'))
|
||||
if (theChar != ' ' &&
|
||||
theChar != '\t' &&
|
||||
theChar != '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2765,12 +2741,12 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
|
||||
if (!foundNewline) {
|
||||
for ( ; (offset + delta) < limit; delta++) {
|
||||
if (((*fText)[offset + delta] != ' ') &&
|
||||
((*fText)[offset + delta] != '\t'))
|
||||
if ((*fText)[offset + delta] != ' ' &&
|
||||
(*fText)[offset + delta] != '\t')
|
||||
break;
|
||||
}
|
||||
if ( ((offset + delta) < limit) &&
|
||||
((*fText)[offset + delta] == '\n') )
|
||||
if ( (offset + delta) < limit &&
|
||||
(*fText)[offset + delta] == '\n' )
|
||||
delta++;
|
||||
}
|
||||
// get the ascent and descent of the spaces/tabs
|
||||
@@ -2782,7 +2758,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
|
||||
offset += delta;
|
||||
delta = 0;
|
||||
} while ((offset < limit) && (!done));
|
||||
} while (offset < limit && !done);
|
||||
|
||||
if ((offset - fromOffset) < 1) {
|
||||
// there weren't any words that fit entirely in this line
|
||||
@@ -2881,7 +2857,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
|
||||
long startEraseLine = startLine;
|
||||
STELinePtr line = (*fLines)[startLine];
|
||||
|
||||
if ((erase) && (startOffset != -1)) {
|
||||
if (erase && startOffset != -1) {
|
||||
// erase only to the right of startOffset
|
||||
startEraseLine++;
|
||||
long startErase = startOffset;
|
||||
@@ -2911,7 +2887,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
|
||||
|
||||
MovePenTo(fTextRect.left, line->origin + line->ascent + fTextRect.top);
|
||||
|
||||
if ((erase) && (i >= startEraseLine)) {
|
||||
if (erase && i >= startEraseLine) {
|
||||
eraseRect.top = line->origin + fTextRect.top;
|
||||
eraseRect.bottom = (line + 1)->origin + fTextRect.top;
|
||||
|
||||
@@ -2975,7 +2951,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
|
||||
numChars -= tabChars;
|
||||
tabChars = numChars;
|
||||
numTabs = 0;
|
||||
} while ((foundTab) && (tabChars > 0));
|
||||
} while (foundTab && tabChars > 0);
|
||||
}
|
||||
}
|
||||
line++;
|
||||
@@ -3026,7 +3002,7 @@ BTextView::DragCaret(int32 offset)
|
||||
if (offset != -1) {
|
||||
if (fActive) {
|
||||
// ignore if offset is within active selection
|
||||
if ((offset >= fSelStart) && (offset <= fSelEnd)) {
|
||||
if (offset >= fSelStart && offset <= fSelEnd) {
|
||||
fDragOffset = -1;
|
||||
return;
|
||||
}
|
||||
@@ -3104,7 +3080,7 @@ BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
|
||||
if (dropOffset > TextLength())
|
||||
dropOffset = TextLength();
|
||||
|
||||
void *from;
|
||||
void *from = NULL;
|
||||
inMessage->FindPointer("be:originator", &from);
|
||||
|
||||
bool internalDrop = (from == this && fSelEnd != fSelStart);
|
||||
@@ -3184,16 +3160,22 @@ BTextView::AutoResize(bool doredraw)
|
||||
void
|
||||
BTextView::NewOffscreen(float padding)
|
||||
{
|
||||
if (fOffscreen)
|
||||
if (fOffscreen != NULL)
|
||||
DeleteOffscreen();
|
||||
|
||||
//TODO: Implement
|
||||
/*
|
||||
BRect bitmapRect(0, 0, fTextRect.Width() + padding, fTextRect.Height());
|
||||
fOffscreen = new BBitmap(bitmapRect, fColorSpace, true, false);
|
||||
if (fOffscreen != NULL && fOffscreen->Lock()) {
|
||||
BView *bufferView = new BView(bitmapRect, "buffer view", 0, 0);
|
||||
fOffscreen->AddChild(bufferView);
|
||||
fOffscreen->Unlock();
|
||||
}*/
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
BTextView::DeleteOffscreen()
|
||||
{
|
||||
if (fOffscreen && fOffscreen->Lock()) {
|
||||
if (fOffscreen != NULL && fOffscreen->Lock()) {
|
||||
delete fOffscreen;
|
||||
fOffscreen = NULL;
|
||||
}
|
||||
@@ -3207,8 +3189,7 @@ BTextView::Activate()
|
||||
if (fSelStart != fSelEnd) {
|
||||
if (fSelectable)
|
||||
Highlight(fSelStart, fSelEnd);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (fEditable)
|
||||
InvertCaret();
|
||||
}
|
||||
@@ -3228,8 +3209,7 @@ BTextView::Deactivate()
|
||||
if (fSelStart != fSelEnd) {
|
||||
if (fSelectable)
|
||||
Highlight(fSelStart, fSelEnd);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (fCaretVisible)
|
||||
InvertCaret();
|
||||
}
|
||||
@@ -3260,8 +3240,8 @@ BTextView::CharClassification(int32 offset) const
|
||||
case '_':
|
||||
case '.':
|
||||
case '\0':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case B_TAB:
|
||||
case B_ENTER:
|
||||
case '&':
|
||||
case '*':
|
||||
case '+':
|
||||
@@ -3316,7 +3296,9 @@ BTextView::GetProperty(BMessage *specifier, int32 form,
|
||||
reply->AddInt32("result", fSelStart);
|
||||
reply->AddInt32("result", fSelEnd);
|
||||
reply->AddInt32("error", B_OK);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (strcmp(property, "Text") == 0) {
|
||||
int32 index, range;
|
||||
char *buffer;
|
||||
@@ -3331,7 +3313,9 @@ BTextView::GetProperty(BMessage *specifier, int32 form,
|
||||
reply->AddString("result", buffer);
|
||||
delete buffer;
|
||||
reply->AddInt32("error", B_OK);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (strcmp(property, "text_run_array") == 0)
|
||||
return false;
|
||||
else
|
||||
@@ -3354,8 +3338,8 @@ BTextView::SetProperty(BMessage *specifier, int32 form,
|
||||
reply->AddInt32("error", B_OK);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(property, "Text") == 0) {
|
||||
|
||||
} else if (strcmp(property, "Text") == 0) {
|
||||
int32 index, range;
|
||||
const char *buffer;
|
||||
|
||||
@@ -3371,8 +3355,8 @@ BTextView::SetProperty(BMessage *specifier, int32 form,
|
||||
reply->AddInt32("error", B_OK);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(property, "text_run_array") == 0)
|
||||
|
||||
} else if (strcmp(property, "text_run_array") == 0)
|
||||
return false;
|
||||
|
||||
else
|
||||
@@ -3389,8 +3373,8 @@ BTextView::CountProperties(BMessage *specifier, int32 form,
|
||||
reply->AddInt32("error", B_OK);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user