int CImage::GetDirtyState() { LPOBJECT lpObject = NULL; int dirty = NO; int ObjDirty; while (lpObject = GetNextObject(lpObject, YES, NO)) { if (Control.UndoObjects && !IsSelectedObject(lpObject)) continue; if (lpObject->DataDirty) ObjDirty = lpObject->DataDirty; else if ((lpObject != GetBase()) && lpObject->lpAlpha && lpObject->AlphaDirty) ObjDirty = lpObject->AlphaDirty; else continue; if (!dirty) dirty = ObjDirty; else if (ObjDirty != dirty) return(IDS_EDITS); } return(dirty); }
BOOL CImage::GetUndoState() { LPOBJECT lpObject = NULL; BOOL ObjUndoNotRedo; int UndoNotRedo = -1; while (lpObject = GetNextObject(lpObject, YES, NO)) { if (Control.UndoObjects && !IsSelectedObject(lpObject)) continue; if (lpObject->DataDirty) ObjUndoNotRedo = lpObject->DataUndoNotRedo; else if ((lpObject != GetBase()) && lpObject->lpAlpha && lpObject->AlphaDirty) ObjUndoNotRedo = lpObject->AlphaUndoNotRedo; else continue; if (UndoNotRedo < 0) UndoNotRedo = ObjUndoNotRedo; else if (ObjUndoNotRedo != UndoNotRedo) return(TRUE); } return(UndoNotRedo); }
BOOL CImage::EditInit( EDIT_TARGET Target, UNDO_TYPE UndoType, LPOBJECT lpTargetObject) { LPOBJECT lpObject, lpBase; int retc; BOOL fDiscardUndo = NO; BOOL fUndoFailed; BOOL fMaskEdit; EDIT_TARGET OldTarget; lpBase = GetBase(); // the InitUndoType flag is kept separately from the // DataUndoType and AlphaUndoType so that if the initialization // of the undo fails we still know what was edited when // EditedObject and EditedObjectFrame are called lpObject = NULL; while (lpObject = GetNextObject(lpObject, YES, NO)) lpObject->InitUndoType = 0; // No mask undo's are allowed - so apply any that we have now if (!Control.UndoMasks) ObjEditApply(lpBase, NO, YES, NO); // No undo's are allowed - so apply any that we have now if (Control.NoUndo || fDisableUndos) { lpObject = NULL; while (lpObject = GetNextObject(lpObject, YES, NO)) ObjEditApply(lpObject, YES, lpObject != lpBase, NO); } // if we have don't have multiple objects, strip off the delete objects flag if (!Control.MultipleObjects) UndoType &= ~UT_DELETEOBJECTS; // find out whether we are in mask edit mode fMaskEdit = (Target == ET_OBJECT) && (lpTargetObject == lpBase) && ((UndoType & UT_ALPHAUNDO) != 0); // see if any objects cannot have their undos freed without // asking the user first, if so ask the user and get the response // This is only a manual apply thing if (UndoType & (UT_NEWDATA|UT_NEWALPHA) && Control.UseApply) { lpObject = NULL; fDiscardUndo = YES; while (lpObject = GetNextObject(lpObject, YES, NO)) { // see if this is an object we are not editing if ((Target == ET_SELOBJECTS && !IsSelectedObject(lpObject)) || (Target == ET_OBJECT && lpObject != lpTargetObject)) continue; if (!ObjEditUndoDiscardable(lpObject, (UndoType & UT_NEWDATA) != 0, (UndoType & UT_NEWALPHA) != 0)) { if (lpCmdList->fPlayback) { fDiscardUndo = fDiscardUndo; } else { DISCARDUNDO_PARMS parms; retc = AstralConfirm( IDS_OKTOAPPLY ); if (retc == IDCANCEL) return(FALSE); fDiscardUndo = retc == IDYES; parms.fDiscardUndo = fDiscardUndo; PostCommand(lpCmdList, IDS_CMD_DISCARDUNDO, &parms); } break; } } } OldTarget = EditTarget; EditTarget = Target; // now loop through the objects initializing their undos lpObject = NULL; while (lpObject = GetNextObject(lpObject, YES, NO)) { // if our last edit involved editing all objects then // make sure we apply for all objects if (OldTarget == ET_ALLOBJECTS) { ObjEditApply(lpObject, !fMaskEdit, (lpObject != lpBase) && !fMaskEdit, NO); } // see if this is an object we are not editing if ((Target == ET_SELOBJECTS && !IsSelectedObject(lpObject)) || (Target == ET_OBJECT && lpObject != lpTargetObject)) { // if no individual undo's, wack any undo buffers // if in auto apply or in manual apply and state is redo // Objects that are not the base need to also have // their alphas wacked if this is not a mask edit if (!Control.UndoObjects && (!Control.UseApply || ( Control.UseApply && !lpObject->DataUndoNotRedo ) ) ) ObjEditApply(lpObject, !fMaskEdit, (lpObject != lpBase) && !fMaskEdit, NO); continue; } // Discard it's undo if possible if (fDiscardUndo) ObjEditFreeUndo(lpObject, (UndoType & UT_NEWDATA) != 0, (UndoType & UT_NEWALPHA) != 0); // save state of undo failed flag fUndoFailed = lpObject->fUndoFailed; // Initialize the undo for this object if (!ObjEditInit(lpObject, UndoType)) { // Undo initialization failed, so apply all objects that // were going to be initialized lpObject = NULL; while (lpObject = GetNextObject(lpObject, YES, NO)) { // see if this is an object we are not editing if ((Target == ET_SELOBJECTS && !IsSelectedObject(lpObject)) || (Target == ET_OBJECT && lpObject != lpTargetObject)) { continue; } lpObject->fUndoFailed = YES; lpObject->InitUndoType = 0; if (lpObject == lpBase) ObjEditApply(lpObject, (UndoType & UT_DATAUNDO) != 0, (UndoType & UT_ALPHAUNDO) != 0, NO); else ObjEditApply(lpObject, YES, YES, NO); } // if we have failed before if (fUndoFailed) return(TRUE); else { Message(IDS_NOUNDO); return(FALSE); } } lpObject->fUndoFailed = NO; lpObject->InitUndoType = UndoType; } return( TRUE ); }
void CImage::EditUndo( BOOL fEditUndo, BOOL fMaskUndo, LPUPDATE_TYPE lpUpdateType, LPRECT lpUpdateRect) { RECT rUndo, rUndoMask, rTemp; LPOBJECT lpBase, lpObject, lpNext; BOOL fNewSize, fSetupMiniViews, fRemoveMarquee, fUndoDelete, fColorMapChanged; BOOL fUndoAlpha, fUndoData; int nDeleted; LPMASK lpMask; EDIT_TARGET Target; AstralSetRectEmpty(lpUpdateRect); // Initialize things for updating the display fNewSize = fSetupMiniViews = fUndoDelete = fColorMapChanged = NO; AstralSetRectEmpty(&rUndo); AstralSetRectEmpty(&rUndoMask); // loop through objects doing undo lpBase = GetBase(); lpObject = NULL; // get the target of the last edit Target = EditTarget; while (lpObject = GetNextObject(lpObject, NO, NO, fEditUndo)) { // See if this is an object we are undoing if (fEditUndo) { // check for special undo processing of a deleted object if (lpObject->fDeleted) continue; // do no undo processing for a deleted object // { // if (Control.UndoObjects && !IsSelectedObject(lpBase)) // continue; // } else // if target is not the entire image and we are in undo // object mode and the object is not selected then // skip this object if (Target != ET_ALLOBJECTS && Control.UndoObjects && !IsSelectedObject(lpObject)) continue; } // Only handle mask undo for the base object if (fMaskUndo) { if (lpObject != lpBase || lpObject->fBothDirty || !lpObject->AlphaDirty) continue; } fUndoData = fUndoAlpha = NO; // Do preprocess for doing a data undo if (fEditUndo) { if (lpObject->DataDirty) fUndoData = YES; // See if we need to undo the alpha for this object if ((lpObject != lpBase) && lpObject->lpAlpha && lpObject->AlphaDirty) fUndoAlpha = YES; if (!fUndoData && !fUndoAlpha) continue; // check to see and undoing/redoing deleted objects will change // the select state, if so undraw the object marquee if (lpObject == lpBase && lpObject->DataUndoType & UT_DELETEOBJECTS) { fUndoDelete = YES; fRemoveMarquee = NO; nDeleted = 0; lpNext = lpObject; while (lpNext = GetNextObject(lpNext, YES, NO, YES)) { if (lpNext->fUndoDeleted) ++nDeleted; else if (lpNext->fDeleted && lpNext->fSelected) { fRemoveMarquee = YES; break; } } if (GetSelObject(NULL) == lpBase && !fRemoveMarquee) { if (CountObjects() - nDeleted <= 1) fRemoveMarquee = YES; } if (fRemoveMarquee) { GetObjectMarqueeRect(this, &rTemp); AstralUnionRect(lpUpdateRect, lpUpdateRect, &rTemp); } } } else // fMaskUndo if (!lpObject->AlphaDirty) continue; else fUndoAlpha = YES; // do a preprocess for undoing the mask caused either by // a mask undo or by an edit function that also edits the mask if (((lpObject == lpBase) && fEditUndo && lpObject->fBothDirty) || fMaskUndo) { if ( lpObject->AlphaUndoType & (UT_CREATEMASK|UT_DELETEMASK) ) { // if the undo is going to delete the mask, // we need to undraw the mask if (GetMask()) { GetMaskMarqueeRect(this, &rTemp); AstralUnionRect(lpUpdateRect, lpUpdateRect, &rTemp); if (GetMaskUpdateRect(YES, NO, &rTemp)) AstralUnionRect(&rUndoMask, &rUndoMask, &rTemp); } // if the undo is going to create the mask, // we need to undraw the object marquees if // not in mask and object marquee mode else { if (!Control.UseMaskAndObjects) { GetObjectMarqueeRect(this, &rTemp); AstralUnionRect(lpUpdateRect, lpUpdateRect, &rTemp); } } } } // Actually do the undo ObjEditUndo(lpObject, fUndoData, fUndoAlpha); // do a postprocess for undoing the mask if ((lpMask = GetMask()) && (((lpObject == lpBase) && fEditUndo && lpObject->fBothDirty) || fMaskUndo)) { // if the undo is going to add the mask, we need to redraw the mask if (lpObject->AlphaUndoType & (UT_CREATEMASK|UT_DELETEMASK) ) { if (GetMaskUpdateRect(YES, NO, &rTemp)) AstralUnionRect(&rUndoMask, &rUndoMask, &rTemp); } else // just redraw the undo area for the mask AstralUnionRect(&rUndoMask, &rUndoMask, &lpMask->Pixmap.UndoRect); } // Setup rectangle for undoing deletion of objects // Handled specially so that moved objects will still undo // and redo properly if (fEditUndo) { if (lpObject == lpBase && lpObject->DataUndoType & UT_DELETEOBJECTS) { lpNext = lpObject; while (lpNext = GetNextObject(lpNext, YES, NO, YES)) { if (lpNext->fDeleted || lpNext->fUndoDeleted) AstralUnionRect(&rUndo, &rUndo, &lpNext->rObject); } fSetupMiniViews = YES; } if (lpObject->DataUndoType & UT_COLORMAP) fColorMapChanged = YES; if (lpObject->Pixmap.fNewFrame) { /* if new frame, cause window to be redisplayed */ if (lpObject == lpBase) fNewSize = YES; else { if (!fNewSize) { AstralUnionRect(&rUndo, &rUndo, &lpObject->rObject); AstralUnionRect(&rUndo, &rUndo, &lpObject->rUndoObject); } } } else { AstralSetRectEmpty(&rTemp); if (fUndoData) AstralUnionRect(&rTemp, &rTemp, &lpObject->Pixmap.UndoRect); if (fUndoAlpha) AstralUnionRect(&rTemp, &rTemp, &lpObject->lpAlpha->Pixmap.UndoRect); if (rTemp.right >= rTemp.left) { if (!fNewSize) { OffsetRect(&rTemp, lpObject->rObject.left, lpObject->rObject.top); AstralUnionRect(&rUndo, &rUndo, &rTemp); } } if( lpObject->DataUndoType & UT_OBJECTRECT ) { AstralUnionRect( &rUndo, &rUndo, &lpObject->rObject ); AstralUnionRect( &rUndo, &rUndo, &lpObject->rUndoObject ); } } } } // now redisplay whatever changes are necessary for the undo if (fColorMapChanged) { ImgColorMapChanged(this); *lpUpdateType |= UT_DATATYPE; } if (fNewSize) { *lpUpdateType |= UT_DATATYPE; if (lpBase->Pixmap.UndoFrame) { if ((FrameXSize(lpBase->Pixmap.UndoFrame) == FrameXSize(lpBase->Pixmap.EditFrame)) && (FrameYSize(lpBase->Pixmap.UndoFrame) == FrameYSize(lpBase->Pixmap.EditFrame))) fNewSize = NO; } if (fNewSize) *lpUpdateType |= UT_SIZE; else { int dx, dy; GetInfo(&dx, &dy, NULL, NULL); SetRect(lpUpdateRect, 0, 0, dx-1, dy-1); } } else { if (!AstralIsRectEmpty(lpUpdateRect)) *lpUpdateType |= UT_ACTIVEAREA; if (rUndoMask.right >= rUndoMask.left) { *lpUpdateType |= UT_ACTIVEAREA; AstralUnionRect(lpUpdateRect, lpUpdateRect, &rUndoMask); } if (rUndo.right >= rUndo.left) { *lpUpdateType |= UT_AREA; AstralUnionRect(lpUpdateRect, lpUpdateRect, &rUndo); } } }