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:
Stefano Ceccherini
2004-06-21 12:56:46 +00:00
parent 4f4f12888d
commit 7889e7c9ed
4 changed files with 86 additions and 52 deletions
@@ -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 // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -49,7 +49,8 @@ _BTextGapBuffer_::_BTextGapBuffer_()
fGapIndex(fItemCount), fGapIndex(fItemCount),
fGapCount(fBufferCount - fGapIndex), fGapCount(fBufferCount - fGapIndex),
fScratchBuffer(NULL), fScratchBuffer(NULL),
fScratchSize(0) fScratchSize(0),
fPasswordMode(false)
{ {
fBuffer = (char *)malloc(fExtraCount + fItemCount); fBuffer = (char *)malloc(fExtraCount + fItemCount);
fScratchBuffer = (char*)malloc(0); fScratchBuffer = (char*)malloc(0);
@@ -199,8 +200,8 @@ _BTextGapBuffer_::GetString(int32 fromOffset, int32 numChars)
result = fBuffer + fromOffset; result = fBuffer + fromOffset;
if (!isStartBeforeGap) if (!isStartBeforeGap)
result += fGapCount; result += fGapCount;
}
else { } else {
if (fScratchSize < numChars) { if (fScratchSize < numChars) {
fScratchBuffer = (char *)realloc(fScratchBuffer, numChars); fScratchBuffer = (char *)realloc(fScratchBuffer, numChars);
fScratchSize = numChars; fScratchSize = numChars;
@@ -254,12 +255,13 @@ _BTextGapBuffer_::RealCharAt(int32 offset) const
bool bool
_BTextGapBuffer_::PasswordMode() const _BTextGapBuffer_::PasswordMode() const
{ {
return false; return fPasswordMode;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
_BTextGapBuffer_::SetPasswordMode(bool state) _BTextGapBuffer_::SetPasswordMode(bool state)
{ {
fPasswordMode = state;
} }
/* /*
* $Log $ * $Log $
@@ -83,6 +83,7 @@ protected:
int32 fGapCount; // gap count int32 fGapCount; // gap count
char *fScratchBuffer; // for GetString char *fScratchBuffer; // for GetString
int32 fScratchSize; // scratch size int32 fScratchSize; // scratch size
bool fPasswordMode;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline int32 inline int32
+72 -47
View File
@@ -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 // Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"), // copy of this software and associated documentation files (the "Software"),
@@ -20,7 +20,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
// //
// File Name: TextView.cpp // 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]) // Marc Flerackers ([email protected])
// Stefano Ceccherini ([email protected]) // Stefano Ceccherini ([email protected])
// Description: BTextView displays and manages styled text. // Description: BTextView displays and manages styled text.
@@ -87,6 +87,7 @@ enum {
B_OTHER_CHARACTER B_OTHER_CHARACTER
} separatorCharacters; } separatorCharacters;
// _BTextTrackState_ class ----------------------------------------------------- // _BTextTrackState_ class -----------------------------------------------------
class _BTextTrackState_ { class _BTextTrackState_ {
@@ -103,7 +104,7 @@ public:
// Globals --------------------------------------------------------------------- // Globals ---------------------------------------------------------------------
static property_info static property_info
prop_list[] = { sPropertyList[] = {
{ {
"Selection", "Selection",
{ B_GET_PROPERTY, 0 }, { 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; _BWidthBuffer_* BTextView::sWidths = NULL;
sem_id BTextView::sWidthSem = B_BAD_SEM_ID; sem_id BTextView::sWidthSem = B_BAD_SEM_ID;
int32 BTextView::sWidthAtom = 0; int32 BTextView::sWidthAtom = 0;
@@ -369,14 +370,16 @@ BTextView::Archive(BMessage *data, bool deep) const
data->AddData("_dis_ch", B_RAW_TYPE, fDisallowedChars->Items(), data->AddData("_dis_ch", B_RAW_TYPE, fDisallowedChars->Items(),
fDisallowedChars->CountItems() * sizeof(int32)); fDisallowedChars->CountItems() * sizeof(int32));
ssize_t runSize = 0; int32 runSize = 0;
text_run_array *runArray = RunArray(0, TextLength()); text_run_array *runArray = RunArray(0, TextLength());
void *flattened = FlattenRunArray(runArray, (int32*)&runSize); void *flattened = FlattenRunArray(runArray, &runSize);
if (flattened != NULL) { if (flattened != NULL) {
data->AddData("_runs", B_RAW_TYPE, flattened, runSize); data->AddData("_runs", B_RAW_TYPE, flattened, runSize);
free(flattened); free(flattened);
} } else
err = B_NO_MEMORY;
free(runArray); free(runArray);
return err; return err;
@@ -762,7 +765,7 @@ BTextView::MessageReceived(BMessage *message)
case B_GET_PROPERTY: case B_GET_PROPERTY:
case B_COUNT_PROPERTIES: case B_COUNT_PROPERTIES:
{ {
BPropertyInfo propInfo(prop_list); BPropertyInfo propInfo(sPropertyList);
BMessage specifier; BMessage specifier;
const char *property; const char *property;
@@ -826,7 +829,7 @@ BTextView::ResolveSpecifier(BMessage *message, int32 index,
const char *property) const char *property)
{ {
CALLED(); CALLED();
BPropertyInfo propInfo(prop_list); BPropertyInfo propInfo(sPropertyList);
BHandler *target = NULL; BHandler *target = NULL;
switch (propInfo.FindMatch(message, 0, specifier, form, property)) { switch (propInfo.FindMatch(message, 0, specifier, form, property)) {
@@ -865,7 +868,7 @@ BTextView::GetSupportedSuites(BMessage *data)
if (err != B_OK) if (err != B_OK)
return err; return err;
BPropertyInfo prop_info(prop_list); BPropertyInfo prop_info(sPropertyList);
err = data->AddFlat("messages", &prop_info); err = data->AddFlat("messages", &prop_info);
if (err != B_OK) if (err != B_OK)
@@ -1131,6 +1134,9 @@ void
BTextView::GetText(int32 offset, int32 length, char *buffer) const BTextView::GetText(int32 offset, int32 length, char *buffer) const
{ {
CALLED(); CALLED();
if (buffer == NULL)
return;
int32 textLen = fText->Length(); int32 textLen = fText->Length();
if (offset < 0 || offset > (textLen - 1)) { if (offset < 0 || offset > (textLen - 1)) {
buffer[0] = '\0'; buffer[0] = '\0';
@@ -1466,7 +1472,7 @@ BTextView::GetFontAndColor(BFont *outFont, uint32 *outMode,
// TODO fill in outMode and outEqColor // TODO fill in outMode and outEqColor
fStyles->GetStyle(fSelStart, outFont, outColor); 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. // We should use _BStyleBuffer_::ContinuousGetStyle() here.
*outMode = doSize; *outMode = doSize;
} }
@@ -1509,20 +1515,20 @@ BTextView::RunArray(int32 startOffset, int32 endOffset,
int32 *outSize) const int32 *outSize) const
{ {
CALLED(); CALLED();
STEStyleRangePtr result = fStyles->GetStyleRange(startOffset, endOffset - 1); STEStyleRangePtr styleRange = fStyles->GetStyleRange(startOffset, endOffset - 1);
if (result == NULL) if (styleRange == NULL)
return 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)); (sizeof(text_run) * styleRange->count));
res->count = result->count; res->count = styleRange->count;
for (int32 i = 0; i < res->count; i++) { for (int32 i = 0; i < res->count; i++) {
res->runs[i].offset = result->runs[i].offset; res->runs[i].offset = styleRange->runs[i].offset;
res->runs[i].font = &result->runs[i].style.font; res->runs[i].font = &styleRange->runs[i].style.font;
res->runs[i].color = result->runs[i].style.color; res->runs[i].color = styleRange->runs[i].style.color;
} }
if (outSize != NULL) if (outSize != NULL)
@@ -1565,13 +1571,14 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
result.y += height; result.y += height;
height = ascent + descent; height = ascent + descent;
} else { } else {
int32 offset = line->offset; int32 offset = line->offset;
int32 length = inOffset - line->offset; int32 length = inOffset - line->offset;
int32 numChars = length; int32 numChars = length;
bool foundTab = false; bool foundTab = false;
do { do {
foundTab = fText->FindChar('\t', offset, &numChars); foundTab = fText->FindChar(B_TAB, offset, &numChars);
result.x += StyledWidth(offset, numChars); result.x += StyledWidth(offset, numChars);
@@ -1648,7 +1655,7 @@ BTextView::OffsetAt(BPoint point) const
} }
// any more tabs? // any more tabs?
foundTab = fText->FindChar('\t', offset, &numChars); foundTab = fText->FindChar(B_TAB, offset, &numChars);
delta = numChars / 2; delta = numChars / 2;
delta = (delta < 1) ? 1 : delta; delta = (delta < 1) ? 1 : delta;
@@ -1716,7 +1723,7 @@ BTextView::OffsetAt(BPoint point) const
// special case: return the offset preceding any spaces that // special case: return the offset preceding any spaces that
// aren't at the end of the buffer // 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; return --offset;
} }
@@ -2108,7 +2115,11 @@ void
BTextView::SetColorSpace(color_space colors) BTextView::SetColorSpace(color_space colors)
{ {
CALLED(); CALLED();
fColorSpace = colors; if (colors != fColorSpace && fOffscreen) {
fColorSpace = colors;
DeleteOffscreen();
NewOffscreen();
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
color_space color_space
@@ -2188,7 +2199,6 @@ BTextView::AllAttached()
{ {
CALLED(); CALLED();
BView::AllAttached(); BView::AllAttached();
printf("selstart %ld, selend %ld\n", fSelStart, fSelEnd);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -2206,6 +2216,10 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize)
sizeof(flattened_text_run_array); 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);
if (array == NULL) {
*outSize = 0;
return NULL;
}
array->magic[0] = 0x41; array->magic[0] = 0x41;
array->magic[1] = 0x6c; 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); 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);
if (run_array == NULL) {
*outSize = 0;
return NULL;
}
run_array->count = array->count; run_array->count = array->count;
@@ -2596,7 +2614,7 @@ BTextView::HandleAlphaKey(const char *bytes, int32 numBytes)
const char *text = Text(); const char *text = Text();
while (*(text + offset) != '\0' && while (*(text + offset) != '\0' &&
*(text + offset) == '\t' || *(text + offset) == ' ') *(text + offset) == B_TAB || *(text + offset) == B_SPACE)
offset++; offset++;
if (start != offset) if (start != offset)
@@ -2832,13 +2850,13 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
} else { } else {
// include all trailing spaces and tabs, // include all trailing spaces and tabs,
// but not spaces after tabs // but not spaces after tabs
if (theChar != ' ' && theChar != '\t') if (theChar != B_SPACE && theChar != B_TAB)
break; break;
else { else {
if (theChar == ' ' && foundTab) if (theChar == B_SPACE && foundTab)
break; break;
else { else {
if (theChar == '\t') if (theChar == B_TAB)
foundTab = true; foundTab = true;
} }
} }
@@ -2853,7 +2871,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
tabWidth = 0.0; tabWidth = 0.0;
else { else {
int32 tabCount = 0; 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++; tabCount++;
tabWidth = fTabWidth - fmod(strWidth, fTabWidth); tabWidth = fTabWidth - fmod(strWidth, fTabWidth);
@@ -2867,8 +2885,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
bool foundNewline = done; bool foundNewline = done;
done = true; done = true;
int32 pos = delta - 1; int32 pos = delta - 1;
if ((*fText)[offset + pos] != ' ' && if ((*fText)[offset + pos] != B_SPACE &&
(*fText)[offset + pos] != '\t' && (*fText)[offset + pos] != B_TAB &&
(*fText)[offset + pos] != '\n') (*fText)[offset + pos] != '\n')
break; break;
@@ -2876,8 +2894,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
for ( ; ((offset + pos) > offset); pos--) { for ( ; ((offset + pos) > offset); pos--) {
uchar theChar = (*fText)[offset + pos]; uchar theChar = (*fText)[offset + pos];
if (theChar != ' ' && if (theChar != B_SPACE &&
theChar != '\t' && theChar != B_TAB &&
theChar != '\n') theChar != '\n')
break; break;
} }
@@ -2888,8 +2906,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
if (!foundNewline) { if (!foundNewline) {
for ( ; (offset + delta) < limit; delta++) { for ( ; (offset + delta) < limit; delta++) {
if ((*fText)[offset + delta] != ' ' && if ((*fText)[offset + delta] != B_SPACE &&
(*fText)[offset + delta] != '\t') (*fText)[offset + delta] != B_TAB)
break; break;
} }
if ( (offset + delta) < limit && if ( (offset + delta) < limit &&
@@ -3012,7 +3030,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
startEraseLine++; startEraseLine++;
long startErase = startOffset; long startErase = startOffset;
if (startErase > line->offset) { 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) if (startErase <= line->offset)
break; break;
} }
@@ -3028,6 +3046,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
eraseRect = clipRect; eraseRect = clipRect;
} }
for (long i = startLine; i <= endLine; i++) { for (long i = startLine; i <= endLine; i++) {
long length = (line + 1)->offset - line->offset; long length = (line + 1)->offset - line->offset;
// DrawString() chokes if you draw a newline // DrawString() chokes if you draw a newline
@@ -3063,10 +3082,10 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
//if (style->underline) //if (style->underline)
// startPenLoc = PenLocation(); // startPenLoc = PenLocation();
foundTab = fText->FindChar('\t', offset, &tabChars); foundTab = fText->FindChar(B_TAB, offset, &tabChars);
if (foundTab) { if (foundTab) {
for (numTabs = 0; (tabChars + numTabs) < numChars; numTabs++) { for (numTabs = 0; (tabChars + numTabs) < numChars; numTabs++) {
if ((*fText)[offset + tabChars + numTabs] != '\t') if ((*fText)[offset + tabChars + numTabs] != B_TAB)
break; break;
} }
} }
@@ -3201,7 +3220,7 @@ void
BTextView::InitiateDrag() BTextView::InitiateDrag()
{ {
CALLED(); CALLED();
BMessage *drag = new BMessage(); BMessage *drag = new BMessage(B_MIME_DATA);
BBitmap *dragBitmap = NULL; BBitmap *dragBitmap = NULL;
BPoint bitmapPoint; BPoint bitmapPoint;
BHandler *dragHandler = NULL; BHandler *dragHandler = NULL;
@@ -3228,6 +3247,12 @@ bool
BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset) BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
{ {
CALLED(); CALLED();
void *from = NULL;
inMessage->FindPointer("be:originator", &from);
bool internalDrop = (from == this && fSelEnd != fSelStart);
if (fActive) if (fActive)
SetViewCursor(B_CURSOR_I_BEAM); SetViewCursor(B_CURSOR_I_BEAM);
@@ -3238,12 +3263,7 @@ BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
long dropOffset = OffsetAt(where); long dropOffset = OffsetAt(where);
if (dropOffset > TextLength()) if (dropOffset > TextLength())
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 this view initiated the drag, move instead of copy
if (internalDrop) { if (internalDrop) {
// dropping onto itself? // 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); fUndo = new _BDropUndoBuffer_(this, text, dataLen, runArray, runLen, dropOffset, internalDrop);
} }
if (internalDrop) if (internalDrop) {
if (dropOffset > fSelEnd)
dropOffset -= dataLen;
Delete(); Delete();
}
Insert(dropOffset, text, dataLen, runArray); Insert(dropOffset, text, dataLen, runArray);
} }
@@ -3571,8 +3594,10 @@ void
BTextView::LockWidthBuffer() BTextView::LockWidthBuffer()
{ {
CALLED(); CALLED();
if (atomic_add(&sWidthAtom, 1) > 0) if (atomic_add(&sWidthAtom, 1) > 0) {
acquire_sem(sWidthSem); while (acquire_sem(sWidthSem) == B_INTERRUPTED)
;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -38,6 +38,8 @@
#include "UndoBuffer.h" #include "UndoBuffer.h"
// TODO: document properly this file
// ******** _BUndoBuffer_ ******* // ******** _BUndoBuffer_ *******
_BUndoBuffer_::_BUndoBuffer_(BTextView *textView, undo_state state) _BUndoBuffer_::_BUndoBuffer_(BTextView *textView, undo_state state)
: :
@@ -223,6 +225,9 @@ _BDropUndoBuffer_::_BDropUndoBuffer_(BTextView *textView, char const *text, int3
fDropRunArrayLength = runArrayLen; fDropRunArrayLength = runArrayLen;
memcpy(fDropRunArray, runArray, runArrayLen); memcpy(fDropRunArray, runArray, runArrayLen);
} }
if (fInternalDrop && fDropLocation >= fEnd)
fDropLocation -= fDropTextLength;
} }
@@ -371,6 +376,7 @@ _BTypingUndoBuffer_::BackwardErase()
void void
_BTypingUndoBuffer_::ForwardErase() _BTypingUndoBuffer_::ForwardErase()
{ {
// TODO: Cleanup
int32 start, end; int32 start, end;
fTextView->GetSelection(&start, &end); fTextView->GetSelection(&start, &end);