//--------------------------------------------------------------------------- #include #include #pragma hdrstop #include "Undo.h" //--------------------------------------------------------------------------- #pragma package(smart_init) TUndo *Undo; //--------------------------------------------------------------------------- // TUndoData //--------------------------------------------------------------------------- __fastcall TUndoData::TUndoData(int inst, char *szTmpFile) { Instance = inst; Filename = szTmpFile; IsMemory = true; IsFile = false; IsUse = false; Bitmap = Mask = NULL; Palette = NULL; Region = NULL; } //--------------------------------------------------------------------------- __fastcall TUndoData::~TUndoData() { if (IsFile) DeleteFile(Filename); if (Region) DeleteObject(Region); if (Palette) delete Palette; if (Mask) delete Mask; if (Bitmap) delete Bitmap; } //--------------------------------------------------------------------------- bool __fastcall TUndoData::SaveToFile(HANDLE fh, TTexpiaBitmap *Bitmap) { int w, h; WORD bpp; DWORD dwWrite; RGBQUAD rgb[256]; if (Bitmap) { w = Bitmap->Width; h = Bitmap->Height; bpp = Bitmap->BitsPerPixel; if (!WriteFile(fh, &w, sizeof(int), &dwWrite, NULL)) return false; if (!WriteFile(fh, &h, sizeof(int), &dwWrite, NULL)) return false; if (!WriteFile(fh, &bpp, sizeof(WORD), &dwWrite, NULL)) return false; if (bpp == 8) { Bitmap->GetColors(0, 256, rgb); if (!WriteFile(fh, &rgb, 256*sizeof(RGBQUAD), &dwWrite, NULL)) return false; } if (!Bitmap->SaveToTexpiaFile(fh, cmZLib)) return false; } return true; } //--------------------------------------------------------------------------- bool __fastcall TUndoData::LoadFromFile(HANDLE fh, TTexpiaBitmap *Bitmap) { int w, h; WORD bpp; DWORD dwRead; RGBQUAD rgb[256]; if (Bitmap) { if (!ReadFile(fh, &w, sizeof(int), &dwRead, NULL)) return false; if (!ReadFile(fh, &h, sizeof(int), &dwRead, NULL)) return false; if (!ReadFile(fh, &bpp, sizeof(WORD), &dwRead, NULL)) return false; if (bpp == 8) { if (!ReadFile(fh, &rgb, 256*sizeof(RGBQUAD), &dwRead, NULL)) return false; if (!Bitmap->Create(w, h, bpp, rgb)) return false; } else { if (!Bitmap->Create(w, h, bpp)) return false; } if (!Bitmap->LoadFromTexpiaFile(fh, cmZLib)) return false; } return true; } //--------------------------------------------------------------------------- bool __fastcall TUndoData::SaveToFile() { HANDLE hFile = INVALID_HANDLE_VALUE; if ((hFile = CreateFile(Filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) goto fail; if (Bitmap) { if (!SaveToFile(hFile, Bitmap)) goto fail; Bitmap->Destroy(); } if (Mask) { if (!SaveToFile(hFile, Mask)) goto fail; Mask->Destroy(); } CloseHandle(hFile); IsFile = true; IsMemory = false; return true; fail: if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); return false; } //--------------------------------------------------------------------------- bool __fastcall TUndoData::LoadFromFile() { HANDLE hFile = INVALID_HANDLE_VALUE; if (!IsMemory) { if ((hFile = CreateFile(Filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) goto fail; if (Bitmap) { if (!LoadFromFile(hFile, Bitmap)) goto fail; } if (Mask) { if (!LoadFromFile(hFile, Mask)) goto fail; } CloseHandle(hFile); IsMemory = true; } return true; fail: if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); return false; } //--------------------------------------------------------------------------- void __fastcall TUndoData::Complete() { IsUse = false; } //--------------------------------------------------------------------------- void __fastcall TUndoData::DestroyInMemory(bool bStart) { if (IsUse) return; if (IsFile) { if (IsMemory) { if (Bitmap) Bitmap->Destroy(); if (Mask) Mask->Destroy(); IsMemory = false; } } else { if (bStart) SaveToFile(); } } //--------------------------------------------------------------------------- bool __fastcall TUndoData::Equal(int inst) { return Instance == inst; } //--------------------------------------------------------------------------- // TUndo //--------------------------------------------------------------------------- __fastcall TUndo::TUndo() { Number = 0; DataList = new TList; FMethod = UM_STACK; Maximum = 3; } //--------------------------------------------------------------------------- __fastcall TUndo::~TUndo() { TUndoData *data; while (DataList->Count) { data = (TUndoData *)DataList->First(); delete data; DataList->Remove(data); } delete DataList; } //--------------------------------------------------------------------------- // Private Function //--------------------------------------------------------------------------- int __fastcall TUndo::GetCount() { int count = 0; for (int i = DataList->Count - 1; i >= 0; i--) { TUndoData *data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) count++; } return count; } //--------------------------------------------------------------------------- TUndoData *__fastcall TUndo::GetLast() { for (int i = DataList->Count - 1; i >= 0; i--) { TUndoData *data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) { data->LoadFromFile(); data->IsUse = true; return data; } } return NULL; } //--------------------------------------------------------------------------- void __fastcall TUndo::SetMethod(EUndoMethod Value) { if (FMethod != Value) FMethod = Value; } //--------------------------------------------------------------------------- bool __fastcall TUndo::SaveData(int k, RECT r, bool bSave) { TUndoData *data = NULL; RGBQUAD rgb[256]; BITMAPHANDLE *bh; RGNXFORM XForm; char szTmpFile[MAX_PATH+1]; sprintf(szTmpFile, "%s\\TPU%05x.TMP", DirectoryTemp.c_str(), Number); if (Number & 0xFFFFF) Number++; else Number = 1; if ((data = new TUndoData(Instance, szTmpFile))==NULL) goto fail; data->Range = r; if (k&UK_PATTERN) { if ((data->Bitmap = new TTexpiaBitmap)==NULL) goto fail; if (data->Bitmap->Create(r.right-r.left, r.bottom-r.top, Image->Bitmap->BitsPerPixel)==false) goto fail; if (Image->Bitmap->BitsPerPixel==8) { if (Palette) Palette->ToRGBQUAD(rgb, 256); else Image->Bitmap->GetColors(0, 256, rgb); data->Bitmap->PutColors(0, 256, rgb); } data->Bitmap->CopyFromRect(Image->Bitmap, r.left, r.top, SRCCOPY); if (Palette) { if ((data->Palette = new TPalette)==NULL) goto fail; data->Palette->SetPalette(Palette); } } if (k&UK_MASK) { if (Image->Mask) { if ((data->Mask = new TTexpiaBitmap)==NULL) goto fail; if (data->Mask->Create(r.right-r.left, r.bottom-r.top, Image->Mask->BitsPerPixel)==false) goto fail; if (Image->Mask->BitsPerPixel==8) { Image->Mask->GetColors(0, 256, rgb); data->Mask->PutColors(0, 256, rgb); } data->Mask->CopyFromRect(Image->Mask, r.left, r.top, SRCCOPY); } } if (k&UK_WORKAREA) { bh = Image->Bitmap->Handle; if (bh) { if (L_BitmapHasRgn(bh)) { XForm.uViewPerspective = TOP_LEFT; XForm.nXScalarNum = 1; XForm.nXScalarDen = 1; XForm.nYScalarNum = 1; XForm.nYScalarDen = 1; XForm.nXOffset = 0; XForm.nYOffset = 0; L_GetBitmapRgnHandle(bh, &XForm, &data->Region); } } } data->Kind = k; DataList->Add(data); if (bSave) Arrange(); return true; fail: if (data) delete data; return false; } //--------------------------------------------------------------------------- void __fastcall TUndo::ReadData(TUndoData *data) { RGBQUAD rgb[256]; RGNXFORM XForm; int fh, w, h; WORD bpp; if (data->Kind&UK_PATTERN) { if (data->Bitmap->BitsPerPixel == 8) { if (data->Palette) data->Palette->ToRGBQUAD(rgb, 256); else data->Bitmap->GetColors(0, 256, rgb); Image->Bitmap->PutColors(0, 256, rgb); } Image->Bitmap->CopyToRect(data->Range.left, data->Range.top, data->Bitmap, SRCCOPY); if (Palette) Palette->SetPalette(data->Palette); } if (data->Kind&UK_MASK) { if (Image->Mask && data->Mask) { if (data->Mask->BitsPerPixel == 8) { data->Mask->GetColors(0, 256, rgb); Image->Mask->PutColors(0, 256, rgb); } Image->Mask->CopyToRect(data->Range.left, data->Range.top, data->Mask, SRCCOPY); } } if (data->Kind&UK_WORKAREA) { if (data->Region) { XForm.uViewPerspective = TOP_LEFT; XForm.nXScalarNum = 1; XForm.nXScalarDen = 1; XForm.nYScalarNum = 1; XForm.nYScalarDen = 1; XForm.nXOffset = 0; XForm.nYOffset = 0; L_SetBitmapRgnHandle(Image->Bitmap->Handle, &XForm, data->Region, L_RGN_SET); WorkArea->SetMask(data->Region); } else { WorkArea->Reset(); } } } //--------------------------------------------------------------------------- void __fastcall TUndo::Arrange() { int i, n; TUndoData *data; if (DataList->Count <= 0) return; if (FMethod == UM_STACK) { n = 0; for (i = DataList->Count - 1; i >= 0; i--) { data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) { if (n > 0) { if (!data->IsFile) { data->SaveToFile(); } } else { data->DestroyInMemory(false); } n++; } else { data->DestroyInMemory(true); } } } else { for (i = DataList->Count - 1; i >= 0; i--) { data = (TUndoData *)DataList->Items[i]; if (!data->Equal(Instance)) { delete data; DataList->Remove(data); } } } } //--------------------------------------------------------------------------- // Public Function //--------------------------------------------------------------------------- void __fastcall TUndo::Set(int instance, TPItemImage *image, TPalette *palette, TWorkArea *workarea) { Instance = instance; Image = image; Palette = palette; WorkArea = workarea; Arrange(); } //--------------------------------------------------------------------------- bool __fastcall TUndo::Save(int k, RECT r, bool bSave) { TUndoData *data; if (SaveData(k, r, bSave)) { if (DataList->Count > (FMethod == UM_STACK ? Maximum : 1)) { data = (TUndoData *)DataList->First(); delete data; DataList->Remove(data); } return true; } return false; } //--------------------------------------------------------------------------- bool __fastcall TUndo::Save(int k, bool bSave) { return Save(k, Rect(0, 0, Image->Bitmap->Width, Image->Bitmap->Height), bSave); } //--------------------------------------------------------------------------- void __fastcall TUndo::Read(bool bDelete) { TUndoData *data = NULL; int i; if (FMethod == UM_STACK) { if (DataList->Count) { for (i = DataList->Count - 1; i >= 0; i--) { data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) break; } if (i >= 0) { data->LoadFromFile(); data->IsUse = true; ReadData(data); data->IsUse = false; if (bDelete) { delete data; DataList->Remove(data); } } } if (DataList->Count) { for (i = DataList->Count - 1; i >= 0; i--) { data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) { data->LoadFromFile(); } } } } else { if (DataList->Count) { data = (TUndoData *)DataList->Items[DataList->Count - 1]; if (bDelete) { SaveData(data->Kind, data->Range, false); ReadData(data); delete data; DataList->Remove(data); } else { ReadData(data); } } } } //--------------------------------------------------------------------------- void __fastcall TUndo::RemoveLast() { for (int i = DataList->Count - 1; i >= 0; i--) { TUndoData *data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) { delete data; DataList->Remove(data); break; } } } //--------------------------------------------------------------------------- void __fastcall TUndo::RemoveAll() { for (int i = 0; i < DataList->Count;) { TUndoData *data = (TUndoData *)DataList->Items[i]; if (data->Equal(Instance)) { delete data; DataList->Remove(data); } else { i++; } } } //---------------------------------------------------------------------------