Some more work on TextView by Jack Burton and me, Undo partially works now

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4498 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marc Flerackers 2003-09-04 08:45:34 +00:00
parent 1d5050d24f
commit b140f1de88
3 changed files with 291 additions and 36 deletions

View File

@ -26,7 +26,6 @@
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
#include <Application.h>
#include <Clipboard.h>
@ -42,6 +41,7 @@
#include "TextGapBuffer.h"
#include "LineBuffer.h"
#include "StyleBuffer.h"
#include "UndoBuffer.h"
//#include <CRTDBG.H>
@ -142,8 +142,8 @@ prop_list[] =
{ 0 }
};
sem_id BTextView::sWidthSem;
int32 BTextView::sWidthAtom;
sem_id BTextView::sWidthSem = B_BAD_SEM_ID; // Created/deleted by init/fini_interface_kit
int32 BTextView::sWidthAtom = 0;
//------------------------------------------------------------------------------
BTextView::BTextView(BRect frame, const char *name, BRect textRect,
@ -285,6 +285,7 @@ BTextView::~BTextView()
delete fLines;
delete fStyles;
delete fDisallowedChars;
delete fUndo;
}
//------------------------------------------------------------------------------
BArchivable *
@ -668,7 +669,11 @@ BTextView::MessageReceived(BMessage *message)
case B_PASTE:
Paste(be_clipboard);
break;
case B_UNDO:
Undo(be_clipboard);
break;
case B_SET_PROPERTY:
case B_GET_PROPERTY:
case B_COUNT_PROPERTIES:
@ -975,8 +980,7 @@ BTextView::Delete(int32 startOffset, int32 endOffset)
Refresh(startOffset, endOffset, true, true);
// draw the caret
if (fActive)
{
if (fActive) {
if (!fCaretVisible)
InvertCaret();
}
@ -1039,8 +1043,12 @@ BTextView::GoToLine(int32 index)
void
BTextView::Cut(BClipboard *clipboard)
{
delete fUndo;
fUndo = new _BCutUndoBuffer_(this);
Copy(clipboard);
DeleteText(fSelStart, fSelEnd);
Refresh(0, LONG_MAX, true, false);
}
//------------------------------------------------------------------------------
void
@ -1068,18 +1076,27 @@ BTextView::Paste(BClipboard *clipboard)
if (clipboard->Lock()) {
if ((clip = clipboard->Data()) != NULL) {
const char *text;
ssize_t len;
const char *text = NULL;
text_run_array * runArray = NULL;
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,
(const void **)&text, &len) == B_OK) {
DeleteText(fSelStart, fSelEnd);
InsertText(text, len, fSelStart, NULL);
}
InsertText(text, len, fSelStart, runArray);
delete fUndo;
fUndo = new _BPasteUndoBuffer_(this, text, len, runArray, runLen);
}
}
clipboard->Unlock();
}
Refresh(0, LONG_MAX, true, false);
}
//------------------------------------------------------------------------------
void
@ -1104,7 +1121,7 @@ BTextView::AcceptsPaste(BClipboard *clipboard)
be_clipboard->Unlock();
return (result);
return result;
}
//------------------------------------------------------------------------------
bool
@ -1941,13 +1958,18 @@ BTextView::IsResizable () const
void
BTextView::SetDoesUndo(bool undo)
{
if (undo && fUndo == NULL)
fUndo = new _BUndoBuffer_(this, B_UNDO_UNAVAILABLE);
else if (!undo && fUndo != NULL) {
delete fUndo;
fUndo = NULL;
}
}
//------------------------------------------------------------------------------
bool
BTextView::DoesUndo() const
{
return false;
return fUndo != NULL;
}
//------------------------------------------------------------------------------
void
@ -2128,12 +2150,14 @@ BTextView::DeleteText(int32 fromOffset, int32 toOffset)
void
BTextView::Undo(BClipboard *clipboard)
{
if (fUndo)
fUndo->Undo(clipboard);
}
//------------------------------------------------------------------------------
undo_state
BTextView::UndoState(bool *isRedo) const
{
return B_UNDO_UNAVAILABLE;
return fUndo == NULL ? B_UNDO_UNAVAILABLE : fUndo->State(isRedo);
}
//------------------------------------------------------------------------------
void
@ -3133,8 +3157,7 @@ BTextView::PreviousInitialByte(int32 offset) const
const char *text = Text();
int count = 6;
for (--offset; (text + offset) > text && count; --offset, --count)
{
for (--offset; (text + offset) > text && count; --offset, --count) {
if ((*(text + offset) & 0xc0 ) != 0x80)
break;
}
@ -3146,16 +3169,13 @@ bool
BTextView::GetProperty(BMessage *specifier, int32 form,
const char *property, BMessage *reply)
{
if (strcmp(property, "Selection") == 0)
{
if (strcmp(property, "Selection") == 0) {
reply->what = B_REPLY;
reply->AddInt32("result", fSelStart);
reply->AddInt32("result", fSelEnd);
reply->AddInt32("error", B_OK);
return true;
}
else if (strcmp(property, "Text") == 0)
{
} else if (strcmp(property, "Text") == 0) {
int32 index, range;
char *buffer;
@ -3170,11 +3190,8 @@ BTextView::GetProperty(BMessage *specifier, int32 form,
delete buffer;
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
return false;
}
@ -3183,8 +3200,7 @@ bool
BTextView::SetProperty(BMessage *specifier, int32 form,
const char *property, BMessage *reply)
{
if (strcmp(property, "Selection") == 0)
{
if (strcmp(property, "Selection") == 0) {
int32 index, range;
specifier->FindInt32("index", &index);
@ -3197,8 +3213,7 @@ BTextView::SetProperty(BMessage *specifier, int32 form,
return true;
}
else if (strcmp(property, "Text") == 0)
{
else if (strcmp(property, "Text") == 0) {
int32 index, range;
const char *buffer;
@ -3216,9 +3231,8 @@ BTextView::SetProperty(BMessage *specifier, int32 form,
return true;
}
else if (strcmp(property, "text_run_array") == 0)
{
return false;
}
else
return false;
}
@ -3227,8 +3241,7 @@ bool
BTextView::CountProperties(BMessage *specifier, int32 form,
const char *property, BMessage *reply)
{
if (strcmp(property, "Text") == 0)
{
if (strcmp(property, "Text") == 0) {
reply->what = B_REPLY;
reply->AddInt32("result", TextLength());
reply->AddInt32("error", B_OK);
@ -3257,14 +3270,14 @@ BTextView::CancelInputMethod()
void
BTextView::LockWidthBuffer()
{
if (atomic_add(&sWidthAtom, -1) <= 0)
if (atomic_add(&sWidthAtom, 1) > 0)
acquire_sem(sWidthSem);
}
//------------------------------------------------------------------------------
void
BTextView::UnlockWidthBuffer()
{
if (atomic_add(&sWidthAtom, 1) < 0)
if (atomic_add(&sWidthAtom, -1) > 1)
release_sem(sWidthSem);
}
//------------------------------------------------------------------------------

View File

@ -0,0 +1,168 @@
#include "UndoBuffer.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <Clipboard.h>
// ******** _BUndoBuffer_ *******
_BUndoBuffer_::_BUndoBuffer_(BTextView *textView, undo_state state)
:
fTextView(textView),
fState(state),
fRedo(false),
fRunArray(NULL),
fRunArrayLength(0)
{
fTextView->GetSelection(&fStart, &fEnd);
fTextLength = fEnd - fStart;
fTextData = (char*)malloc(fTextLength);
memcpy(fTextData, fTextView->Text() + fStart, fTextLength);
if (fTextView->IsStylable())
fRunArray = fTextView->RunArray(fStart, fEnd, &fRunArrayLength);
}
_BUndoBuffer_::~_BUndoBuffer_()
{
free(fTextData);
free(fRunArray);
}
void
_BUndoBuffer_::Undo(BClipboard *clipboard)
{
fRedo ? RedoSelf(clipboard) : UndoSelf(clipboard);
fRedo = !fRedo;
}
undo_state
_BUndoBuffer_::State(bool *redo)
{
*redo = fRedo;
return fState;
}
void
_BUndoBuffer_::UndoSelf(BClipboard *clipboard)
{
fTextView->Select(fStart, fStart);
fTextView->Insert(fTextData, fTextLength, fRunArray);
fTextView->Select(fStart, fStart);
}
void
_BUndoBuffer_::RedoSelf(BClipboard *clipboard)
{
}
// ******** _BCutUndoBuffer_ *******
_BCutUndoBuffer_::_BCutUndoBuffer_(BTextView *textView)
:_BUndoBuffer_(textView, B_UNDO_CUT)
{
}
_BCutUndoBuffer_::~_BCutUndoBuffer_()
{
}
void
_BCutUndoBuffer_::RedoSelf(BClipboard *clipboard)
{
BMessage *clip = NULL;
fTextView->Select(fStart, fStart);
fTextView->Delete(fStart, fEnd);
if (clipboard->Lock()) {
clipboard->Clear();
if ((clip = clipboard->Data())) {
clip->AddData("text/plain", B_MIME_TYPE, fTextData, fTextLength);
if (fRunArray)
clip->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
fRunArray, fRunArrayLength);
clipboard->Commit();
}
clipboard->Unlock();
}
}
// ******** _BPasteUndoBuffer_ *******
_BPasteUndoBuffer_::_BPasteUndoBuffer_(BTextView *textView, const char *text,
int32 textLen, text_run_array *runArray, int32 runArrayLen)
:_BUndoBuffer_(textView, B_UNDO_PASTE),
fPasteText(NULL),
fPasteTextLength(textLen),
fPasteRunArray(NULL)
{
fPasteText = (char *)malloc(fPasteTextLength);
memcpy(fPasteText, text, fPasteTextLength);
if (runArray) {
fPasteRunArray = (text_run_array *)malloc(runArrayLen);
fPasteRunArrayLength = runArrayLen;
memcpy(fPasteRunArray, runArray, runArrayLen);
}
}
_BPasteUndoBuffer_::~_BPasteUndoBuffer_()
{
free(fPasteText);
free(fPasteRunArray);
}
void
_BPasteUndoBuffer_::UndoSelf(BClipboard *clipboard)
{
fTextView->Select(fStart, fStart);
fTextView->Delete(fStart, fStart + fPasteTextLength);
fTextView->Insert(fTextData, fTextLength, fRunArray);
fTextView->Select(fStart, fEnd);
}
void
_BPasteUndoBuffer_::RedoSelf(BClipboard *clipboard)
{
fTextView->Select(fStart, fStart);
fTextView->Delete(fStart, fEnd);
fTextView->Insert(fPasteText, fPasteTextLength, fPasteRunArray);
fTextView->Select(fStart + fPasteTextLength, fStart + fPasteTextLength);
}
// ******** _BClearUndoBuffer_ *******
_BClearUndoBuffer_::_BClearUndoBuffer_(BTextView *textView)
:
_BUndoBuffer_(textView, B_UNDO_CLEAR)
{
}
_BClearUndoBuffer_::~_BClearUndoBuffer_()
{
}
void
_BClearUndoBuffer_::RedoSelf(BClipboard *clipboard)
{
fTextView->Select(fStart, fStart);
fTextView->Delete(fStart, fEnd);
}

View File

@ -0,0 +1,74 @@
#ifndef __UNDOBUFFER_H
#define __UNDOBUFFER_H
#include <TextView.h>
class BClipboard;
class _BUndoBuffer_
{
public:
_BUndoBuffer_(BTextView *, undo_state);
virtual ~_BUndoBuffer_();
void Undo(BClipboard *);
undo_state State(bool *);
protected:
virtual void UndoSelf(BClipboard *);
virtual void RedoSelf(BClipboard *);
BTextView *fTextView;
int32 fStart;
int32 fEnd;
char *fTextData;
int32 fTextLength;
text_run_array *fRunArray;
int32 fRunArrayLength;
private:
undo_state fState;
bool fRedo;
};
// ******** _BCutUndoBuffer_ *******
class _BCutUndoBuffer_ : public _BUndoBuffer_
{
public:
_BCutUndoBuffer_(BTextView *textView);
~_BCutUndoBuffer_();
protected:
virtual void RedoSelf(BClipboard *);
};
// ******** _BPasteUndoBuffer_ *******
class _BPasteUndoBuffer_ : public _BUndoBuffer_
{
public:
_BPasteUndoBuffer_(BTextView *, const char *, int32, text_run_array *, int32);
~_BPasteUndoBuffer_();
protected:
virtual void UndoSelf(BClipboard *);
virtual void RedoSelf(BClipboard *);
private:
char *fPasteText;
int32 fPasteTextLength;
text_run_array *fPasteRunArray;
int32 fPasteRunArrayLength;
};
// ******** _BClearUndoBuffer_ *******
class _BClearUndoBuffer_ : public _BUndoBuffer_
{
public:
_BClearUndoBuffer_(BTextView *textView);
~_BClearUndoBuffer_();
protected:
virtual void RedoSelf(BClipboard *);
};
#endif //__UNDOBUFFER_H