2 * Copyright 2003-2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Stefano Ceccherini (burton666@libero.it)
9 //! UndoBuffer and its subclasses handle different types of Undo operations.
12 #include "UndoBuffer.h"
13 #include "utf8_functions.h"
15 #include <Clipboard.h>
22 // TODO: properly document this file
25 // #pragma mark - UndoBuffer
28 BTextView::UndoBuffer::UndoBuffer(BTextView
* textView
, undo_state state
)
37 fTextView
->GetSelection(&fStart
, &fEnd
);
38 fTextLength
= fEnd
- fStart
;
40 fTextData
= (char*)malloc(fTextLength
);
41 memcpy(fTextData
, fTextView
->Text() + fStart
, fTextLength
);
43 if (fTextView
->IsStylable())
44 fRunArray
= fTextView
->RunArray(fStart
, fEnd
, &fRunArrayLength
);
48 BTextView::UndoBuffer::~UndoBuffer()
51 BTextView::FreeRunArray(fRunArray
);
56 BTextView::UndoBuffer::Undo(BClipboard
* clipboard
)
58 fRedo
? RedoSelf(clipboard
) : UndoSelf(clipboard
);
65 BTextView::UndoBuffer::State(bool* _isRedo
) const
74 BTextView::UndoBuffer::UndoSelf(BClipboard
* clipboard
)
76 fTextView
->Select(fStart
, fStart
);
77 fTextView
->Insert(fTextData
, fTextLength
, fRunArray
);
78 fTextView
->Select(fStart
, fStart
);
83 BTextView::UndoBuffer::RedoSelf(BClipboard
* clipboard
)
88 // #pragma mark - CutUndoBuffer
91 BTextView::CutUndoBuffer::CutUndoBuffer(BTextView
* textView
)
92 : BTextView::UndoBuffer(textView
, B_UNDO_CUT
)
97 BTextView::CutUndoBuffer::~CutUndoBuffer()
103 BTextView::CutUndoBuffer::RedoSelf(BClipboard
* clipboard
)
105 BMessage
* clip
= NULL
;
107 fTextView
->Select(fStart
, fStart
);
108 fTextView
->Delete(fStart
, fEnd
);
109 if (clipboard
->Lock()) {
111 if ((clip
= clipboard
->Data())) {
112 clip
->AddData("text/plain", B_MIME_TYPE
, fTextData
, fTextLength
);
114 clip
->AddData("application/x-vnd.Be-text_run_array",
115 B_MIME_TYPE
, fRunArray
, fRunArrayLength
);
123 // #pragma mark - PasteUndoBuffer
126 BTextView::PasteUndoBuffer::PasteUndoBuffer(BTextView
* textView
,
127 const char* text
, int32 textLen
, text_run_array
* runArray
,
129 : BTextView::UndoBuffer(textView
, B_UNDO_PASTE
),
131 fPasteTextLength(textLen
),
134 fPasteText
= (char*)malloc(fPasteTextLength
);
135 memcpy(fPasteText
, text
, fPasteTextLength
);
138 fPasteRunArray
= BTextView::CopyRunArray(runArray
);
142 BTextView::PasteUndoBuffer::~PasteUndoBuffer()
145 BTextView::FreeRunArray(fPasteRunArray
);
150 BTextView::PasteUndoBuffer::UndoSelf(BClipboard
* clipboard
)
152 fTextView
->Select(fStart
, fStart
);
153 fTextView
->Delete(fStart
, fStart
+ fPasteTextLength
);
154 fTextView
->Insert(fTextData
, fTextLength
, fRunArray
);
155 fTextView
->Select(fStart
, fEnd
);
160 BTextView::PasteUndoBuffer::RedoSelf(BClipboard
* clipboard
)
162 fTextView
->Select(fStart
, fStart
);
163 fTextView
->Delete(fStart
, fEnd
);
164 fTextView
->Insert(fPasteText
, fPasteTextLength
, fPasteRunArray
);
165 fTextView
->Select(fStart
+ fPasteTextLength
, fStart
+ fPasteTextLength
);
169 // #pragma mark - ClearUndoBuffer
172 BTextView::ClearUndoBuffer::ClearUndoBuffer(BTextView
* textView
)
173 : BTextView::UndoBuffer(textView
, B_UNDO_CLEAR
)
178 BTextView::ClearUndoBuffer::~ClearUndoBuffer()
184 BTextView::ClearUndoBuffer::RedoSelf(BClipboard
* clipboard
)
186 fTextView
->Select(fStart
, fStart
);
187 fTextView
->Delete(fStart
, fEnd
);
191 // #pragma mark - DropUndoBuffer
194 BTextView::DropUndoBuffer::DropUndoBuffer(BTextView
* textView
,
195 char const* text
, int32 textLen
, text_run_array
* runArray
,
196 int32 runArrayLen
, int32 location
, bool internalDrop
)
197 : BTextView::UndoBuffer(textView
, B_UNDO_DROP
),
199 fDropTextLength(textLen
),
202 fInternalDrop
= internalDrop
;
203 fDropLocation
= location
;
205 fDropText
= (char*)malloc(fDropTextLength
);
206 memcpy(fDropText
, text
, fDropTextLength
);
209 fDropRunArray
= BTextView::CopyRunArray(runArray
);
211 if (fInternalDrop
&& fDropLocation
>= fEnd
)
212 fDropLocation
-= fDropTextLength
;
216 BTextView::DropUndoBuffer::~DropUndoBuffer()
219 BTextView::FreeRunArray(fDropRunArray
);
224 BTextView::DropUndoBuffer::UndoSelf(BClipboard
* )
226 fTextView
->Select(fDropLocation
, fDropLocation
);
227 fTextView
->Delete(fDropLocation
, fDropLocation
+ fDropTextLength
);
229 fTextView
->Select(fStart
, fStart
);
230 fTextView
->Insert(fTextData
, fTextLength
, fRunArray
);
232 fTextView
->Select(fStart
, fEnd
);
237 BTextView::DropUndoBuffer::RedoSelf(BClipboard
* )
240 fTextView
->Select(fStart
, fStart
);
241 fTextView
->Delete(fStart
, fEnd
);
243 fTextView
->Select(fDropLocation
, fDropLocation
);
244 fTextView
->Insert(fDropText
, fDropTextLength
, fDropRunArray
);
245 fTextView
->Select(fDropLocation
, fDropLocation
+ fDropTextLength
);
249 // #pragma mark - TypingUndoBuffer
252 BTextView::TypingUndoBuffer::TypingUndoBuffer(BTextView
* textView
)
253 : BTextView::UndoBuffer(textView
, B_UNDO_TYPING
),
262 BTextView::TypingUndoBuffer::~TypingUndoBuffer()
269 BTextView::TypingUndoBuffer::UndoSelf(BClipboard
* clipboard
)
271 int32 len
= fTypedEnd
- fTypedStart
;
275 fTypedText
= (char*)malloc(len
);
276 memcpy(fTypedText
, fTextView
->Text() + fTypedStart
, len
);
278 fTextView
->Select(fTypedStart
, fTypedStart
);
279 fTextView
->Delete(fTypedStart
, fTypedEnd
);
280 fTextView
->Insert(fTextData
, fTextLength
);
281 fTextView
->Select(fStart
, fEnd
);
287 BTextView::TypingUndoBuffer::RedoSelf(BClipboard
* clipboard
)
289 fTextView
->Select(fTypedStart
, fTypedStart
);
290 fTextView
->Delete(fTypedStart
, fTypedStart
+ fTextLength
);
291 fTextView
->Insert(fTypedText
, fTypedEnd
- fTypedStart
);
297 BTextView::TypingUndoBuffer::InputCharacter(int32 len
)
300 fTextView
->GetSelection(&start
, &end
);
302 if (start
!= fTypedEnd
|| end
!= fTypedEnd
)
310 BTextView::TypingUndoBuffer::_Reset()
313 fTextView
->GetSelection(&fStart
, &fEnd
);
314 fTextLength
= fEnd
- fStart
;
315 fTypedStart
= fStart
;
318 fTextData
= (char*)malloc(fTextLength
);
319 memcpy(fTextData
, fTextView
->Text() + fStart
, fTextLength
);
329 BTextView::TypingUndoBuffer::BackwardErase()
332 fTextView
->GetSelection(&start
, &end
);
334 const char* text
= fTextView
->Text();
335 int32 charLen
= UTF8PreviousCharLen(text
+ start
, text
);
337 if (start
!= fTypedEnd
|| end
!= fTypedEnd
) {
339 // if we've got a selection, we're already done
344 char* buffer
= (char*)malloc(fTextLength
+ charLen
);
345 memcpy(buffer
+ charLen
, fTextData
, fTextLength
);
347 fTypedStart
= start
- charLen
;
349 for (int32 x
= 0; x
< charLen
; x
++)
350 buffer
[x
] = fTextView
->ByteAt(start
+ x
);
354 fTextLength
+= charLen
;
355 fTypedEnd
-= charLen
;
360 BTextView::TypingUndoBuffer::ForwardErase()
365 fTextView
->GetSelection(&start
, &end
);
367 int32 charLen
= UTF8NextCharLen(fTextView
->Text() + start
);
369 if (start
!= fTypedEnd
|| end
!= fTypedEnd
|| fUndone
> 0) {
371 // if we've got a selection, we're already done
372 if (fStart
== fEnd
) {
374 fTextLength
= charLen
;
375 fTextData
= (char*)malloc(fTextLength
);
377 // store the erased character
378 for (int32 x
= 0; x
< charLen
; x
++)
379 fTextData
[x
] = fTextView
->ByteAt(start
+ x
);
382 // Here we need to store the erased text, so we get the text that it's
383 // already in the buffer, and we add the erased character.
384 // a realloc + memmove would maybe be cleaner, but that way we spare a
385 // copy (malloc + memcpy vs realloc + memmove).
387 int32 newLength
= fTextLength
+ charLen
;
388 char* buffer
= (char*)malloc(newLength
);
390 // copy the already stored data
391 memcpy(buffer
, fTextData
, fTextLength
);
393 if (fTextLength
< newLength
) {
394 // store the erased character
395 for (int32 x
= 0; x
< charLen
; x
++)
396 buffer
[fTextLength
+ x
] = fTextView
->ByteAt(start
+ x
);
399 fTextLength
= newLength
;