Fixed a crash when undoing an "internal text drop", some cleanups.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8091 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2003, OpenBeOS
|
||||
// Copyright (c) 2001-2004, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
@@ -20,7 +20,7 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: TextView.cpp
|
||||
// Authors: Hiroshi Lockheimer (TextView is based on his STEEngine)
|
||||
// Authors: Hiroshi Lockheimer (BTextView is based on his STEEngine)
|
||||
// Marc Flerackers ([email protected])
|
||||
// Stefano Ceccherini ([email protected])
|
||||
// Description: BTextView displays and manages styled text.
|
||||
@@ -87,6 +87,7 @@ enum {
|
||||
B_OTHER_CHARACTER
|
||||
} separatorCharacters;
|
||||
|
||||
|
||||
// _BTextTrackState_ class -----------------------------------------------------
|
||||
class _BTextTrackState_ {
|
||||
|
||||
@@ -103,7 +104,7 @@ public:
|
||||
|
||||
// Globals ---------------------------------------------------------------------
|
||||
static property_info
|
||||
prop_list[] = {
|
||||
sPropertyList[] = {
|
||||
{
|
||||
"Selection",
|
||||
{ B_GET_PROPERTY, 0 },
|
||||
@@ -157,7 +158,7 @@ prop_list[] = {
|
||||
};
|
||||
|
||||
|
||||
// Initialized/finalized by init/fini_interface_kit ?
|
||||
// Initialized/finalized by init/fini_interface_kit
|
||||
_BWidthBuffer_* BTextView::sWidths = NULL;
|
||||
sem_id BTextView::sWidthSem = B_BAD_SEM_ID;
|
||||
int32 BTextView::sWidthAtom = 0;
|
||||
@@ -369,14 +370,16 @@ BTextView::Archive(BMessage *data, bool deep) const
|
||||
data->AddData("_dis_ch", B_RAW_TYPE, fDisallowedChars->Items(),
|
||||
fDisallowedChars->CountItems() * sizeof(int32));
|
||||
|
||||
ssize_t runSize = 0;
|
||||
int32 runSize = 0;
|
||||
text_run_array *runArray = RunArray(0, TextLength());
|
||||
|
||||
void *flattened = FlattenRunArray(runArray, (int32*)&runSize);
|
||||
void *flattened = FlattenRunArray(runArray, &runSize);
|
||||
if (flattened != NULL) {
|
||||
data->AddData("_runs", B_RAW_TYPE, flattened, runSize);
|
||||
free(flattened);
|
||||
}
|
||||
} else
|
||||
err = B_NO_MEMORY;
|
||||
|
||||
free(runArray);
|
||||
|
||||
return err;
|
||||
@@ -762,7 +765,7 @@ BTextView::MessageReceived(BMessage *message)
|
||||
case B_GET_PROPERTY:
|
||||
case B_COUNT_PROPERTIES:
|
||||
{
|
||||
BPropertyInfo propInfo(prop_list);
|
||||
BPropertyInfo propInfo(sPropertyList);
|
||||
BMessage specifier;
|
||||
const char *property;
|
||||
|
||||
@@ -826,7 +829,7 @@ BTextView::ResolveSpecifier(BMessage *message, int32 index,
|
||||
const char *property)
|
||||
{
|
||||
CALLED();
|
||||
BPropertyInfo propInfo(prop_list);
|
||||
BPropertyInfo propInfo(sPropertyList);
|
||||
BHandler *target = NULL;
|
||||
|
||||
switch (propInfo.FindMatch(message, 0, specifier, form, property)) {
|
||||
@@ -865,7 +868,7 @@ BTextView::GetSupportedSuites(BMessage *data)
|
||||
if (err != B_OK)
|
||||
return err;
|
||||
|
||||
BPropertyInfo prop_info(prop_list);
|
||||
BPropertyInfo prop_info(sPropertyList);
|
||||
err = data->AddFlat("messages", &prop_info);
|
||||
|
||||
if (err != B_OK)
|
||||
@@ -1131,6 +1134,9 @@ void
|
||||
BTextView::GetText(int32 offset, int32 length, char *buffer) const
|
||||
{
|
||||
CALLED();
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
int32 textLen = fText->Length();
|
||||
if (offset < 0 || offset > (textLen - 1)) {
|
||||
buffer[0] = '\0';
|
||||
@@ -1466,7 +1472,7 @@ BTextView::GetFontAndColor(BFont *outFont, uint32 *outMode,
|
||||
// TODO fill in outMode and outEqColor
|
||||
fStyles->GetStyle(fSelStart, outFont, outColor);
|
||||
|
||||
// XXX: This is a hack to make beshare work.
|
||||
// TODO: This is a hack to make beshare work.
|
||||
// We should use _BStyleBuffer_::ContinuousGetStyle() here.
|
||||
*outMode = doSize;
|
||||
}
|
||||
@@ -1509,20 +1515,20 @@ BTextView::RunArray(int32 startOffset, int32 endOffset,
|
||||
int32 *outSize) const
|
||||
{
|
||||
CALLED();
|
||||
STEStyleRangePtr result = fStyles->GetStyleRange(startOffset, endOffset - 1);
|
||||
STEStyleRangePtr styleRange = fStyles->GetStyleRange(startOffset, endOffset - 1);
|
||||
|
||||
if (result == NULL)
|
||||
if (styleRange == NULL)
|
||||
return NULL;
|
||||
|
||||
text_run_array *res = (text_run_array *)malloc(sizeof(int32) +
|
||||
(sizeof(text_run) * result->count));
|
||||
(sizeof(text_run) * styleRange->count));
|
||||
|
||||
res->count = result->count;
|
||||
res->count = styleRange->count;
|
||||
|
||||
for (int32 i = 0; i < res->count; i++) {
|
||||
res->runs[i].offset = result->runs[i].offset;
|
||||
res->runs[i].font = &result->runs[i].style.font;
|
||||
res->runs[i].color = result->runs[i].style.color;
|
||||
res->runs[i].offset = styleRange->runs[i].offset;
|
||||
res->runs[i].font = &styleRange->runs[i].style.font;
|
||||
res->runs[i].color = styleRange->runs[i].style.color;
|
||||
}
|
||||
|
||||
if (outSize != NULL)
|
||||
@@ -1565,13 +1571,14 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
|
||||
|
||||
result.y += height;
|
||||
height = ascent + descent;
|
||||
|
||||
} else {
|
||||
int32 offset = line->offset;
|
||||
int32 length = inOffset - line->offset;
|
||||
int32 numChars = length;
|
||||
bool foundTab = false;
|
||||
do {
|
||||
foundTab = fText->FindChar('\t', offset, &numChars);
|
||||
foundTab = fText->FindChar(B_TAB, offset, &numChars);
|
||||
|
||||
result.x += StyledWidth(offset, numChars);
|
||||
|
||||
@@ -1648,7 +1655,7 @@ BTextView::OffsetAt(BPoint point) const
|
||||
}
|
||||
|
||||
// any more tabs?
|
||||
foundTab = fText->FindChar('\t', offset, &numChars);
|
||||
foundTab = fText->FindChar(B_TAB, offset, &numChars);
|
||||
|
||||
delta = numChars / 2;
|
||||
delta = (delta < 1) ? 1 : delta;
|
||||
@@ -1716,7 +1723,7 @@ BTextView::OffsetAt(BPoint point) const
|
||||
|
||||
// special case: return the offset preceding any spaces that
|
||||
// aren't at the end of the buffer
|
||||
if (offset != fText->Length() && (*fText)[offset - 1] == ' ')
|
||||
if (offset != fText->Length() && (*fText)[offset - 1] == B_SPACE)
|
||||
return --offset;
|
||||
}
|
||||
|
||||
@@ -2108,7 +2115,11 @@ void
|
||||
BTextView::SetColorSpace(color_space colors)
|
||||
{
|
||||
CALLED();
|
||||
fColorSpace = colors;
|
||||
if (colors != fColorSpace && fOffscreen) {
|
||||
fColorSpace = colors;
|
||||
DeleteOffscreen();
|
||||
NewOffscreen();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
color_space
|
||||
@@ -2188,7 +2199,6 @@ BTextView::AllAttached()
|
||||
{
|
||||
CALLED();
|
||||
BView::AllAttached();
|
||||
printf("selstart %ld, selend %ld\n", fSelStart, fSelEnd);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
@@ -2206,6 +2216,10 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize)
|
||||
sizeof(flattened_text_run_array);
|
||||
|
||||
flattened_text_run_array *array = (flattened_text_run_array *)malloc(size);
|
||||
if (array == NULL) {
|
||||
*outSize = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array->magic[0] = 0x41;
|
||||
array->magic[1] = 0x6c;
|
||||
@@ -2257,6 +2271,10 @@ 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);
|
||||
if (run_array == NULL) {
|
||||
*outSize = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
run_array->count = array->count;
|
||||
|
||||
@@ -2596,7 +2614,7 @@ BTextView::HandleAlphaKey(const char *bytes, int32 numBytes)
|
||||
const char *text = Text();
|
||||
|
||||
while (*(text + offset) != '\0' &&
|
||||
*(text + offset) == '\t' || *(text + offset) == ' ')
|
||||
*(text + offset) == B_TAB || *(text + offset) == B_SPACE)
|
||||
offset++;
|
||||
|
||||
if (start != offset)
|
||||
@@ -2832,13 +2850,13 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
} else {
|
||||
// include all trailing spaces and tabs,
|
||||
// but not spaces after tabs
|
||||
if (theChar != ' ' && theChar != '\t')
|
||||
if (theChar != B_SPACE && theChar != B_TAB)
|
||||
break;
|
||||
else {
|
||||
if (theChar == ' ' && foundTab)
|
||||
if (theChar == B_SPACE && foundTab)
|
||||
break;
|
||||
else {
|
||||
if (theChar == '\t')
|
||||
if (theChar == B_TAB)
|
||||
foundTab = true;
|
||||
}
|
||||
}
|
||||
@@ -2853,7 +2871,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
tabWidth = 0.0;
|
||||
else {
|
||||
int32 tabCount = 0;
|
||||
for (int32 i = delta - 1; (*fText)[offset + i] == '\t'; i--)
|
||||
for (int32 i = delta - 1; (*fText)[offset + i] == B_TAB; i--)
|
||||
tabCount++;
|
||||
|
||||
tabWidth = fTabWidth - fmod(strWidth, fTabWidth);
|
||||
@@ -2867,8 +2885,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
bool foundNewline = done;
|
||||
done = true;
|
||||
int32 pos = delta - 1;
|
||||
if ((*fText)[offset + pos] != ' ' &&
|
||||
(*fText)[offset + pos] != '\t' &&
|
||||
if ((*fText)[offset + pos] != B_SPACE &&
|
||||
(*fText)[offset + pos] != B_TAB &&
|
||||
(*fText)[offset + pos] != '\n')
|
||||
break;
|
||||
|
||||
@@ -2876,8 +2894,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
|
||||
|
||||
for ( ; ((offset + pos) > offset); pos--) {
|
||||
uchar theChar = (*fText)[offset + pos];
|
||||
if (theChar != ' ' &&
|
||||
theChar != '\t' &&
|
||||
if (theChar != B_SPACE &&
|
||||
theChar != B_TAB &&
|
||||
theChar != '\n')
|
||||
break;
|
||||
}
|
||||
@@ -2888,8 +2906,8 @@ 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] != B_SPACE &&
|
||||
(*fText)[offset + delta] != B_TAB)
|
||||
break;
|
||||
}
|
||||
if ( (offset + delta) < limit &&
|
||||
@@ -3012,7 +3030,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
|
||||
startEraseLine++;
|
||||
long startErase = startOffset;
|
||||
if (startErase > line->offset) {
|
||||
for ( ; ((*fText)[startErase] != ' ') && ((*fText)[startErase] != '\t'); startErase--) {
|
||||
for ( ; ((*fText)[startErase] != B_SPACE) && ((*fText)[startErase] != B_TAB); startErase--) {
|
||||
if (startErase <= line->offset)
|
||||
break;
|
||||
}
|
||||
@@ -3028,6 +3046,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
|
||||
|
||||
eraseRect = clipRect;
|
||||
}
|
||||
|
||||
for (long i = startLine; i <= endLine; i++) {
|
||||
long length = (line + 1)->offset - line->offset;
|
||||
// DrawString() chokes if you draw a newline
|
||||
@@ -3063,10 +3082,10 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
|
||||
//if (style->underline)
|
||||
// startPenLoc = PenLocation();
|
||||
|
||||
foundTab = fText->FindChar('\t', offset, &tabChars);
|
||||
foundTab = fText->FindChar(B_TAB, offset, &tabChars);
|
||||
if (foundTab) {
|
||||
for (numTabs = 0; (tabChars + numTabs) < numChars; numTabs++) {
|
||||
if ((*fText)[offset + tabChars + numTabs] != '\t')
|
||||
if ((*fText)[offset + tabChars + numTabs] != B_TAB)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3201,7 +3220,7 @@ void
|
||||
BTextView::InitiateDrag()
|
||||
{
|
||||
CALLED();
|
||||
BMessage *drag = new BMessage();
|
||||
BMessage *drag = new BMessage(B_MIME_DATA);
|
||||
BBitmap *dragBitmap = NULL;
|
||||
BPoint bitmapPoint;
|
||||
BHandler *dragHandler = NULL;
|
||||
@@ -3228,6 +3247,12 @@ bool
|
||||
BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
void *from = NULL;
|
||||
inMessage->FindPointer("be:originator", &from);
|
||||
|
||||
bool internalDrop = (from == this && fSelEnd != fSelStart);
|
||||
|
||||
if (fActive)
|
||||
SetViewCursor(B_CURSOR_I_BEAM);
|
||||
|
||||
@@ -3238,12 +3263,7 @@ BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
|
||||
long dropOffset = OffsetAt(where);
|
||||
if (dropOffset > TextLength())
|
||||
dropOffset = TextLength();
|
||||
|
||||
void *from = NULL;
|
||||
inMessage->FindPointer("be:originator", &from);
|
||||
|
||||
bool internalDrop = (from == this && fSelEnd != fSelStart);
|
||||
|
||||
|
||||
// if this view initiated the drag, move instead of copy
|
||||
if (internalDrop) {
|
||||
// dropping onto itself?
|
||||
@@ -3266,8 +3286,11 @@ BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
|
||||
fUndo = new _BDropUndoBuffer_(this, text, dataLen, runArray, runLen, dropOffset, internalDrop);
|
||||
}
|
||||
|
||||
if (internalDrop)
|
||||
if (internalDrop) {
|
||||
if (dropOffset > fSelEnd)
|
||||
dropOffset -= dataLen;
|
||||
Delete();
|
||||
}
|
||||
|
||||
Insert(dropOffset, text, dataLen, runArray);
|
||||
}
|
||||
@@ -3571,8 +3594,10 @@ void
|
||||
BTextView::LockWidthBuffer()
|
||||
{
|
||||
CALLED();
|
||||
if (atomic_add(&sWidthAtom, 1) > 0)
|
||||
acquire_sem(sWidthSem);
|
||||
if (atomic_add(&sWidthAtom, 1) > 0) {
|
||||
while (acquire_sem(sWidthSem) == B_INTERRUPTED)
|
||||
;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user