btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / interface / textview_support / UndoBuffer.cpp
blob2f8759c1761fffc12d5cf72ba7763284265334a5
1 /*
2 * Copyright 2003-2008, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stefano Ceccherini (burton666@libero.it)
7 */
9 //! UndoBuffer and its subclasses handle different types of Undo operations.
12 #include "UndoBuffer.h"
13 #include "utf8_functions.h"
15 #include <Clipboard.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
22 // TODO: properly document this file
25 // #pragma mark - UndoBuffer
28 BTextView::UndoBuffer::UndoBuffer(BTextView* textView, undo_state state)
30 fTextView(textView),
31 fTextData(NULL),
32 fRunArray(NULL),
33 fRunArrayLength(0),
34 fRedo(false),
35 fState(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()
50 free(fTextData);
51 BTextView::FreeRunArray(fRunArray);
55 void
56 BTextView::UndoBuffer::Undo(BClipboard* clipboard)
58 fRedo ? RedoSelf(clipboard) : UndoSelf(clipboard);
60 fRedo = !fRedo;
64 undo_state
65 BTextView::UndoBuffer::State(bool* _isRedo) const
67 *_isRedo = fRedo;
69 return fState;
73 void
74 BTextView::UndoBuffer::UndoSelf(BClipboard* clipboard)
76 fTextView->Select(fStart, fStart);
77 fTextView->Insert(fTextData, fTextLength, fRunArray);
78 fTextView->Select(fStart, fStart);
82 void
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()
102 void
103 BTextView::CutUndoBuffer::RedoSelf(BClipboard* clipboard)
105 BMessage* clip = NULL;
107 fTextView->Select(fStart, fStart);
108 fTextView->Delete(fStart, fEnd);
109 if (clipboard->Lock()) {
110 clipboard->Clear();
111 if ((clip = clipboard->Data())) {
112 clip->AddData("text/plain", B_MIME_TYPE, fTextData, fTextLength);
113 if (fRunArray)
114 clip->AddData("application/x-vnd.Be-text_run_array",
115 B_MIME_TYPE, fRunArray, fRunArrayLength);
116 clipboard->Commit();
118 clipboard->Unlock();
123 // #pragma mark - PasteUndoBuffer
126 BTextView::PasteUndoBuffer::PasteUndoBuffer(BTextView* textView,
127 const char* text, int32 textLen, text_run_array* runArray,
128 int32 runArrayLen)
129 : BTextView::UndoBuffer(textView, B_UNDO_PASTE),
130 fPasteText(NULL),
131 fPasteTextLength(textLen),
132 fPasteRunArray(NULL)
134 fPasteText = (char*)malloc(fPasteTextLength);
135 memcpy(fPasteText, text, fPasteTextLength);
137 if (runArray)
138 fPasteRunArray = BTextView::CopyRunArray(runArray);
142 BTextView::PasteUndoBuffer::~PasteUndoBuffer()
144 free(fPasteText);
145 BTextView::FreeRunArray(fPasteRunArray);
149 void
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);
159 void
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()
183 void
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),
198 fDropText(NULL),
199 fDropTextLength(textLen),
200 fDropRunArray(NULL)
202 fInternalDrop = internalDrop;
203 fDropLocation = location;
205 fDropText = (char*)malloc(fDropTextLength);
206 memcpy(fDropText, text, fDropTextLength);
208 if (runArray)
209 fDropRunArray = BTextView::CopyRunArray(runArray);
211 if (fInternalDrop && fDropLocation >= fEnd)
212 fDropLocation -= fDropTextLength;
216 BTextView::DropUndoBuffer::~DropUndoBuffer()
218 free(fDropText);
219 BTextView::FreeRunArray(fDropRunArray);
223 void
224 BTextView::DropUndoBuffer::UndoSelf(BClipboard* )
226 fTextView->Select(fDropLocation, fDropLocation);
227 fTextView->Delete(fDropLocation, fDropLocation + fDropTextLength);
228 if (fInternalDrop) {
229 fTextView->Select(fStart, fStart);
230 fTextView->Insert(fTextData, fTextLength, fRunArray);
232 fTextView->Select(fStart, fEnd);
236 void
237 BTextView::DropUndoBuffer::RedoSelf(BClipboard* )
239 if (fInternalDrop) {
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),
254 fTypedText(NULL),
255 fTypedStart(fStart),
256 fTypedEnd(fEnd),
257 fUndone(0)
262 BTextView::TypingUndoBuffer::~TypingUndoBuffer()
264 free(fTypedText);
268 void
269 BTextView::TypingUndoBuffer::UndoSelf(BClipboard* clipboard)
271 int32 len = fTypedEnd - fTypedStart;
273 free(fTypedText);
274 fTypedText = NULL;
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);
282 fUndone++;
286 void
287 BTextView::TypingUndoBuffer::RedoSelf(BClipboard* clipboard)
289 fTextView->Select(fTypedStart, fTypedStart);
290 fTextView->Delete(fTypedStart, fTypedStart + fTextLength);
291 fTextView->Insert(fTypedText, fTypedEnd - fTypedStart);
292 fUndone--;
296 void
297 BTextView::TypingUndoBuffer::InputCharacter(int32 len)
299 int32 start, end;
300 fTextView->GetSelection(&start, &end);
302 if (start != fTypedEnd || end != fTypedEnd)
303 _Reset();
305 fTypedEnd += len;
309 void
310 BTextView::TypingUndoBuffer::_Reset()
312 free(fTextData);
313 fTextView->GetSelection(&fStart, &fEnd);
314 fTextLength = fEnd - fStart;
315 fTypedStart = fStart;
316 fTypedEnd = fStart;
318 fTextData = (char*)malloc(fTextLength);
319 memcpy(fTextData, fTextView->Text() + fStart, fTextLength);
321 free(fTypedText);
322 fTypedText = NULL;
323 fRedo = false;
324 fUndone = 0;
328 void
329 BTextView::TypingUndoBuffer::BackwardErase()
331 int32 start, end;
332 fTextView->GetSelection(&start, &end);
334 const char* text = fTextView->Text();
335 int32 charLen = UTF8PreviousCharLen(text + start, text);
337 if (start != fTypedEnd || end != fTypedEnd) {
338 _Reset();
339 // if we've got a selection, we're already done
340 if (start != end)
341 return;
344 char* buffer = (char*)malloc(fTextLength + charLen);
345 memcpy(buffer + charLen, fTextData, fTextLength);
347 fTypedStart = start - charLen;
348 start = fTypedStart;
349 for (int32 x = 0; x < charLen; x++)
350 buffer[x] = fTextView->ByteAt(start + x);
351 free(fTextData);
352 fTextData = buffer;
354 fTextLength += charLen;
355 fTypedEnd -= charLen;
359 void
360 BTextView::TypingUndoBuffer::ForwardErase()
362 // TODO: Cleanup
363 int32 start, end;
365 fTextView->GetSelection(&start, &end);
367 int32 charLen = UTF8NextCharLen(fTextView->Text() + start);
369 if (start != fTypedEnd || end != fTypedEnd || fUndone > 0) {
370 _Reset();
371 // if we've got a selection, we're already done
372 if (fStart == fEnd) {
373 free(fTextData);
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);
381 } else {
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;
400 free(fTextData);
401 fTextData = buffer;