static void memfile_undosys_step_free(UndoStep *us_p) { /* To avoid unnecessary slow down, free backwards (so we don't need to merge when clearing all). */ MemFileUndoStep *us = (MemFileUndoStep *)us_p; if (us_p->next != NULL) { UndoStep *us_next_p = BKE_undosys_step_same_type_next(us_p); if (us_next_p != NULL) { MemFileUndoStep *us_next = (MemFileUndoStep *)us_next_p; BLO_memfile_merge(&us->data->memfile, &us_next->data->memfile); } } BKE_memfile_undo_free(us->data); }
/* name can be a dynamic string */ void BKE_undo_write(bContext *C, const char *name) { uintptr_t maxmem, totmem, memused; int nr /*, success */ /* UNUSED */; UndoElem *uel; if ((U.uiflag & USER_GLOBALUNDO) == 0) { return; } if (U.undosteps == 0) { return; } /* remove all undos after (also when curundo == NULL) */ while (undobase.last != curundo) { uel = undobase.last; BLI_remlink(&undobase, uel); BLO_memfile_free(&uel->memfile); MEM_freeN(uel); } /* make new */ curundo = uel = MEM_callocN(sizeof(UndoElem), "undo file"); BLI_strncpy(uel->name, name, sizeof(uel->name)); BLI_addtail(&undobase, uel); /* and limit amount to the maximum */ nr = 0; uel = undobase.last; while (uel) { nr++; if (nr == U.undosteps) break; uel = uel->prev; } if (uel) { while (undobase.first != uel) { UndoElem *first = undobase.first; BLI_remlink(&undobase, first); /* the merge is because of compression */ BLO_memfile_merge(&first->memfile, &first->next->memfile); MEM_freeN(first); } } /* disk save version */ if (UNDO_DISK) { static int counter = 0; char filepath[FILE_MAX]; char numstr[32]; int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */ /* calculate current filepath */ counter++; counter = counter % U.undosteps; BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter); BLI_make_file_string("/", filepath, BKE_tempdir_session(), numstr); /* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); BLI_strncpy(curundo->str, filepath, sizeof(curundo->str)); } else { MemFile *prevfile = NULL; if (curundo->prev) prevfile = &(curundo->prev->memfile); memused = MEM_get_memory_in_use(); /* success = */ /* UNUSED */ BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags); curundo->undosize = MEM_get_memory_in_use() - memused; } if (U.undomemory != 0) { /* limit to maximum memory (afterwards, we can't know in advance) */ totmem = 0; maxmem = ((uintptr_t)U.undomemory) * 1024 * 1024; /* keep at least two (original + other) */ uel = undobase.last; while (uel && uel->prev) { totmem += uel->undosize; if (totmem > maxmem) break; uel = uel->prev; } if (uel) { if (uel->prev && uel->prev->prev) uel = uel->prev; while (undobase.first != uel) { UndoElem *first = undobase.first; BLI_remlink(&undobase, first); /* the merge is because of compression */ BLO_memfile_merge(&first->memfile, &first->next->memfile); MEM_freeN(first); } } } }