diff --git a/src/kits/interface/BTextView/TextView.cpp b/src/kits/interface/BTextView/TextView.cpp index a41aa29241..6f1d71535a 100644 --- a/src/kits/interface/BTextView/TextView.cpp +++ b/src/kits/interface/BTextView/TextView.cpp @@ -28,6 +28,7 @@ // System Includes ------------------------------------------------------------- #include +#include #include #include #include @@ -37,17 +38,15 @@ #include #include - -#include "TextGapBuffer.h" -#include "LineBuffer.h" -#include "StyleBuffer.h" -#include "UndoBuffer.h" - //#include // Project Includes ------------------------------------------------------------ // Local Includes -------------------------------------------------------------- +#include "LineBuffer.h" +#include "StyleBuffer.h" +#include "TextGapBuffer.h" +#include "UndoBuffer.h" // Local Defines --------------------------------------------------------------- @@ -333,13 +332,15 @@ BTextView::AttachedToWindow() fDragOffset = -1; fActive = false; + Window()->SetPulseRate(50000); + Refresh(0, LONG_MAX, true, false); } //------------------------------------------------------------------------------ void BTextView::DetachedFromWindow() { - //TODO: if cursor in bounds, reset it to B_HAND_CURSOR + BView::DetachedFromWindow(); } //------------------------------------------------------------------------------ void @@ -366,7 +367,7 @@ void BTextView::MouseDown(BPoint where) { // should we even bother? - if ((!fEditable) && (!fSelectable)) + if (!fEditable && !fSelectable) return; if (!IsFocus()) { @@ -378,8 +379,8 @@ BTextView::MouseDown(BPoint where) if (fCaretVisible) InvertCaret(); - int32 mouseOffset = OffsetAt(where); - bool shiftDown = modifiers() & B_SHIFT_KEY; + int32 mouseOffset = OffsetAt(where); + bool shiftDown = modifiers() & B_SHIFT_KEY; // should we initiate a drag? if ((fSelStart != fSelEnd) && (!shiftDown)) { @@ -407,8 +408,7 @@ BTextView::MouseDown(BPoint where) // triple click fClickCount = 0; fClickTime = 0; - } - else { + } else { // double click fClickCount = 2; fClickTime = system_time(); @@ -510,6 +510,7 @@ BTextView::MouseDown(BPoint where) void BTextView::MouseUp(BPoint where) { + PerformMouseUp(where); } //------------------------------------------------------------------------------ void @@ -518,7 +519,7 @@ BTextView::MouseMoved(BPoint where, uint32 code, const BMessage *message) switch (code) { case B_ENTERED_VIEW: if ((fActive) && (message == NULL)) - be_app->SetCursor(B_I_BEAM_CURSOR); + SetViewCursor(B_CURSOR_I_BEAM); break; case B_INSIDE_VIEW: @@ -531,7 +532,7 @@ BTextView::MouseMoved(BPoint where, uint32 code, const BMessage *message) case B_EXITED_VIEW: DragCaret(-1); if (fActive) - be_app->SetCursor(B_HAND_CURSOR); + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); break; default: @@ -560,13 +561,15 @@ BTextView::KeyDown(const char *bytes, int32 numBytes) { if (!fEditable) return; - + + const char keyPressed = bytes[0]; + // hide the cursor and caret be_app->ObscureCursor(); if (fCaretVisible) InvertCaret(); - switch (bytes[0]) { + switch (keyPressed) { case B_BACKSPACE: HandleBackspace(); break; @@ -575,7 +578,7 @@ BTextView::KeyDown(const char *bytes, int32 numBytes) case B_RIGHT_ARROW: case B_UP_ARROW: case B_DOWN_ARROW: - HandleArrowKey(bytes[0]); + HandleArrowKey(keyPressed); break; case B_DELETE: @@ -586,7 +589,7 @@ BTextView::KeyDown(const char *bytes, int32 numBytes) case B_END: case B_PAGE_UP: case B_PAGE_DOWN: - HandlePageKey(bytes[0]); + HandlePageKey(keyPressed); break; case B_ESCAPE: @@ -674,6 +677,10 @@ BTextView::MessageReceived(BMessage *message) Undo(be_clipboard); break; + case B_SELECT_ALL: + SelectAll(); + break; + case B_SET_PROPERTY: case B_GET_PROPERTY: case B_COUNT_PROPERTIES: @@ -769,14 +776,12 @@ BTextView::ResolveSpecifier(BMessage *message, int32 index, status_t BTextView::GetSupportedSuites(BMessage *data) { - // TODO: check if the suite name is ok, according to the documentation it - // is unnamed status_t err; if (data == NULL) return B_BAD_VALUE; - err = data->AddString("suites", ""); + err = data->AddString("suites", "suite/vnd.Be-text-view"); if (err != B_OK) return err; @@ -793,7 +798,7 @@ BTextView::GetSupportedSuites(BMessage *data) status_t BTextView::Perform(perform_code d, void *arg) { - return B_ERROR; + return BView::Perform(d, arg); } //------------------------------------------------------------------------------ void @@ -900,9 +905,12 @@ BTextView::Insert(int32 startOffset, const char *inText, int32 inLength, InvertCaret(); } } - + + if (startOffset > TextLength()) + startOffset = TextLength(); + // copy data into buffer - InsertText(inText, inLength, fSelStart, inRuns); + InsertText(inText, inLength, startOffset, inRuns); // offset the caret/selection long saveStart = fSelStart; @@ -910,7 +918,7 @@ BTextView::Insert(int32 startOffset, const char *inText, int32 inLength, fSelEnd += inLength; // recalc line breaks and draw the text - Refresh(saveStart, fSelStart, true, true); + Refresh(saveStart, startOffset, true, true); // draw the caret/hilite the selection if (fActive) { @@ -1043,12 +1051,12 @@ BTextView::GoToLine(int32 index) void BTextView::Cut(BClipboard *clipboard) { - delete fUndo; - fUndo = new _BCutUndoBuffer_(this); + if (fUndo) { + delete fUndo; + fUndo = new _BCutUndoBuffer_(this); + } Copy(clipboard); - DeleteText(fSelStart, fSelEnd); - - Refresh(0, LONG_MAX, true, false); + Delete(); } //------------------------------------------------------------------------------ void @@ -1061,12 +1069,19 @@ BTextView::Copy(BClipboard *clipboard) if ((clip = clipboard->Data()) != NULL) { 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->Unlock(); + clipboard->Unlock(); + } } //------------------------------------------------------------------------------ void @@ -1077,26 +1092,30 @@ BTextView::Paste(BClipboard *clipboard) if (clipboard->Lock()) { if ((clip = clipboard->Data()) != NULL) { 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, runArray); + text_run_array *runArray = NULL; + ssize_t runLen = 0; - delete fUndo; - fUndo = new _BPasteUndoBuffer_(this, text, len, runArray, runLen); + if (IsStylable()) + 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(); } - - Refresh(0, LONG_MAX, true, false); } //------------------------------------------------------------------------------ void @@ -1113,30 +1132,30 @@ BTextView::AcceptsPaste(BClipboard *clipboard) bool result = false; - be_clipboard->Lock(); - - //result = (be_clipboard->CountEntries(B_ASCII_TYPE) > 0); - result = (be_clipboard->Data()->GetInfo((type_code)B_ASCII_TYPE, 0, NULL, - NULL) == B_OK); - - be_clipboard->Unlock(); - + if (clipboard->Lock()) { + BMessage *data = clipboard->Data(); + result = data && data->HasData("text/plain", B_MIME_TYPE); + clipboard->Unlock(); + } + return result; } //------------------------------------------------------------------------------ bool BTextView::AcceptsDrop(const BMessage *inMessage) { - if (inMessage->HasData("text", B_ASCII_TYPE) || - inMessage->HasData("char", B_INT32_TYPE)) + if (fEditable && inMessage->HasData("text/plain", B_MIME_TYPE)) return true; - + return false; } //------------------------------------------------------------------------------ void BTextView::Select(int32 startOffset, int32 endOffset) { + if (!fSelectable) + return; + // a negative selection? if (startOffset > endOffset) return; @@ -1208,8 +1227,13 @@ BTextView::SelectAll() void BTextView::GetSelection(int32 *outStart, int32 *outEnd) const { - *outStart = fSelStart; - *outEnd = fSelEnd; + if (fSelectable) { + *outStart = fSelStart; + *outEnd = fSelEnd; + } else { + *outStart = 0; + *outEnd = 0; + } } //------------------------------------------------------------------------------ void @@ -1226,9 +1250,12 @@ BTextView::SetFontAndColor(const BFont *inFont, uint32 inMode, } } + BFont newFont = *inFont; + NormalizeFont(&newFont); + // add the style to the style buffer fStyles->SetStyleRange(fSelStart, fSelEnd, fText->Length(), - inMode, inFont, inColor); + inMode, &newFont, inColor); if ((inMode & doFont) || (inMode & doSize)) // 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 fStyles->SetStyleRange(startOffset, endOffset, fText->Length(), - inMode, inFont, inColor); + inMode, &newFont, inColor); if ((inMode & doFont) || (inMode & doSize)) // recalc the line breaks and redraw with new style @@ -1286,7 +1316,7 @@ BTextView::SetFontAndColor(int32 startOffset, int32 endOffset, } //------------------------------------------------------------------------------ void -BTextView::GetFontAndColor(int32 inOffset, BFont*outFont, +BTextView::GetFontAndColor(int32 inOffset, BFont *outFont, rgb_color *outColor) const { fStyles->GetStyle(inOffset, outFont, outColor); @@ -1311,7 +1341,7 @@ BTextView::SetRunArray(int32 startOffset, int32 endOffset, long numStyles = inRuns->count; if (numStyles > 0) { - long textLength = fText->Length(); + int32 textLength = fText->Length(); const text_run *theRun = &inRuns->runs[0]; for (long index = 0; index < numStyles; index++) { long fromOffset = theRun->offset + startOffset; @@ -1346,8 +1376,7 @@ BTextView::RunArray(int32 startOffset, int32 endOffset, 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].font = &result->runs[i].style.font; res->runs[i].color = result->runs[i].style.color; @@ -1392,10 +1421,10 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const height = ascent + descent; } else { - int32 offset = line->offset; - int32 length = inOffset - line->offset; - int32 numChars = length; - bool foundTab = false; + int32 offset = line->offset; + int32 length = inOffset - line->offset; + int32 numChars = length; + bool foundTab = false; do { foundTab = fText->FindChar('\t', offset, &numChars); @@ -1421,7 +1450,7 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const if (outHeight != NULL) *outHeight = height; - return (result); + return result; } //------------------------------------------------------------------------------ int32 @@ -1549,7 +1578,7 @@ BTextView::OffsetAt(BPoint point) const return (--offset); } - return (offset); + return offset; } //------------------------------------------------------------------------------ int32 @@ -1567,7 +1596,7 @@ void BTextView::FindWord(int32 inOffset, int32 *outFromOffset, int32 *outToOffset) { - long offset; + int32 offset; // check to the left for (offset = inOffset; offset > 0; offset--) { @@ -1578,7 +1607,7 @@ BTextView::FindWord(int32 inOffset, int32 *outFromOffset, *outFromOffset = offset; // check to the right - long textLen = TextLength(); + int32 textLen = TextLength(); for (offset = inOffset; offset < textLen; offset++) { if (CharClassification(offset) == B_SEPARATOR_CHARACTER) break; @@ -1975,13 +2004,12 @@ BTextView::DoesUndo() const void BTextView::HideTyping(bool enabled) { - } //------------------------------------------------------------------------------ bool BTextView::IsTypingHidden() const { - return false; + return fText->PasswordMode(); } //------------------------------------------------------------------------------ void @@ -1989,7 +2017,7 @@ BTextView::ResizeToPreferred() { float widht, height; GetPreferredSize(&widht, &height); - BView::ResizeTo(widht,height); + BView::ResizeTo(widht, height); } //------------------------------------------------------------------------------ void @@ -2028,8 +2056,7 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) array->version[3] = 0x00; 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; inArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family, &array->styles[i].style); @@ -2164,6 +2191,24 @@ void BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap, 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() {} @@ -2184,18 +2229,20 @@ BTextView::InitObject(BRect textRect, const BFont *initialFont, fTextRect = textRect; BFont font; - if (initialFont == NULL) { + if (initialFont == NULL) GetFont(&font); - initialFont = &font; - } - + else + font = *initialFont; + + NormalizeFont(&font); + rgb_color black = {0, 0, 0, 255}; if (initialColor == NULL) initialColor = &black; fText = new _BTextGapBuffer_; fLines = new _BLineBuffer_; - fStyles = new _BStyleBuffer_(initialFont, initialColor); + fStyles = new _BStyleBuffer_(&font, initialColor); } //------------------------------------------------------------------------------ void @@ -2210,6 +2257,15 @@ BTextView::HandleBackspace() else 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); fSelEnd = fSelStart; @@ -2306,7 +2362,16 @@ BTextView::HandleDelete() } else 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); fSelEnd = fSelStart; @@ -2341,6 +2406,15 @@ BTextView::HandleAlphaKey(const char *bytes, int32 numBytes) { 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) { Highlight(fSelStart, fSelEnd); DeleteText(fSelStart, fSelEnd); @@ -2533,7 +2607,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent, } } - return (limit); + return limit; } bool done = false; @@ -2555,7 +2629,8 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent, // iterate through the style runs int32 length = offset; 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; *outDescent = (descent > *outDescent) ? descent : *outDescent; @@ -2563,7 +2638,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent, length -= numChars; } - return (offset); + return offset; } // wrap the text @@ -2684,7 +2759,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent, offset = (offset < limit) ? offset : limit; - return (offset); + return offset; } //------------------------------------------------------------------------------ float @@ -2699,7 +2774,8 @@ BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent, // iterate through the style runs 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; maxDescent = (descent > maxDescent) ? descent : maxDescent; @@ -2714,7 +2790,7 @@ BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent, if (outDescent != NULL) *outDescent = maxDescent; - return (result); + return result; } //------------------------------------------------------------------------------ float @@ -2807,7 +2883,8 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset, long offset = line->offset; const BFont *font = 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); SetHighColor(*color); @@ -2946,74 +3023,75 @@ void BTextView::InitiateDrag() { BMessage *drag = new BMessage(); + BBitmap *dragBitmap = NULL; + BPoint bitmapPoint; + BHandler *dragHandler = NULL; - // add the text - drag->AddData("text", B_ASCII_TYPE, fText->Text() + fSelStart, - fSelEnd - fSelStart); + GetDragParameters(drag, &dragBitmap, &bitmapPoint, &dragHandler); - // add the corresponding styles - int32 size = 0; - text_run_array *styles = RunArray(fSelStart, fSelEnd, &size); + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); - drag->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE, - styles, size); - - BRegion hiliteRgn; - GetTextRegion(fSelStart, fSelEnd, &hiliteRgn); - BRect bounds = Bounds(); - BRect dragRect = hiliteRgn.Frame(); - if (!bounds.Contains(dragRect)) - dragRect = bounds & dragRect; - - be_app->SetCursor(B_HAND_CURSOR); - DragMessage(drag, dragRect); + if (dragBitmap != NULL) + DragMessage(drag, dragBitmap, bitmapPoint, dragHandler); + else { + BRegion hiliteRgn; + GetTextRegion(fSelStart, fSelEnd, &hiliteRgn); + BRect bounds = Bounds(); + BRect dragRect = hiliteRgn.Frame(); + if (!bounds.Contains(dragRect)) + dragRect = bounds & dragRect; + + DragMessage(drag, dragRect, dragHandler); + } } //------------------------------------------------------------------------------ bool BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset) { - // make sure the drag caret is erased - DragCaret(-1); - if (fActive) - be_app->SetCursor(B_I_BEAM_CURSOR); + SetViewCursor(B_CURSOR_I_BEAM); // are we sure we like this message? if (!AcceptsDrop(inMessage)) return false; 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 ((fActive) && (fSelStart != fSelEnd)) { + if (internalDrop) { // dropping onto itself? - if ((dropOffset >= fSelStart) && (dropOffset <= fSelEnd)) - return true; - - if (dropOffset > fSelEnd) - dropOffset -= fSelEnd - fSelStart; - - Delete(); + if (dropOffset >= fSelStart && dropOffset <= fSelEnd) + return true; } - - Select(dropOffset, dropOffset); ssize_t dataLen = 0; - const char *text; - inMessage->FindData("text", B_ASCII_TYPE, (const void**)&text, &dataLen); - /*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); - }*/ + const char *text = NULL; + if (inMessage->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &dataLen) == B_OK) { + 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; } //------------------------------------------------------------------------------ @@ -3061,11 +3139,19 @@ BTextView::AutoResize(bool doredraw) void BTextView::NewOffscreen(float padding) { + if (fOffscreen) + DeleteOffscreen(); + + //TODO: Implement } //------------------------------------------------------------------------------ void BTextView::DeleteOffscreen() { + if (fOffscreen && fOffscreen->Lock()) { + delete fOffscreen; + fOffscreen = NULL; + } } //------------------------------------------------------------------------------ void @@ -3086,7 +3172,7 @@ BTextView::Activate() ulong buttons; GetMouse(&where, &buttons); if (Bounds().Contains(where)) - be_app->SetCursor(B_I_BEAM_CURSOR); + SetViewCursor(B_CURSOR_I_BEAM); } //------------------------------------------------------------------------------ void @@ -3107,7 +3193,7 @@ BTextView::Deactivate() ulong buttons; GetMouse(&where, &buttons); if (Bounds().Contains(where)) - be_app->SetCursor(B_HAND_CURSOR); + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); } //------------------------------------------------------------------------------ void @@ -3126,11 +3212,22 @@ BTextView::CharClassification(int32 offset) const // japanese word breakers switch (fText->RealCharAt(offset)) { case B_SPACE: - 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; default: return B_OTHER_CHARACTER; diff --git a/src/kits/interface/BTextView/UndoBuffer.cpp b/src/kits/interface/BTextView/UndoBuffer.cpp index dfadaa113b..ecd2aba002 100644 --- a/src/kits/interface/BTextView/UndoBuffer.cpp +++ b/src/kits/interface/BTextView/UndoBuffer.cpp @@ -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 (burton666@libero.it) +// Description: _BUndoBuffer_ and its subclasses +// handle different types of Undo operations. +//------------------------------------------------------------------------------ +// Standard Includes ----------------------------------------------------------- #include #include #include +// System Includes ------------------------------------------------------------- #include -// ******** _BUndoBuffer_ ******* +// Local Includes -------------------------------------------------------------- +#include "UndoBuffer.h" + +// ******** _BUndoBuffer_ ******* _BUndoBuffer_::_BUndoBuffer_(BTextView *textView, undo_state state) : fTextView(textView), - fState(state), - fRedo(false), + fTextData(NULL), fRunArray(NULL), - fRunArrayLength(0) - + fRunArrayLength(0), + fRedo(false), + fState(state) { fTextView->GetSelection(&fStart, &fEnd); fTextLength = fEnd - fStart; - fTextData = (char*)malloc(fTextLength); + fTextData = (char *)malloc(fTextLength); memcpy(fTextData, fTextView->Text() + fStart, fTextLength); if (fTextView->IsStylable()) @@ -70,7 +100,8 @@ _BUndoBuffer_::RedoSelf(BClipboard *clipboard) // ******** _BCutUndoBuffer_ ******* _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_(BTextView *textView, const char *text, int32 textLen, text_run_array *runArray, int32 runArrayLen) - :_BUndoBuffer_(textView, B_UNDO_PASTE), + : + _BUndoBuffer_(textView, B_UNDO_PASTE), fPasteText(NULL), fPasteTextLength(textLen), - fPasteRunArray(NULL) + fPasteRunArray(NULL), + fPasteRunArrayLength(0) { fPasteText = (char *)malloc(fPasteTextLength); memcpy(fPasteText, text, fPasteTextLength); @@ -166,3 +199,164 @@ _BClearUndoBuffer_::RedoSelf(BClipboard *clipboard) fTextView->Select(fStart, fStart); 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(); +} diff --git a/src/kits/interface/BTextView/UndoBuffer.h b/src/kits/interface/BTextView/UndoBuffer.h index a9938b2b5f..66c184cd9a 100644 --- a/src/kits/interface/BTextView/UndoBuffer.h +++ b/src/kits/interface/BTextView/UndoBuffer.h @@ -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 (burton666@libero.it) +// Description: _BUndoBuffer_ and its subclasses +// handle different types of Undo operations. +//------------------------------------------------------------------------------ #ifndef __UNDOBUFFER_H #define __UNDOBUFFER_H +// System Includes ------------------------------------------------------------- #include class BClipboard; + class _BUndoBuffer_ { public: @@ -25,10 +53,10 @@ protected: int32 fTextLength; text_run_array *fRunArray; int32 fRunArrayLength; - + + bool fRedo; private: 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