- Fixed text pasting

- Fixed text moving
- Almost completely implemented Undo capabilities
- in BTextView::GetSupportedSuites(BMessage *data): added the suites name
- fixed BTextView::Insert(int32, const char *, int32, const text_run_array *), it didn't
  take offset into account
- undo is disabled by default (even if the BeBook says the opposite)
- added B_SELECT_ALL message handler
- now it doesn't select anything if the object isn't selectable
- drag message is now filled in BTextView::GetDragMessage() as it should, and not in
  BTextView::InitiateDrag()
- changed all deprecated SetCursor() calls to SetViewCursor()
- added some NormalizeFont() calls, while trying to fix the multi-byte insertion bug


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5009 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2003-10-13 14:38:43 +00:00
parent 2d6751a062
commit b032f97253
3 changed files with 513 additions and 153 deletions
+238 -141
View File
@@ -28,6 +28,7 @@
// System Includes ------------------------------------------------------------- // System Includes -------------------------------------------------------------
#include <Application.h> #include <Application.h>
#include <Bitmap.h>
#include <Clipboard.h> #include <Clipboard.h>
#include <Errors.h> #include <Errors.h>
#include <Message.h> #include <Message.h>
@@ -37,17 +38,15 @@
#include <TextView.h> #include <TextView.h>
#include <Window.h> #include <Window.h>
#include "TextGapBuffer.h"
#include "LineBuffer.h"
#include "StyleBuffer.h"
#include "UndoBuffer.h"
//#include <CRTDBG.H> //#include <CRTDBG.H>
// Project Includes ------------------------------------------------------------ // Project Includes ------------------------------------------------------------
// Local Includes -------------------------------------------------------------- // Local Includes --------------------------------------------------------------
#include "LineBuffer.h"
#include "StyleBuffer.h"
#include "TextGapBuffer.h"
#include "UndoBuffer.h"
// Local Defines --------------------------------------------------------------- // Local Defines ---------------------------------------------------------------
@@ -333,13 +332,15 @@ BTextView::AttachedToWindow()
fDragOffset = -1; fDragOffset = -1;
fActive = false; fActive = false;
Window()->SetPulseRate(50000);
Refresh(0, LONG_MAX, true, false); Refresh(0, LONG_MAX, true, false);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
BTextView::DetachedFromWindow() BTextView::DetachedFromWindow()
{ {
//TODO: if cursor in bounds, reset it to B_HAND_CURSOR BView::DetachedFromWindow();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -366,7 +367,7 @@ void
BTextView::MouseDown(BPoint where) BTextView::MouseDown(BPoint where)
{ {
// should we even bother? // should we even bother?
if ((!fEditable) && (!fSelectable)) if (!fEditable && !fSelectable)
return; return;
if (!IsFocus()) { if (!IsFocus()) {
@@ -378,8 +379,8 @@ BTextView::MouseDown(BPoint where)
if (fCaretVisible) if (fCaretVisible)
InvertCaret(); InvertCaret();
int32 mouseOffset = OffsetAt(where); int32 mouseOffset = OffsetAt(where);
bool shiftDown = modifiers() & B_SHIFT_KEY; bool shiftDown = modifiers() & B_SHIFT_KEY;
// should we initiate a drag? // should we initiate a drag?
if ((fSelStart != fSelEnd) && (!shiftDown)) { if ((fSelStart != fSelEnd) && (!shiftDown)) {
@@ -407,8 +408,7 @@ BTextView::MouseDown(BPoint where)
// triple click // triple click
fClickCount = 0; fClickCount = 0;
fClickTime = 0; fClickTime = 0;
} } else {
else {
// double click // double click
fClickCount = 2; fClickCount = 2;
fClickTime = system_time(); fClickTime = system_time();
@@ -510,6 +510,7 @@ BTextView::MouseDown(BPoint where)
void void
BTextView::MouseUp(BPoint where) BTextView::MouseUp(BPoint where)
{ {
PerformMouseUp(where);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -518,7 +519,7 @@ BTextView::MouseMoved(BPoint where, uint32 code, const BMessage *message)
switch (code) { switch (code) {
case B_ENTERED_VIEW: case B_ENTERED_VIEW:
if ((fActive) && (message == NULL)) if ((fActive) && (message == NULL))
be_app->SetCursor(B_I_BEAM_CURSOR); SetViewCursor(B_CURSOR_I_BEAM);
break; break;
case B_INSIDE_VIEW: case B_INSIDE_VIEW:
@@ -531,7 +532,7 @@ BTextView::MouseMoved(BPoint where, uint32 code, const BMessage *message)
case B_EXITED_VIEW: case B_EXITED_VIEW:
DragCaret(-1); DragCaret(-1);
if (fActive) if (fActive)
be_app->SetCursor(B_HAND_CURSOR); SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
break; break;
default: default:
@@ -560,13 +561,15 @@ BTextView::KeyDown(const char *bytes, int32 numBytes)
{ {
if (!fEditable) if (!fEditable)
return; return;
const char keyPressed = bytes[0];
// hide the cursor and caret // hide the cursor and caret
be_app->ObscureCursor(); be_app->ObscureCursor();
if (fCaretVisible) if (fCaretVisible)
InvertCaret(); InvertCaret();
switch (bytes[0]) { switch (keyPressed) {
case B_BACKSPACE: case B_BACKSPACE:
HandleBackspace(); HandleBackspace();
break; break;
@@ -575,7 +578,7 @@ BTextView::KeyDown(const char *bytes, int32 numBytes)
case B_RIGHT_ARROW: case B_RIGHT_ARROW:
case B_UP_ARROW: case B_UP_ARROW:
case B_DOWN_ARROW: case B_DOWN_ARROW:
HandleArrowKey(bytes[0]); HandleArrowKey(keyPressed);
break; break;
case B_DELETE: case B_DELETE:
@@ -586,7 +589,7 @@ BTextView::KeyDown(const char *bytes, int32 numBytes)
case B_END: case B_END:
case B_PAGE_UP: case B_PAGE_UP:
case B_PAGE_DOWN: case B_PAGE_DOWN:
HandlePageKey(bytes[0]); HandlePageKey(keyPressed);
break; break;
case B_ESCAPE: case B_ESCAPE:
@@ -674,6 +677,10 @@ BTextView::MessageReceived(BMessage *message)
Undo(be_clipboard); Undo(be_clipboard);
break; break;
case B_SELECT_ALL:
SelectAll();
break;
case B_SET_PROPERTY: case B_SET_PROPERTY:
case B_GET_PROPERTY: case B_GET_PROPERTY:
case B_COUNT_PROPERTIES: case B_COUNT_PROPERTIES:
@@ -769,14 +776,12 @@ BTextView::ResolveSpecifier(BMessage *message, int32 index,
status_t status_t
BTextView::GetSupportedSuites(BMessage *data) BTextView::GetSupportedSuites(BMessage *data)
{ {
// TODO: check if the suite name is ok, according to the documentation it
// is unnamed
status_t err; status_t err;
if (data == NULL) if (data == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
err = data->AddString("suites", ""); err = data->AddString("suites", "suite/vnd.Be-text-view");
if (err != B_OK) if (err != B_OK)
return err; return err;
@@ -793,7 +798,7 @@ BTextView::GetSupportedSuites(BMessage *data)
status_t status_t
BTextView::Perform(perform_code d, void *arg) BTextView::Perform(perform_code d, void *arg)
{ {
return B_ERROR; return BView::Perform(d, arg);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -900,9 +905,12 @@ BTextView::Insert(int32 startOffset, const char *inText, int32 inLength,
InvertCaret(); InvertCaret();
} }
} }
if (startOffset > TextLength())
startOffset = TextLength();
// copy data into buffer // copy data into buffer
InsertText(inText, inLength, fSelStart, inRuns); InsertText(inText, inLength, startOffset, inRuns);
// offset the caret/selection // offset the caret/selection
long saveStart = fSelStart; long saveStart = fSelStart;
@@ -910,7 +918,7 @@ BTextView::Insert(int32 startOffset, const char *inText, int32 inLength,
fSelEnd += inLength; fSelEnd += inLength;
// recalc line breaks and draw the text // recalc line breaks and draw the text
Refresh(saveStart, fSelStart, true, true); Refresh(saveStart, startOffset, true, true);
// draw the caret/hilite the selection // draw the caret/hilite the selection
if (fActive) { if (fActive) {
@@ -1043,12 +1051,12 @@ BTextView::GoToLine(int32 index)
void void
BTextView::Cut(BClipboard *clipboard) BTextView::Cut(BClipboard *clipboard)
{ {
delete fUndo; if (fUndo) {
fUndo = new _BCutUndoBuffer_(this); delete fUndo;
fUndo = new _BCutUndoBuffer_(this);
}
Copy(clipboard); Copy(clipboard);
DeleteText(fSelStart, fSelEnd); Delete();
Refresh(0, LONG_MAX, true, false);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -1061,12 +1069,19 @@ BTextView::Copy(BClipboard *clipboard)
if ((clip = clipboard->Data()) != NULL) { if ((clip = clipboard->Data()) != NULL) {
clip->AddData("text/plain", B_MIME_TYPE, Text() + fSelStart, clip->AddData("text/plain", B_MIME_TYPE, Text() + fSelStart,
fSelEnd - fSelStart); fSelEnd - fSelStart);
int32 size;
if (IsStylable()) {
text_run_array *runArray = RunArray(fSelStart, fSelEnd, &size);
clip->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
runArray, size);
free(runArray);
}
clipboard->Commit(); clipboard->Commit();
} }
} clipboard->Unlock();
}
clipboard->Unlock();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -1077,26 +1092,30 @@ BTextView::Paste(BClipboard *clipboard)
if (clipboard->Lock()) { if (clipboard->Lock()) {
if ((clip = clipboard->Data()) != NULL) { if ((clip = clipboard->Data()) != NULL) {
const char *text = NULL; const char *text = NULL;
text_run_array * runArray = NULL;
ssize_t len = 0; ssize_t len = 0;
ssize_t runLen = 0;
clip->FindData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
(const void **)&runArray, &runLen);
if (clip->FindData("text/plain", B_MIME_TYPE, if (clip->FindData("text/plain", B_MIME_TYPE,
(const void **)&text, &len) == B_OK) { (const void **)&text, &len) == B_OK) {
DeleteText(fSelStart, fSelEnd); text_run_array *runArray = NULL;
InsertText(text, len, fSelStart, runArray); ssize_t runLen = 0;
delete fUndo; if (IsStylable())
fUndo = new _BPasteUndoBuffer_(this, text, len, runArray, runLen); clip->FindData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
(const void **)&runArray, &runLen);
if (fUndo) {
delete fUndo;
fUndo = new _BPasteUndoBuffer_(this, text, len, runArray, runLen);
}
if (fSelStart != fSelEnd)
Delete();
Insert(text, len, runArray);
} }
} }
clipboard->Unlock(); clipboard->Unlock();
} }
Refresh(0, LONG_MAX, true, false);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -1113,30 +1132,30 @@ BTextView::AcceptsPaste(BClipboard *clipboard)
bool result = false; bool result = false;
be_clipboard->Lock(); if (clipboard->Lock()) {
BMessage *data = clipboard->Data();
//result = (be_clipboard->CountEntries(B_ASCII_TYPE) > 0); result = data && data->HasData("text/plain", B_MIME_TYPE);
result = (be_clipboard->Data()->GetInfo((type_code)B_ASCII_TYPE, 0, NULL, clipboard->Unlock();
NULL) == B_OK); }
be_clipboard->Unlock();
return result; return result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool
BTextView::AcceptsDrop(const BMessage *inMessage) BTextView::AcceptsDrop(const BMessage *inMessage)
{ {
if (inMessage->HasData("text", B_ASCII_TYPE) || if (fEditable && inMessage->HasData("text/plain", B_MIME_TYPE))
inMessage->HasData("char", B_INT32_TYPE))
return true; return true;
return false; return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
BTextView::Select(int32 startOffset, int32 endOffset) BTextView::Select(int32 startOffset, int32 endOffset)
{ {
if (!fSelectable)
return;
// a negative selection? // a negative selection?
if (startOffset > endOffset) if (startOffset > endOffset)
return; return;
@@ -1208,8 +1227,13 @@ BTextView::SelectAll()
void void
BTextView::GetSelection(int32 *outStart, int32 *outEnd) const BTextView::GetSelection(int32 *outStart, int32 *outEnd) const
{ {
*outStart = fSelStart; if (fSelectable) {
*outEnd = fSelEnd; *outStart = fSelStart;
*outEnd = fSelEnd;
} else {
*outStart = 0;
*outEnd = 0;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -1226,9 +1250,12 @@ BTextView::SetFontAndColor(const BFont *inFont, uint32 inMode,
} }
} }
BFont newFont = *inFont;
NormalizeFont(&newFont);
// add the style to the style buffer // add the style to the style buffer
fStyles->SetStyleRange(fSelStart, fSelEnd, fText->Length(), fStyles->SetStyleRange(fSelStart, fSelEnd, fText->Length(),
inMode, inFont, inColor); inMode, &newFont, inColor);
if ((inMode & doFont) || (inMode & doSize)) if ((inMode & doFont) || (inMode & doSize))
// recalc the line breaks and redraw with new style // recalc the line breaks and redraw with new style
@@ -1263,9 +1290,12 @@ BTextView::SetFontAndColor(int32 startOffset, int32 endOffset,
} }
} }
BFont newFont = *inFont;
NormalizeFont(&newFont);
// add the style to the style buffer // add the style to the style buffer
fStyles->SetStyleRange(startOffset, endOffset, fText->Length(), fStyles->SetStyleRange(startOffset, endOffset, fText->Length(),
inMode, inFont, inColor); inMode, &newFont, inColor);
if ((inMode & doFont) || (inMode & doSize)) if ((inMode & doFont) || (inMode & doSize))
// recalc the line breaks and redraw with new style // recalc the line breaks and redraw with new style
@@ -1286,7 +1316,7 @@ BTextView::SetFontAndColor(int32 startOffset, int32 endOffset,
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
BTextView::GetFontAndColor(int32 inOffset, BFont*outFont, BTextView::GetFontAndColor(int32 inOffset, BFont *outFont,
rgb_color *outColor) const rgb_color *outColor) const
{ {
fStyles->GetStyle(inOffset, outFont, outColor); fStyles->GetStyle(inOffset, outFont, outColor);
@@ -1311,7 +1341,7 @@ BTextView::SetRunArray(int32 startOffset, int32 endOffset,
long numStyles = inRuns->count; long numStyles = inRuns->count;
if (numStyles > 0) { if (numStyles > 0) {
long textLength = fText->Length(); int32 textLength = fText->Length();
const text_run *theRun = &inRuns->runs[0]; const text_run *theRun = &inRuns->runs[0];
for (long index = 0; index < numStyles; index++) { for (long index = 0; index < numStyles; index++) {
long fromOffset = theRun->offset + startOffset; long fromOffset = theRun->offset + startOffset;
@@ -1346,8 +1376,7 @@ BTextView::RunArray(int32 startOffset, int32 endOffset,
res->count = result->count; res->count = result->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 = result->runs[i].offset;
res->runs[i].font = &result->runs[i].style.font; res->runs[i].font = &result->runs[i].style.font;
res->runs[i].color = result->runs[i].style.color; res->runs[i].color = result->runs[i].style.color;
@@ -1392,10 +1421,10 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
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('\t', offset, &numChars);
@@ -1421,7 +1450,7 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
if (outHeight != NULL) if (outHeight != NULL)
*outHeight = height; *outHeight = height;
return (result); return result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int32 int32
@@ -1549,7 +1578,7 @@ BTextView::OffsetAt(BPoint point) const
return (--offset); return (--offset);
} }
return (offset); return offset;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int32 int32
@@ -1567,7 +1596,7 @@ void
BTextView::FindWord(int32 inOffset, int32 *outFromOffset, BTextView::FindWord(int32 inOffset, int32 *outFromOffset,
int32 *outToOffset) int32 *outToOffset)
{ {
long offset; int32 offset;
// check to the left // check to the left
for (offset = inOffset; offset > 0; offset--) { for (offset = inOffset; offset > 0; offset--) {
@@ -1578,7 +1607,7 @@ BTextView::FindWord(int32 inOffset, int32 *outFromOffset,
*outFromOffset = offset; *outFromOffset = offset;
// check to the right // check to the right
long textLen = TextLength(); int32 textLen = TextLength();
for (offset = inOffset; offset < textLen; offset++) { for (offset = inOffset; offset < textLen; offset++) {
if (CharClassification(offset) == B_SEPARATOR_CHARACTER) if (CharClassification(offset) == B_SEPARATOR_CHARACTER)
break; break;
@@ -1975,13 +2004,12 @@ BTextView::DoesUndo() const
void void
BTextView::HideTyping(bool enabled) BTextView::HideTyping(bool enabled)
{ {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool
BTextView::IsTypingHidden() const BTextView::IsTypingHidden() const
{ {
return false; return fText->PasswordMode();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -1989,7 +2017,7 @@ BTextView::ResizeToPreferred()
{ {
float widht, height; float widht, height;
GetPreferredSize(&widht, &height); GetPreferredSize(&widht, &height);
BView::ResizeTo(widht,height); BView::ResizeTo(widht, height);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -2028,8 +2056,7 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize)
array->version[3] = 0x00; array->version[3] = 0x00;
array->count = inArray->count; array->count = inArray->count;
for (int32 i = 0; i < inArray->count; i++) for (int32 i = 0; i < inArray->count; i++) {
{
array->styles[i].offset = inArray->runs[i].offset; array->styles[i].offset = inArray->runs[i].offset;
inArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family, inArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family,
&array->styles[i].style); &array->styles[i].style);
@@ -2164,6 +2191,24 @@ void
BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap, BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap,
BPoint *point, BHandler **handler) BPoint *point, BHandler **handler)
{ {
// What is this for ?
drag->AddInt32("be_actions", B_TRASH_TARGET);
// add the text
drag->AddData("text/plain", B_MIME_TYPE, fText->Text() + fSelStart,
fSelEnd - fSelStart);
// add the corresponding styles
int32 size = 0;
text_run_array *styles = RunArray(fSelStart, fSelEnd, &size);
drag->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
styles, size);
// add the message originator
drag->AddPointer("be:originator", this);
free(styles);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void BTextView::_ReservedTextView3() {} void BTextView::_ReservedTextView3() {}
@@ -2184,18 +2229,20 @@ BTextView::InitObject(BRect textRect, const BFont *initialFont,
fTextRect = textRect; fTextRect = textRect;
BFont font; BFont font;
if (initialFont == NULL) { if (initialFont == NULL)
GetFont(&font); GetFont(&font);
initialFont = &font; else
} font = *initialFont;
NormalizeFont(&font);
rgb_color black = {0, 0, 0, 255}; rgb_color black = {0, 0, 0, 255};
if (initialColor == NULL) if (initialColor == NULL)
initialColor = &black; initialColor = &black;
fText = new _BTextGapBuffer_; fText = new _BTextGapBuffer_;
fLines = new _BLineBuffer_; fLines = new _BLineBuffer_;
fStyles = new _BStyleBuffer_(initialFont, initialColor); fStyles = new _BStyleBuffer_(&font, initialColor);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -2210,6 +2257,15 @@ BTextView::HandleBackspace()
else else
Highlight(fSelStart, fSelEnd); Highlight(fSelStart, fSelEnd);
if (fUndo) {
_BTypingUndoBuffer_ *undoBuffer = dynamic_cast<_BTypingUndoBuffer_ *>(fUndo);
if (!undoBuffer) {
delete fUndo;
fUndo = undoBuffer = new _BTypingUndoBuffer_(this);
}
undoBuffer->BackwardErase();
}
DeleteText(fSelStart, fSelEnd); DeleteText(fSelStart, fSelEnd);
fSelEnd = fSelStart; fSelEnd = fSelStart;
@@ -2306,7 +2362,16 @@ BTextView::HandleDelete()
} }
else else
Highlight(fSelStart, fSelEnd); Highlight(fSelStart, fSelEnd);
if (fUndo) {
_BTypingUndoBuffer_ *undoBuffer = dynamic_cast<_BTypingUndoBuffer_ *>(fUndo);
if (!undoBuffer) {
delete fUndo;
fUndo = undoBuffer = new _BTypingUndoBuffer_(this);
}
undoBuffer->ForwardErase();
}
DeleteText(fSelStart, fSelEnd); DeleteText(fSelStart, fSelEnd);
fSelEnd = fSelStart; fSelEnd = fSelStart;
@@ -2341,6 +2406,15 @@ BTextView::HandleAlphaKey(const char *bytes, int32 numBytes)
{ {
bool refresh = fSelStart != fText->Length(); bool refresh = fSelStart != fText->Length();
if (fUndo) {
_BTypingUndoBuffer_ *undoBuffer = dynamic_cast<_BTypingUndoBuffer_ *>(fUndo);
if (!undoBuffer) {
delete fUndo;
fUndo = undoBuffer = new _BTypingUndoBuffer_(this);
}
undoBuffer->InputCharacter(numBytes);
}
if (fSelStart != fSelEnd) { if (fSelStart != fSelEnd) {
Highlight(fSelStart, fSelEnd); Highlight(fSelStart, fSelEnd);
DeleteText(fSelStart, fSelEnd); DeleteText(fSelStart, fSelEnd);
@@ -2533,7 +2607,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
} }
} }
return (limit); return limit;
} }
bool done = false; bool done = false;
@@ -2555,7 +2629,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
// iterate through the style runs // iterate through the style runs
int32 length = offset; int32 length = offset;
int32 startOffset = fromOffset; int32 startOffset = fromOffset;
while (int32 numChars = fStyles->Iterate(startOffset, length, NULL, NULL, &ascent, &descent)) { int32 numChars;
while ((numChars = fStyles->Iterate(startOffset, length, NULL, NULL, &ascent, &descent) != 0)) {
*outAscent = (ascent > *outAscent) ? ascent : *outAscent; *outAscent = (ascent > *outAscent) ? ascent : *outAscent;
*outDescent = (descent > *outDescent) ? descent : *outDescent; *outDescent = (descent > *outDescent) ? descent : *outDescent;
@@ -2563,7 +2638,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
length -= numChars; length -= numChars;
} }
return (offset); return offset;
} }
// wrap the text // wrap the text
@@ -2684,7 +2759,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent,
offset = (offset < limit) ? offset : limit; offset = (offset < limit) ? offset : limit;
return (offset); return offset;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
float float
@@ -2699,7 +2774,8 @@ BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent,
// iterate through the style runs // iterate through the style runs
const BFont *font = NULL; const BFont *font = NULL;
while (long numChars = fStyles->Iterate(fromOffset, length, &font, NULL, &ascent, &descent)) { int32 numChars;
while ((numChars = fStyles->Iterate(fromOffset, length, &font, NULL, &ascent, &descent) != 0)) {
maxAscent = (ascent > maxAscent) ? ascent : maxAscent; maxAscent = (ascent > maxAscent) ? ascent : maxAscent;
maxDescent = (descent > maxDescent) ? descent : maxDescent; maxDescent = (descent > maxDescent) ? descent : maxDescent;
@@ -2714,7 +2790,7 @@ BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent,
if (outDescent != NULL) if (outDescent != NULL)
*outDescent = maxDescent; *outDescent = maxDescent;
return (result); return result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
float float
@@ -2807,7 +2883,8 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
long offset = line->offset; long offset = line->offset;
const BFont *font = NULL; const BFont *font = NULL;
const rgb_color *color = NULL; const rgb_color *color = NULL;
while (long numChars = fStyles->Iterate(offset, length, &font, &color)) { int32 numChars;
while ((numChars = fStyles->Iterate(offset, length, &font, &color) != 0)) {
SetFont(font); SetFont(font);
SetHighColor(*color); SetHighColor(*color);
@@ -2946,74 +3023,75 @@ void
BTextView::InitiateDrag() BTextView::InitiateDrag()
{ {
BMessage *drag = new BMessage(); BMessage *drag = new BMessage();
BBitmap *dragBitmap = NULL;
BPoint bitmapPoint;
BHandler *dragHandler = NULL;
// add the text GetDragParameters(drag, &dragBitmap, &bitmapPoint, &dragHandler);
drag->AddData("text", B_ASCII_TYPE, fText->Text() + fSelStart,
fSelEnd - fSelStart);
// add the corresponding styles SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
int32 size = 0;
text_run_array *styles = RunArray(fSelStart, fSelEnd, &size);
drag->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE, if (dragBitmap != NULL)
styles, size); DragMessage(drag, dragBitmap, bitmapPoint, dragHandler);
else {
BRegion hiliteRgn; BRegion hiliteRgn;
GetTextRegion(fSelStart, fSelEnd, &hiliteRgn); GetTextRegion(fSelStart, fSelEnd, &hiliteRgn);
BRect bounds = Bounds(); BRect bounds = Bounds();
BRect dragRect = hiliteRgn.Frame(); BRect dragRect = hiliteRgn.Frame();
if (!bounds.Contains(dragRect)) if (!bounds.Contains(dragRect))
dragRect = bounds & dragRect; dragRect = bounds & dragRect;
be_app->SetCursor(B_HAND_CURSOR); DragMessage(drag, dragRect, dragHandler);
DragMessage(drag, dragRect); }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool bool
BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset) BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset)
{ {
// make sure the drag caret is erased
DragCaret(-1);
if (fActive) if (fActive)
be_app->SetCursor(B_I_BEAM_CURSOR); SetViewCursor(B_CURSOR_I_BEAM);
// are we sure we like this message? // are we sure we like this message?
if (!AcceptsDrop(inMessage)) if (!AcceptsDrop(inMessage))
return false; return false;
long dropOffset = OffsetAt(where); long dropOffset = OffsetAt(where);
if (dropOffset > TextLength())
dropOffset = TextLength();
void *from;
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 ((fActive) && (fSelStart != fSelEnd)) { if (internalDrop) {
// dropping onto itself? // dropping onto itself?
if ((dropOffset >= fSelStart) && (dropOffset <= fSelEnd)) if (dropOffset >= fSelStart && dropOffset <= fSelEnd)
return true; return true;
if (dropOffset > fSelEnd)
dropOffset -= fSelEnd - fSelStart;
Delete();
} }
Select(dropOffset, dropOffset);
ssize_t dataLen = 0; ssize_t dataLen = 0;
const char *text; const char *text = NULL;
inMessage->FindData("text", B_ASCII_TYPE, (const void**)&text, &dataLen); if (inMessage->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &dataLen) == B_OK) {
/*if (text != NULL) {
long styleLen = 0;
STEStyleRangePtr styles = NULL;
styles = (STEStyleRangePtr)inMessage->FindData("style", STE_STYLE_TYPE, &styleLen);
Insert(text, dataLen, styles);
}
else {
char theChar = inMessage->FindLong("char");
if (inMessage->Error() == B_NO_ERROR)
Insert(&theChar, 1);
}*/
text_run_array *runArray = NULL;
ssize_t runLen = 0;
if (IsStylable())
inMessage->FindData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
(const void **)&runArray, &runLen);
if (fUndo) {
delete fUndo;
fUndo = new _BDropUndoBuffer_(this, text, dataLen, runArray, runLen, dropOffset, internalDrop);
}
if (internalDrop)
Delete();
Insert(dropOffset, text, dataLen, runArray);
}
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -3061,11 +3139,19 @@ BTextView::AutoResize(bool doredraw)
void void
BTextView::NewOffscreen(float padding) BTextView::NewOffscreen(float padding)
{ {
if (fOffscreen)
DeleteOffscreen();
//TODO: Implement
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
BTextView::DeleteOffscreen() BTextView::DeleteOffscreen()
{ {
if (fOffscreen && fOffscreen->Lock()) {
delete fOffscreen;
fOffscreen = NULL;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -3086,7 +3172,7 @@ BTextView::Activate()
ulong buttons; ulong buttons;
GetMouse(&where, &buttons); GetMouse(&where, &buttons);
if (Bounds().Contains(where)) if (Bounds().Contains(where))
be_app->SetCursor(B_I_BEAM_CURSOR); SetViewCursor(B_CURSOR_I_BEAM);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -3107,7 +3193,7 @@ BTextView::Deactivate()
ulong buttons; ulong buttons;
GetMouse(&where, &buttons); GetMouse(&where, &buttons);
if (Bounds().Contains(where)) if (Bounds().Contains(where))
be_app->SetCursor(B_HAND_CURSOR); SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
@@ -3126,11 +3212,22 @@ BTextView::CharClassification(int32 offset) const
// japanese word breakers // japanese word breakers
switch (fText->RealCharAt(offset)) { switch (fText->RealCharAt(offset)) {
case B_SPACE: case B_SPACE:
case '/':
case '\\':
case '-':
case '_': case '_':
case '.': case '.':
case '\0':
case '\t':
case '\n':
case '&':
case '*':
case '+':
case '-':
case '/':
case '<':
case '=':
case '>':
case '\\':
case '^':
case '|':
return B_SEPARATOR_CHARACTER; return B_SEPARATOR_CHARACTER;
default: default:
return B_OTHER_CHARACTER; return B_OTHER_CHARACTER;
+204 -10
View File
@@ -1,26 +1,56 @@
#include "UndoBuffer.h" //------------------------------------------------------------------------------
// Copyright (c) 2003, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: UndoBuffer.cpp
// Author: Stefano Ceccherini ([email protected])
// Description: _BUndoBuffer_ and its subclasses
// handle different types of Undo operations.
//------------------------------------------------------------------------------
// Standard Includes -----------------------------------------------------------
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
// System Includes -------------------------------------------------------------
#include <Clipboard.h> #include <Clipboard.h>
// ******** _BUndoBuffer_ ******* // Local Includes --------------------------------------------------------------
#include "UndoBuffer.h"
// ******** _BUndoBuffer_ *******
_BUndoBuffer_::_BUndoBuffer_(BTextView *textView, undo_state state) _BUndoBuffer_::_BUndoBuffer_(BTextView *textView, undo_state state)
: :
fTextView(textView), fTextView(textView),
fState(state), fTextData(NULL),
fRedo(false),
fRunArray(NULL), fRunArray(NULL),
fRunArrayLength(0) fRunArrayLength(0),
fRedo(false),
fState(state)
{ {
fTextView->GetSelection(&fStart, &fEnd); fTextView->GetSelection(&fStart, &fEnd);
fTextLength = fEnd - fStart; fTextLength = fEnd - fStart;
fTextData = (char*)malloc(fTextLength); fTextData = (char *)malloc(fTextLength);
memcpy(fTextData, fTextView->Text() + fStart, fTextLength); memcpy(fTextData, fTextView->Text() + fStart, fTextLength);
if (fTextView->IsStylable()) if (fTextView->IsStylable())
@@ -70,7 +100,8 @@ _BUndoBuffer_::RedoSelf(BClipboard *clipboard)
// ******** _BCutUndoBuffer_ ******* // ******** _BCutUndoBuffer_ *******
_BCutUndoBuffer_::_BCutUndoBuffer_(BTextView *textView) _BCutUndoBuffer_::_BCutUndoBuffer_(BTextView *textView)
:_BUndoBuffer_(textView, B_UNDO_CUT) :
_BUndoBuffer_(textView, B_UNDO_CUT)
{ {
} }
@@ -104,10 +135,12 @@ _BCutUndoBuffer_::RedoSelf(BClipboard *clipboard)
// ******** _BPasteUndoBuffer_ ******* // ******** _BPasteUndoBuffer_ *******
_BPasteUndoBuffer_::_BPasteUndoBuffer_(BTextView *textView, const char *text, _BPasteUndoBuffer_::_BPasteUndoBuffer_(BTextView *textView, const char *text,
int32 textLen, text_run_array *runArray, int32 runArrayLen) int32 textLen, text_run_array *runArray, int32 runArrayLen)
:_BUndoBuffer_(textView, B_UNDO_PASTE), :
_BUndoBuffer_(textView, B_UNDO_PASTE),
fPasteText(NULL), fPasteText(NULL),
fPasteTextLength(textLen), fPasteTextLength(textLen),
fPasteRunArray(NULL) fPasteRunArray(NULL),
fPasteRunArrayLength(0)
{ {
fPasteText = (char *)malloc(fPasteTextLength); fPasteText = (char *)malloc(fPasteTextLength);
memcpy(fPasteText, text, fPasteTextLength); memcpy(fPasteText, text, fPasteTextLength);
@@ -166,3 +199,164 @@ _BClearUndoBuffer_::RedoSelf(BClipboard *clipboard)
fTextView->Select(fStart, fStart); fTextView->Select(fStart, fStart);
fTextView->Delete(fStart, fEnd); fTextView->Delete(fStart, fEnd);
} }
// ******** _BDropUndoBuffer_ ********
_BDropUndoBuffer_::_BDropUndoBuffer_(BTextView *textView, char const *text, int32 textLen,
text_run_array *runArray, int32 runArrayLen, int32 location,
bool internalDrop)
:
_BUndoBuffer_(textView, B_UNDO_DROP),
fDropText(NULL),
fDropTextLength(textLen),
fDropRunArray(NULL)
{
fInternalDrop = internalDrop;
fDropLocation = location;
fDropText = (char *)malloc(fDropTextLength);
memcpy(fDropText, text, fDropTextLength);
if (runArray) {
fDropRunArray = (text_run_array *)malloc(runArrayLen);
fDropRunArrayLength = runArrayLen;
memcpy(fDropRunArray, runArray, runArrayLen);
}
}
_BDropUndoBuffer_::~_BDropUndoBuffer_()
{
free(fDropText);
free(fDropRunArray);
}
void
_BDropUndoBuffer_::UndoSelf(BClipboard *)
{
fTextView->Select(fDropLocation, fDropLocation);
fTextView->Delete(fDropLocation, fDropLocation + fDropTextLength);
if (fInternalDrop) {
fTextView->Select(fStart, fStart);
fTextView->Insert(fTextData, fTextLength, fRunArray);
}
fTextView->Select(fStart, fEnd);
}
void
_BDropUndoBuffer_::RedoSelf(BClipboard *)
{
if (fInternalDrop) {
fTextView->Select(fStart, fStart);
fTextView->Delete(fStart, fEnd);
}
fTextView->Select(fDropLocation, fDropLocation);
fTextView->Insert(fDropText, fDropTextLength, fDropRunArray);
fTextView->Select(fDropLocation, fDropLocation + fDropTextLength);
}
// ******** _BTypingUndoBuffer_ ********
_BTypingUndoBuffer_::_BTypingUndoBuffer_(BTextView *textView)
:
_BUndoBuffer_(textView, B_UNDO_TYPING),
fTypedText(NULL),
fTypedStart(fStart),
fNumBytes(0)
{
}
_BTypingUndoBuffer_::~_BTypingUndoBuffer_()
{
free(fTypedText);
}
void
_BTypingUndoBuffer_::UndoSelf(BClipboard *clipboard)
{
free(fTypedText);
fTypedText = (char *)malloc(fNumBytes);
memcpy(fTypedText, fTextView->Text() + fTypedStart, fNumBytes);
fTextView->Select(fTypedStart, fTypedStart);
fTextView->Delete(fTypedStart, fTypedStart + fNumBytes);
fTextView->Insert(fTextData, fTextLength);
fTextView->Select(fStart, fEnd);
}
void
_BTypingUndoBuffer_::RedoSelf(BClipboard *clipboard)
{
fTextView->Select(fTypedStart, fTypedStart);
fTextView->Delete(fTypedStart, fTypedStart + fTextLength);
fTextView->Insert(fTypedText, fNumBytes);
}
void
_BTypingUndoBuffer_::InputCharacter(int32 len)
{
int32 start, end;
fTextView->GetSelection(&start, &end);
int32 currentPos = fTypedStart + fNumBytes;
if (start != currentPos)
Reset();
fNumBytes += len;
}
void
_BTypingUndoBuffer_::Reset()
{
free(fTextData);
fTextView->GetSelection(&fStart, &fEnd);
fTextLength = fEnd - fStart;
fTypedStart = fStart;
fNumBytes = 0;
fTextData = (char *)malloc(fTextLength);
memcpy(fTextData, fTextView->Text() + fStart, fTextLength);
free(fTypedText);
fTypedText = NULL;
fRedo = false;
}
void
_BTypingUndoBuffer_::ForwardErase()
{
//TODO: Fix this. Currently, it just resets the
//undobuffer every time DELETE is pressed, while
//it should reset it just the first time it's pressed.
//Moreover, it doesn't work with multi-byte characters.
int32 start, end;
fTextView->GetSelection(&start, &end);
int32 currentPos = fTypedStart + fNumBytes;
if (start != currentPos)
Reset();
}
void
_BTypingUndoBuffer_::BackwardErase()
{
//TODO: Fix this. Currently, it just resets the
//undobuffer every time BACKSPACE is pressed, while
//it should reset it just the first time it's pressed.
//Moreover, it doesn't work with multi-byte characters.
int32 start, end;
fTextView->GetSelection(&start, &end);
int32 currentPos = fTypedStart + fNumBytes;
if (start != currentPos)
Reset();
}
+71 -2
View File
@@ -1,9 +1,37 @@
//------------------------------------------------------------------------------
// Copyright (c) 2003, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: UndoBuffer.h
// Author: Stefano Ceccherini ([email protected])
// Description: _BUndoBuffer_ and its subclasses
// handle different types of Undo operations.
//------------------------------------------------------------------------------
#ifndef __UNDOBUFFER_H #ifndef __UNDOBUFFER_H
#define __UNDOBUFFER_H #define __UNDOBUFFER_H
// System Includes -------------------------------------------------------------
#include <TextView.h> #include <TextView.h>
class BClipboard; class BClipboard;
class _BUndoBuffer_ class _BUndoBuffer_
{ {
public: public:
@@ -25,10 +53,10 @@ protected:
int32 fTextLength; int32 fTextLength;
text_run_array *fRunArray; text_run_array *fRunArray;
int32 fRunArrayLength; int32 fRunArrayLength;
bool fRedo;
private: private:
undo_state fState; undo_state fState;
bool fRedo;
}; };
@@ -71,4 +99,45 @@ protected:
}; };
// ******** _BDropUndoBuffer_ ********
class _BDropUndoBuffer_ : public _BUndoBuffer_
{
public:
_BDropUndoBuffer_(BTextView *, char const *, int32, text_run_array *, int32, int32, bool);
~_BDropUndoBuffer_();
protected:
virtual void UndoSelf(BClipboard *);
virtual void RedoSelf(BClipboard *);
private:
char *fDropText;
int32 fDropTextLength;
text_run_array *fDropRunArray;
int32 fDropRunArrayLength;
int32 fDropLocation;
bool fInternalDrop;
};
// ******** _BTypingUndoBuffer_ ********
class _BTypingUndoBuffer_ : public _BUndoBuffer_
{
public:
_BTypingUndoBuffer_(BTextView *);
~_BTypingUndoBuffer_();
void InputCharacter(int32);
void BackwardErase();
void ForwardErase();
protected:
virtual void RedoSelf(BClipboard *);
virtual void UndoSelf(BClipboard *);
private:
void Reset();
char *fTypedText;
int32 fTypedStart;
int32 fNumBytes;
};
#endif //__UNDOBUFFER_H #endif //__UNDOBUFFER_H