313 lines
8.8 KiB
C
313 lines
8.8 KiB
C
/*
|
||
* 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);
|
||
}
|