mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-22 14:17:43 +02:00
Initial commit at Tue Apr 25 08:41:48 EDT 2017 by tim on stravinsky
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* DBWundo.c --
|
||||
*
|
||||
* Procedures for undoing/redoing operations associated
|
||||
* with the dbwind module.
|
||||
*
|
||||
* *********************************************************************
|
||||
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
||||
* * Permission to use, copy, modify, and distribute this *
|
||||
* * software and its documentation for any purpose and without *
|
||||
* * fee is hereby granted, provided that the above copyright *
|
||||
* * notice appear in all copies. The University of California *
|
||||
* * makes no representations about the suitability of this *
|
||||
* * software for any purpose. It is provided "as is" without *
|
||||
* * express or implied warranty. Export of this software outside *
|
||||
* * of the United States of America may require an export license. *
|
||||
* *********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/dbwind/DBWundo.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "windows/windows.h"
|
||||
#include "tiles/tile.h"
|
||||
#include "utils/hash.h"
|
||||
#include "database/database.h"
|
||||
#include "utils/main.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "utils/undo.h"
|
||||
#include "textio/textio.h"
|
||||
#include "commands/commands.h"
|
||||
|
||||
/*
|
||||
* Client identifiers returned by the undo package
|
||||
* in dbwUndoInit().
|
||||
*/
|
||||
UndoType dbwUndoIDOldEdit, dbwUndoIDNewEdit, dbwUndoIDBox;
|
||||
|
||||
/*
|
||||
* Function to play events forward/backward.
|
||||
*/
|
||||
void dbwUndoChangeEdit(), dbwUndoBoxForw(), dbwUndoBoxBack();
|
||||
|
||||
/*
|
||||
* Structure to hold all the information needed to switch
|
||||
* to a new edit cell. We rely upon the fact that no CellDef
|
||||
* is ever deleted, so it is safe to retain pointers to defs.
|
||||
* The defs, transform, and use identifier are used to identify
|
||||
* uniquely the cell use affected.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Transform e_editToRoot; /* Transform to root coordinates from edit */
|
||||
Transform e_rootToEdit; /* Transform to edit coordinates from root */
|
||||
CellDef *e_rootDef; /* Root def in the edit cell's home window */
|
||||
CellDef *e_editDef; /* Edit cell def itself */
|
||||
CellDef *e_parentDef; /* Parent def of the editcell, or NULL if the
|
||||
* edit cell was a root itself.
|
||||
*/
|
||||
char e_useId[4]; /* Use identifier. This is a place holder
|
||||
* only; the actual structure is allocated to
|
||||
* hold all the bytes in the use id, plus the
|
||||
* null byte.
|
||||
*/
|
||||
} editUE;
|
||||
|
||||
#define editSize(n) (sizeof (editUE) - 3 + (n))
|
||||
|
||||
/* Structure used for undo-ing changes in the box. It just holds the
|
||||
* box's old and new locations.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CellDef *bue_oldDef;
|
||||
Rect bue_oldArea;
|
||||
CellDef *bue_newDef;
|
||||
Rect bue_newArea;
|
||||
} BoxUndoEvent;
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* dbwUndoInit --
|
||||
*
|
||||
* Initialize handling of undo for the dbwind module.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Calls the undo package to add several clients.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
dbwUndoInit()
|
||||
{
|
||||
void (*nullProc)() = NULL;
|
||||
|
||||
dbwUndoIDOldEdit = UndoAddClient(nullProc, nullProc,
|
||||
(UndoEvent *(*)()) NULL, (int (*)()) NULL, nullProc,
|
||||
dbwUndoChangeEdit, "change edit cell");
|
||||
|
||||
dbwUndoIDNewEdit = UndoAddClient(nullProc, nullProc,
|
||||
(UndoEvent *(*)()) NULL, (int (*)()) NULL, dbwUndoChangeEdit,
|
||||
nullProc, "change edit cell");
|
||||
|
||||
dbwUndoIDBox = UndoAddClient(nullProc, nullProc,
|
||||
(UndoEvent *(*)()) NULL, (int (*)()) NULL, dbwUndoBoxForw,
|
||||
dbwUndoBoxBack, "box change");
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBWUndoOldEdit --
|
||||
* DBWUndoNewEdit --
|
||||
*
|
||||
* Record the old and new edit cells when the edit cell changes.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Each creates a single undo list entry.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DBWUndoOldEdit(editUse, editRootDef, editToRootTrans, rootToEditTrans)
|
||||
CellUse *editUse;
|
||||
CellDef *editRootDef;
|
||||
Transform *editToRootTrans, *rootToEditTrans;
|
||||
{
|
||||
char *useid = editUse->cu_id;
|
||||
editUE *ep;
|
||||
|
||||
ep = (editUE *) UndoNewEvent(dbwUndoIDOldEdit,
|
||||
(unsigned) editSize(strlen(useid)));
|
||||
if (ep == (editUE *) NULL)
|
||||
return;
|
||||
|
||||
ep->e_editToRoot = *editToRootTrans;
|
||||
ep->e_rootToEdit = *rootToEditTrans;
|
||||
ep->e_rootDef = editRootDef;
|
||||
ep->e_editDef = editUse->cu_def;
|
||||
ep->e_parentDef = editUse->cu_parent;
|
||||
(void) strcpy(ep->e_useId, useid);
|
||||
}
|
||||
|
||||
void
|
||||
DBWUndoNewEdit(editUse, editRootDef, editToRootTrans, rootToEditTrans)
|
||||
CellUse *editUse;
|
||||
CellDef *editRootDef;
|
||||
Transform *editToRootTrans, *rootToEditTrans;
|
||||
{
|
||||
char *useid = editUse->cu_id;
|
||||
editUE *ep;
|
||||
|
||||
ep = (editUE *) UndoNewEvent(dbwUndoIDNewEdit,
|
||||
(unsigned) editSize(strlen(useid)));
|
||||
if (ep == (editUE *) NULL)
|
||||
return;
|
||||
|
||||
ep->e_editToRoot = *editToRootTrans;
|
||||
ep->e_rootToEdit = *rootToEditTrans;
|
||||
ep->e_rootDef = editRootDef;
|
||||
ep->e_editDef = editUse->cu_def;
|
||||
ep->e_parentDef = editUse->cu_parent;
|
||||
(void) strcpy(ep->e_useId, useid);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* dbwUndoChangeEdit
|
||||
*
|
||||
* Change the edit cell.
|
||||
* The UndoEvent passed as an argument contains a pointer to
|
||||
* the root cell def of the new edit cell and the parent def
|
||||
* of the edit cell. Both pointers are safe because we never
|
||||
* delete a CellDef.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Changes the edit cell.
|
||||
* Redisplays the old edit cell and the new one.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
dbwUndoChangeEdit(ep)
|
||||
editUE *ep;
|
||||
{
|
||||
Rect area;
|
||||
CellUse *use;
|
||||
CellDef *editDef, *parent;
|
||||
static Rect origin = {-1, -1, 1, 1};
|
||||
|
||||
/* Redisplay the old edit cell */
|
||||
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
|
||||
DBWAreaChanged(EditRootDef, &area, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
||||
GeoTransRect(&EditToRootTransform, &origin, &area);
|
||||
DBWAreaChanged(EditRootDef, &area, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
||||
|
||||
/* Set up the transforms for the new edit cell */
|
||||
EditToRootTransform = ep->e_editToRoot;
|
||||
RootToEditTransform = ep->e_rootToEdit;
|
||||
|
||||
/*
|
||||
* Search for the use uniquely identified by the parent cell
|
||||
* def 'parent' (which may be NULL) and the use identifier
|
||||
* 'ep->e_useId'.
|
||||
*
|
||||
* It's gotta be there.
|
||||
*/
|
||||
EditRootDef = ep->e_rootDef;
|
||||
editDef = ep->e_editDef;
|
||||
parent = ep->e_parentDef;
|
||||
for (use = editDef->cd_parents; use != NULL; use = use->cu_nextuse)
|
||||
if (use->cu_parent == parent && strcmp(use->cu_id, ep->e_useId) == 0)
|
||||
break;
|
||||
|
||||
ASSERT(use != (CellUse *) NULL, "dbwUndoChangeEdit");
|
||||
|
||||
TxPrintf("Edit cell is now %s (%s)\n", editDef->cd_name, use->cu_id);
|
||||
EditCellUse = use;
|
||||
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
|
||||
DBWAreaChanged(EditRootDef, &area, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
||||
GeoTransRect(&EditToRootTransform, &origin, &area);
|
||||
DBWAreaChanged(EditRootDef, &area, DBW_ALLWINDOWS, &DBAllButSpaceBits);
|
||||
CmdSetWindCaption(EditCellUse, EditRootDef);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* DBWUndoBox --
|
||||
*
|
||||
* Remember a box change for later undo-ing.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* An entry is added to the undo list.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
DBWUndoBox(oldDef, oldArea, newDef, newArea)
|
||||
CellDef *oldDef; /* Celldef containing old box. */
|
||||
Rect *oldArea; /* Area of old box in oldDef coords. */
|
||||
CellDef *newDef; /* Celldef containing new box. */
|
||||
Rect *newArea; /* Area of new box in newDef coords. */
|
||||
{
|
||||
BoxUndoEvent *bue;
|
||||
|
||||
bue = (BoxUndoEvent *) UndoNewEvent(dbwUndoIDBox, sizeof(BoxUndoEvent));
|
||||
if (bue == NULL) return;
|
||||
|
||||
bue->bue_oldDef = oldDef;
|
||||
bue->bue_oldArea = *oldArea;
|
||||
bue->bue_newDef = newDef;
|
||||
bue->bue_newArea = *newArea;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* dbwUndoBoxForw --
|
||||
* dbwUndoBoxBack --
|
||||
*
|
||||
* This routines are called to undo a change to the box. They
|
||||
* are invoked by the undo package.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The box's location is modified.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
dbwUndoBoxForw(bue)
|
||||
BoxUndoEvent *bue; /* Event to be redone. */
|
||||
{
|
||||
DBWSetBox(bue->bue_newDef, &bue->bue_newArea);
|
||||
}
|
||||
|
||||
void
|
||||
dbwUndoBoxBack(bue)
|
||||
BoxUndoEvent *bue; /* Event to be undone. */
|
||||
{
|
||||
DBWSetBox(bue->bue_oldDef, &bue->bue_oldArea);
|
||||
}
|
||||
Reference in New Issue
Block a user