File: | home/HaikuArchives/ArtPaint/artpaint/application/UndoQueue.cpp |
Warning: | line 485, column 12 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright 2003, Heikki Suhonen | |||
3 | * Distributed under the terms of the MIT License. | |||
4 | * | |||
5 | * Authors: | |||
6 | * Heikki Suhonen <heikki.suhonen@gmail.com> | |||
7 | * Dale Cieslak <dcieslak@yahoo.com> | |||
8 | * | |||
9 | */ | |||
10 | ||||
11 | #include "UndoQueue.h" | |||
12 | ||||
13 | #include "Image.h" | |||
14 | #include "Selection.h" | |||
15 | #include "SettingsServer.h" | |||
16 | ||||
17 | ||||
18 | #include <Alert.h> | |||
19 | #include <Catalog.h> | |||
20 | #include <MenuItem.h> | |||
21 | ||||
22 | ||||
23 | #include <new> | |||
24 | #include <stdio.h> | |||
25 | ||||
26 | ||||
27 | #undef B_TRANSLATION_CONTEXT"UndoQueue" | |||
28 | #define B_TRANSLATION_CONTEXT"UndoQueue" "UndoQueue" | |||
29 | ||||
30 | int32 UndoQueue::maximum_queue_depth = 10; | |||
31 | BList* UndoQueue::queue_list = new BList(); | |||
32 | ||||
33 | ||||
34 | UndoQueue::UndoQueue(BMenuItem *undo_item,BMenuItem *redo_item,ImageView *iv) | |||
35 | { | |||
36 | image_view = iv; | |||
37 | layer_bitmaps = NULL__null; | |||
38 | layer_bitmap_count = 0; | |||
39 | ||||
40 | undo_menu_item = undo_item; | |||
41 | redo_menu_item = redo_item; | |||
42 | current_event = NULL__null; | |||
43 | first_event = NULL__null; | |||
44 | last_event = NULL__null; | |||
45 | ||||
46 | current_queue_depth = 0; | |||
47 | ||||
48 | queue_list->AddItem(this); | |||
49 | ||||
50 | selection_data = new SelectionData(); | |||
51 | ||||
52 | UpdateMenuItems(); | |||
53 | } | |||
54 | ||||
55 | ||||
56 | UndoQueue::UndoQueue(BFile&) | |||
57 | { | |||
58 | } | |||
59 | ||||
60 | ||||
61 | UndoQueue::~UndoQueue() | |||
62 | { | |||
63 | UndoEvent *spare_event = first_event; | |||
64 | while (spare_event != NULL__null) { | |||
65 | first_event = spare_event->next_event; | |||
66 | delete spare_event; | |||
67 | spare_event = first_event; | |||
68 | } | |||
69 | ||||
70 | queue_list->RemoveItem(this); | |||
71 | ||||
72 | for (int32 i=0;i<layer_bitmap_count;i++) { | |||
73 | delete layer_bitmaps[i]; | |||
74 | layer_bitmaps[i] = NULL__null; | |||
75 | } | |||
76 | delete[] layer_bitmaps; | |||
77 | ||||
78 | delete selection_data; | |||
79 | } | |||
80 | ||||
81 | ||||
82 | UndoEvent* UndoQueue::AddUndoEvent(const char *name,const BBitmap *thumbnail,bool remove_tail) | |||
83 | { | |||
84 | if (maximum_queue_depth == 0) | |||
85 | return NULL__null; | |||
86 | ||||
87 | UndoEvent *event = new UndoEvent(name,thumbnail); | |||
88 | current_queue_depth++; | |||
89 | ||||
90 | if (remove_tail == FALSE0) { | |||
91 | // Insert the new event in between. | |||
92 | if (current_event != NULL__null) { | |||
93 | event->next_event = current_event->next_event; | |||
94 | event->previous_event = current_event; | |||
95 | event->next_event->previous_event = event; | |||
96 | current_event->next_event = event; | |||
97 | } | |||
98 | } | |||
99 | else { | |||
100 | UndoEvent *spare_event; | |||
101 | if (current_event != NULL__null) | |||
102 | spare_event = current_event->next_event; | |||
103 | else { | |||
104 | spare_event = first_event; | |||
105 | first_event = NULL__null; | |||
106 | } | |||
107 | // Delete the rest of the events | |||
108 | while (spare_event != NULL__null) { | |||
109 | UndoEvent *another_spare_event = spare_event->next_event; | |||
110 | delete spare_event; | |||
111 | spare_event = another_spare_event; | |||
112 | current_queue_depth--; | |||
113 | } | |||
114 | ||||
115 | if (current_event != NULL__null) { | |||
116 | current_event->next_event = event; | |||
117 | event->previous_event = current_event; | |||
118 | } | |||
119 | } | |||
120 | ||||
121 | if (first_event == NULL__null) | |||
122 | first_event = event; | |||
123 | current_event = event; | |||
124 | ||||
125 | event->SetQueue(this); | |||
126 | ||||
127 | TruncateQueue(); | |||
128 | ||||
129 | UpdateMenuItems(); | |||
130 | return event; | |||
131 | } | |||
132 | ||||
133 | ||||
134 | status_t UndoQueue::RemoveEvent(UndoEvent *event) | |||
135 | { | |||
136 | current_queue_depth--; | |||
137 | ||||
138 | UndoEvent *spare_event = first_event; | |||
139 | while ((spare_event != event) && (spare_event != NULL__null)) { | |||
140 | spare_event = spare_event->next_event; | |||
141 | } | |||
142 | if (spare_event == NULL__null) | |||
143 | return B_ERROR(-1); | |||
144 | ||||
145 | ||||
146 | // If the current event is the event that is removed we must change the | |||
147 | // current event also. At the moment this should happen always. | |||
148 | if (current_event == spare_event) { | |||
149 | if (event->previous_event != NULL__null) | |||
150 | current_event = spare_event->previous_event; | |||
151 | else | |||
152 | current_event = spare_event->next_event; | |||
153 | } | |||
154 | ||||
155 | ||||
156 | // If the first event is the removed one, we should also update its | |||
157 | // status. | |||
158 | if (first_event == spare_event) { | |||
159 | first_event = spare_event->next_event; | |||
160 | } | |||
161 | ||||
162 | // Unlink the event | |||
163 | if (spare_event->previous_event != NULL__null) { | |||
164 | spare_event->previous_event->next_event = spare_event->next_event; | |||
165 | } | |||
166 | if (spare_event->next_event != NULL__null) { | |||
167 | spare_event->next_event->previous_event = spare_event->previous_event; | |||
168 | } | |||
169 | ||||
170 | ||||
171 | UpdateMenuItems(); | |||
172 | return B_OK((int)0); | |||
173 | } | |||
174 | ||||
175 | BBitmap* UndoQueue::ReturnLayerSpareBitmap(int32 layer_id,BBitmap *layer_bitmap) | |||
176 | { | |||
177 | if (layer_id > layer_bitmap_count-1) { | |||
178 | BBitmap **new_bitmaps = new BBitmap*[layer_id+1]; | |||
179 | for (int32 i=0;i<layer_id+1;i++) | |||
180 | new_bitmaps[i] = NULL__null; | |||
181 | ||||
182 | for (int32 i=0;i<layer_bitmap_count;i++) { | |||
183 | new_bitmaps[i] = layer_bitmaps[i]; | |||
184 | layer_bitmaps[i] = NULL__null; | |||
185 | } | |||
186 | ||||
187 | delete[] layer_bitmaps; | |||
188 | layer_bitmaps = new_bitmaps; | |||
189 | layer_bitmap_count = layer_id+1; | |||
190 | } | |||
191 | ||||
192 | if (layer_bitmaps[layer_id] == NULL__null) { | |||
193 | if (layer_bitmap != NULL__null) { | |||
194 | layer_bitmaps[layer_id] = new BBitmap(layer_bitmap->Bounds(),B_RGB32); | |||
195 | if (layer_bitmaps[layer_id]->IsValid() == FALSE0) | |||
196 | throw std::bad_alloc(); | |||
197 | } | |||
198 | } | |||
199 | ||||
200 | return layer_bitmaps[layer_id]; | |||
201 | } | |||
202 | ||||
203 | ||||
204 | status_t UndoQueue::ChangeLayerSpareBitmap(int32 layer_id, BBitmap *layer_bitmap) | |||
205 | { | |||
206 | // This function doesn't delete the old bitmap. | |||
207 | if (layer_id > layer_bitmap_count-1) { | |||
208 | BBitmap **new_bitmaps = new BBitmap*[layer_id+1]; | |||
209 | for (int32 i=0;i<layer_id+1;i++) | |||
210 | new_bitmaps[i] = NULL__null; | |||
211 | ||||
212 | for (int32 i=0;i<layer_bitmap_count;i++) { | |||
213 | new_bitmaps[i] = layer_bitmaps[i]; | |||
214 | layer_bitmaps[i] = NULL__null; | |||
215 | } | |||
216 | delete[] layer_bitmaps; | |||
217 | layer_bitmaps = new_bitmaps; | |||
218 | layer_bitmap_count = layer_id+1; | |||
219 | } | |||
220 | ||||
221 | if (layer_bitmap != NULL__null) { | |||
222 | layer_bitmaps[layer_id] = new BBitmap(layer_bitmap->Bounds(),B_RGB32); | |||
223 | if (layer_bitmaps[layer_id]->IsValid() == FALSE0) | |||
224 | throw std::bad_alloc(); | |||
225 | ||||
226 | uint32 *spare_bits = (uint32*)layer_bitmaps[layer_id]->Bits(); | |||
227 | uint32 *bits = (uint32*)layer_bitmap->Bits(); | |||
228 | uint32 bitslength = layer_bitmap->BitsLength()/4; | |||
229 | for (uint32 i = 0; i < bitslength; i++) | |||
230 | *spare_bits++ = *bits++; | |||
231 | } | |||
232 | else { | |||
233 | layer_bitmaps[layer_id] = NULL__null; | |||
234 | } | |||
235 | return B_OK((int)0); | |||
236 | } | |||
237 | ||||
238 | ||||
239 | ||||
240 | void UndoQueue::RegisterLayer(int32 layer_id,BBitmap *layer_bitmap) | |||
241 | { | |||
242 | if ((maximum_queue_depth > 0) || (maximum_queue_depth == INFINITE_QUEUE_DEPTH-1)) { | |||
243 | if (layer_id > layer_bitmap_count-1) { | |||
244 | BBitmap **new_bitmaps = new BBitmap*[layer_id+1]; | |||
245 | for (int32 i=0;i<layer_id+1;i++) | |||
246 | new_bitmaps[i] = NULL__null; | |||
247 | ||||
248 | for (int32 i=0;i<layer_bitmap_count;i++) { | |||
249 | new_bitmaps[i] = layer_bitmaps[i]; | |||
250 | layer_bitmaps[i] = NULL__null; | |||
251 | } | |||
252 | delete[] layer_bitmaps; | |||
253 | layer_bitmaps = new_bitmaps; | |||
254 | layer_bitmap_count = layer_id+1; | |||
255 | ||||
256 | } | |||
257 | ||||
258 | if (layer_bitmaps[layer_id] == NULL__null) { | |||
259 | if (layer_bitmap != NULL__null) { | |||
260 | layer_bitmaps[layer_id] = new BBitmap(layer_bitmap->Bounds(),B_RGB32); | |||
261 | if (layer_bitmaps[layer_id]->IsValid() == FALSE0) | |||
262 | throw std::bad_alloc(); | |||
263 | ||||
264 | uint32 *source_bits = (uint32*)layer_bitmap->Bits(); | |||
265 | uint32 *target_bits = (uint32*)layer_bitmaps[layer_id]->Bits(); | |||
266 | int32 bitslength = layer_bitmap->BitsLength()/4; | |||
267 | ||||
268 | for (int32 i=0;i<bitslength;i++) | |||
269 | *target_bits++ = *source_bits++; | |||
270 | } | |||
271 | } | |||
272 | } | |||
273 | } | |||
274 | ||||
275 | ||||
276 | UndoEvent* UndoQueue::Undo() | |||
277 | { | |||
278 | UndoEvent *returned_event = NULL__null; | |||
279 | ||||
280 | if (current_event != NULL__null) { | |||
281 | returned_event = current_event; | |||
282 | current_event = current_event->previous_event; | |||
283 | if (returned_event->ActionCount() == 1) { | |||
284 | if (returned_event->ReturnActions()[0]->type == ADD_LAYER_ACTION) { | |||
285 | // This event should be removed. | |||
286 | current_event = returned_event; | |||
287 | returned_event = NULL__null; | |||
288 | } | |||
289 | } | |||
290 | } | |||
291 | ||||
292 | UpdateMenuItems(); | |||
293 | return returned_event; | |||
294 | } | |||
295 | ||||
296 | ||||
297 | UndoEvent* UndoQueue::Redo() | |||
298 | { | |||
299 | UndoEvent *returned_event = NULL__null; | |||
300 | if (current_event == NULL__null) | |||
301 | returned_event = current_event = first_event; | |||
302 | else { | |||
303 | if (current_event->next_event != NULL__null) { | |||
304 | current_event = current_event->next_event; | |||
305 | returned_event = current_event; | |||
306 | } | |||
307 | } | |||
308 | UpdateMenuItems(); | |||
309 | return returned_event; | |||
310 | } | |||
311 | ||||
312 | ||||
313 | ||||
314 | const char* UndoQueue::ReturnUndoEventName() | |||
315 | { | |||
316 | const char *name = NULL__null; | |||
317 | ||||
318 | UndoEvent *named_event = current_event; | |||
319 | if (named_event != NULL__null) { | |||
320 | UndoAction **actions = named_event->ReturnActions(); | |||
321 | if (actions != NULL__null) { | |||
322 | if ((named_event->ActionCount() > 1) || (actions[0]->type != ADD_LAYER_ACTION)) { | |||
323 | name = named_event->ReturnName(); | |||
324 | } | |||
325 | } | |||
326 | else | |||
327 | name = named_event->ReturnName(); | |||
328 | } | |||
329 | ||||
330 | return name; | |||
331 | } | |||
332 | ||||
333 | ||||
334 | const char* UndoQueue::ReturnRedoEventName() | |||
335 | { | |||
336 | const char *name = NULL__null; | |||
337 | ||||
338 | UndoEvent *named_event; | |||
339 | if (current_event != NULL__null) { | |||
340 | named_event = current_event->next_event; | |||
341 | } | |||
342 | else | |||
343 | named_event = first_event; | |||
344 | ||||
345 | if (named_event != NULL__null) | |||
346 | name = named_event->ReturnName(); | |||
347 | ||||
348 | return name; | |||
349 | } | |||
350 | ||||
351 | ||||
352 | ||||
353 | void UndoQueue::UpdateMenuItems() | |||
354 | { | |||
355 | const char *event_name; | |||
356 | event_name = ReturnUndoEventName(); | |||
357 | ||||
358 | if (undo_menu_item != NULL__null) { | |||
359 | if (event_name != NULL__null) { | |||
360 | char menu_text[256]; | |||
361 | sprintf(menu_text,"%s %s",B_TRANSLATE("Undo")BLocaleRoster::Default()->GetCatalog()->GetString(("Undo" ), "UndoQueue"),event_name); | |||
362 | undo_menu_item->SetLabel(menu_text); | |||
363 | undo_menu_item->SetEnabled(TRUE1); | |||
364 | } | |||
365 | else { | |||
366 | undo_menu_item->SetLabel(B_TRANSLATE("Undo not available")BLocaleRoster::Default()->GetCatalog()->GetString(("Undo not available" ), "UndoQueue")); | |||
367 | undo_menu_item->SetEnabled(FALSE0); | |||
368 | } | |||
369 | } | |||
370 | ||||
371 | event_name = ReturnRedoEventName(); | |||
372 | if (redo_menu_item != NULL__null) { | |||
373 | if (event_name != NULL__null) { | |||
374 | char menu_text[256]; | |||
375 | sprintf(menu_text,"%s %s",B_TRANSLATE("Redo")BLocaleRoster::Default()->GetCatalog()->GetString(("Redo" ), "UndoQueue"),event_name); | |||
376 | redo_menu_item->SetLabel(menu_text); | |||
377 | redo_menu_item->SetEnabled(TRUE1); | |||
378 | } | |||
379 | else { | |||
380 | redo_menu_item->SetLabel(B_TRANSLATE("Redo not available")BLocaleRoster::Default()->GetCatalog()->GetString(("Redo not available" ), "UndoQueue")); | |||
381 | redo_menu_item->SetEnabled(FALSE0); | |||
382 | } | |||
383 | } | |||
384 | } | |||
385 | ||||
386 | ||||
387 | void UndoQueue::SetMenuItems(BMenuItem *undo_item,BMenuItem *redo_item) | |||
388 | { | |||
389 | undo_menu_item = undo_item; | |||
390 | redo_menu_item = redo_item; | |||
391 | UpdateMenuItems(); | |||
392 | } | |||
393 | ||||
394 | ||||
395 | void UndoQueue::HandleLowMemorySituation() | |||
396 | { | |||
397 | BAlert *memory_alert = new BAlert("memory_alert", B_TRANSLATE(BLocaleRoster::Default()->GetCatalog()->GetString(("The undo-mechanism has run out of memory.\n" "The depth of undo will be limited so that the most recent events can be kept in memory. " "It is advisable to save your work at this point to avoid any loss of data in case the " "memory runs out completely.\n" "You may also want to adjust the undo-depth in the settings-window." ), "UndoQueue") | |||
398 | "The undo-mechanism has run out of memory.\n"BLocaleRoster::Default()->GetCatalog()->GetString(("The undo-mechanism has run out of memory.\n" "The depth of undo will be limited so that the most recent events can be kept in memory. " "It is advisable to save your work at this point to avoid any loss of data in case the " "memory runs out completely.\n" "You may also want to adjust the undo-depth in the settings-window." ), "UndoQueue") | |||
399 | "The depth of undo will be limited so that the most recent events can be kept in memory. "BLocaleRoster::Default()->GetCatalog()->GetString(("The undo-mechanism has run out of memory.\n" "The depth of undo will be limited so that the most recent events can be kept in memory. " "It is advisable to save your work at this point to avoid any loss of data in case the " "memory runs out completely.\n" "You may also want to adjust the undo-depth in the settings-window." ), "UndoQueue") | |||
400 | "It is advisable to save your work at this point to avoid any loss of data in case the "BLocaleRoster::Default()->GetCatalog()->GetString(("The undo-mechanism has run out of memory.\n" "The depth of undo will be limited so that the most recent events can be kept in memory. " "It is advisable to save your work at this point to avoid any loss of data in case the " "memory runs out completely.\n" "You may also want to adjust the undo-depth in the settings-window." ), "UndoQueue") | |||
401 | "memory runs out completely.\n"BLocaleRoster::Default()->GetCatalog()->GetString(("The undo-mechanism has run out of memory.\n" "The depth of undo will be limited so that the most recent events can be kept in memory. " "It is advisable to save your work at this point to avoid any loss of data in case the " "memory runs out completely.\n" "You may also want to adjust the undo-depth in the settings-window." ), "UndoQueue") | |||
402 | "You may also want to adjust the undo-depth in the settings-window.")BLocaleRoster::Default()->GetCatalog()->GetString(("The undo-mechanism has run out of memory.\n" "The depth of undo will be limited so that the most recent events can be kept in memory. " "It is advisable to save your work at this point to avoid any loss of data in case the " "memory runs out completely.\n" "You may also want to adjust the undo-depth in the settings-window." ), "UndoQueue"), | |||
403 | B_TRANSLATE("Bummer")BLocaleRoster::Default()->GetCatalog()->GetString(("Bummer" ), "UndoQueue"), NULL__null, NULL__null, B_WIDTH_AS_USUAL,B_WARNING_ALERT); | |||
404 | memory_alert->Go(); | |||
405 | ||||
406 | // We may have to delete either redo-events or undo-events. Currently this function is called | |||
407 | // only when there are no redo events so we only delete undo-events. This may change in the | |||
408 | // future however. | |||
409 | int32 deleted_event_count = 0; | |||
410 | UndoEvent *deleted_event = first_event; | |||
411 | while ((deleted_event_count < 5) && (deleted_event != NULL__null) && (deleted_event != current_event)) { | |||
412 | first_event = deleted_event->next_event; | |||
413 | first_event->previous_event = NULL__null; | |||
414 | delete deleted_event; | |||
415 | deleted_event = first_event; | |||
416 | deleted_event_count++; | |||
417 | current_queue_depth--; | |||
418 | } | |||
419 | } | |||
420 | ||||
421 | ||||
422 | void | |||
423 | UndoQueue::SetQueueDepth(int32 depth) | |||
424 | { | |||
425 | if ((depth != INFINITE_QUEUE_DEPTH-1) | |||
| ||||
426 | && ((depth < maximum_queue_depth) | |||
427 | || (maximum_queue_depth == INFINITE_QUEUE_DEPTH-1))) { | |||
428 | maximum_queue_depth = depth; | |||
429 | for (int32 i = 0; i < queue_list->CountItems(); i++) { | |||
430 | UndoQueue *queue = (UndoQueue*)queue_list->ItemAt(i); | |||
431 | queue->TruncateQueue(); | |||
432 | } | |||
433 | } | |||
434 | ||||
435 | if ((maximum_queue_depth == 0) && (depth != 0)) { | |||
436 | maximum_queue_depth = depth; | |||
437 | for (int32 i = 0; i < queue_list->CountItems(); i++) { | |||
438 | UndoQueue *queue = (UndoQueue*)queue_list->ItemAt(i); | |||
439 | queue->image_view->ReturnImage()->RegisterLayersWithUndo(); | |||
440 | } | |||
441 | } | |||
442 | ||||
443 | maximum_queue_depth = depth; | |||
444 | ||||
445 | if (SettingsServer* server = SettingsServer::Instance()) | |||
446 | server->SetValue(SettingsServer::Application, skUndoQueueDepth, depth); | |||
447 | } | |||
448 | ||||
449 | ||||
450 | void | |||
451 | UndoQueue::TruncateQueue() | |||
452 | { | |||
453 | if ((maximum_queue_depth != INFINITE_QUEUE_DEPTH-1) && (current_queue_depth > maximum_queue_depth)) { | |||
454 | while (current_queue_depth > maximum_queue_depth
| |||
455 | // We should remove the events so that the nearest events to the current | |||
456 | // event from both sides are removed last, and the furthest away events | |||
457 | // first. If needed the actual current event is then removed at the end. | |||
458 | ||||
459 | // search the furhest away event from the current_event, or if current event | |||
460 | // is NULL, from the first_event. If both are NULL, put the current_queue_length to | |||
461 | // zero. | |||
462 | UndoEvent *furthest_event = NULL__null; | |||
463 | if (current_event
| |||
464 | UndoEvent *redo_direction=current_event; | |||
465 | UndoEvent *undo_direction=current_event; | |||
466 | while ((undo_direction != NULL__null) && (redo_direction != NULL__null)) { | |||
467 | undo_direction = undo_direction->previous_event; | |||
468 | redo_direction = redo_direction->next_event; | |||
469 | } | |||
470 | if (undo_direction != NULL__null) { | |||
471 | while (undo_direction->previous_event != NULL__null) | |||
472 | undo_direction = undo_direction->previous_event; | |||
473 | furthest_event = undo_direction; | |||
474 | } | |||
475 | else if (redo_direction != NULL__null) { | |||
476 | while (redo_direction->next_event != NULL__null) | |||
477 | redo_direction = redo_direction->next_event; | |||
478 | furthest_event = redo_direction; | |||
479 | } | |||
480 | else | |||
481 | furthest_event = first_event; | |||
482 | } | |||
483 | else if (first_event
| |||
484 | furthest_event = first_event; | |||
485 | while (furthest_event->next_event != NULL__null) | |||
| ||||
486 | furthest_event = furthest_event->next_event; | |||
487 | } | |||
488 | else | |||
489 | current_queue_depth = 0; | |||
490 | ||||
491 | if (furthest_event == first_event) { | |||
492 | if (first_event
| |||
493 | first_event = first_event->next_event; | |||
494 | } | |||
495 | ||||
496 | if (current_event == furthest_event
| |||
497 | current_event = NULL__null; | |||
498 | ||||
499 | ||||
500 | // Here we should unlink the furthest_event and delete it. | |||
501 | // Also decrease the current undo-depth by one | |||
502 | if (furthest_event
| |||
503 | if (furthest_event->next_event
| |||
504 | furthest_event->next_event->previous_event = furthest_event->previous_event; | |||
505 | if (furthest_event->previous_event != NULL__null) | |||
506 | furthest_event->previous_event->next_event = furthest_event->next_event; | |||
507 | ||||
508 | furthest_event->next_event = NULL__null; | |||
509 | furthest_event->previous_event = NULL__null; | |||
510 | ||||
511 | delete furthest_event; | |||
512 | } | |||
513 | current_queue_depth--; | |||
514 | } | |||
515 | } | |||
516 | ||||
517 | if (maximum_queue_depth == 0) { | |||
518 | // Delete everything. | |||
519 | for (int32 i=0;i<layer_bitmap_count;i++) { | |||
520 | delete layer_bitmaps[i]; | |||
521 | layer_bitmaps[i] = NULL__null; | |||
522 | } | |||
523 | delete[] layer_bitmaps; | |||
524 | layer_bitmap_count = 0; | |||
525 | current_queue_depth = 0; | |||
526 | layer_bitmaps = NULL__null; | |||
527 | } | |||
528 | ||||
529 | UpdateMenuItems(); | |||
530 | } | |||
531 | ||||
532 | ||||
533 | void | |||
534 | UndoQueue::SetSelectionData(const SelectionData *s) | |||
535 | { | |||
536 | delete selection_data; | |||
537 | selection_data = new SelectionData(s); | |||
538 | } |