magic/dbwind/DBWhlights.c

448 lines
14 KiB
C
Raw Normal View History

/* DBWhighlights.c -
*
* This file contains routines that allow the highlight plane
* to be used to display additional things besides the box.
* The routines coordinate all the clients that have highlights
* to display so that when one of them updates its highlights
* it doesn't trash the others' highlights.
*
* *********************************************************************
* * 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/DBWhlights.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/styles.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "windows/windows.h"
#include "graphics/graphics.h"
#include "dbwind/dbwind.h"
#include "textio/textio.h"
#include "graphics/graphicsInt.h"
#define WINDOW_DEF(w) (((CellUse *)(w->w_surfaceID))->cu_def)
/* The array below is used to hold the addresses of redisplay
* procedures for each of the highlight clients. Whenever
* highlights must be redisplayed, each highlight client
* is invoked for each database window.
*/
#define MAXCLIENTS 10
static int (*(dbwhlClients[MAXCLIENTS]))();
/*
* ----------------------------------------------------------------------------
*
* DBWHLAddClient --
*
* This procedure is used to add another client to those
* that are displaying highlights. The redisplay procedure
* passed in by the client will be invoked in the following
* way:
* int
* redisplayProc(window, plane)
* MagWindow *window;
* Plane *plane;
* {
* }
* The procedure is invoked once for each window that contains
* database information (and potentially has highlights). The
* window has been locked via GrLock() before the proc is called,
* and the clipping area has already been set up. The procedure
* is given a pointer to the window, and a pointer to a plane.
* The plane contains non-space tiles over all areas where highlight
* information needs to be redrawn (all of these areas have had
* their highlight information erased). The client should redraw
* any of its highlights that touch any non-space areas.
*
* Results:
* None.
*
* Side effects:
* The client is added to our list of clients.
*
* ----------------------------------------------------------------------------
*/
void
DBWHLAddClient(redisplayProc)
int (*redisplayProc)(); /* Procedure to call during redisplays. */
{
int i;
for (i = 0; i < MAXCLIENTS; i++)
{
if (dbwhlClients[i] == NULL)
{
dbwhlClients[i] = redisplayProc;
return;
}
}
TxError("Magic error: ran out of space in highlight client table.\n");
TxError("Tell your system maintainer to enlarge the table.\n");
}
/*
* ----------------------------------------------------------------------------
*
* DBWHLRemoveClient --
*
* This just removes a client from the list of those that we
* know about.
*
* Results:
* None.
*
* Side effects:
* The given redisplay procedure will no longer be invoked
* during redisplays.
*
* ----------------------------------------------------------------------------
*/
void
DBWHLRemoveClient(redisplayProc)
int (*redisplayProc)(); /* A redisplay procedure. This
* procedure must previously have been
* passed in to DBWHLAddClient.
*/
{
int i;
for (i = 0; i < MAXCLIENTS; i += 1)
{
if (dbwhlClients[i] == redisplayProc)
{
dbwhlClients[i] = NULL;
return;
}
}
ASSERT(FALSE, "DBWHLRemoveClient");
}
/*
* ----------------------------------------------------------------------------
*
* DBWHLRedraw --
*
* This procedure is invoked to redisplay highlights. The
* clients that manage highlights are free to draw on the screen
* at will. But if a client ever erases highlight information, it
* must call this procedure so that the other clients can redraw
* any of their highlights that might have been erased. This
* procedure records what has changed. The information isn't actually
* redrawn until the next time WindUpdate is called. This is done
* to avoid repeated redraws when several pieces of highlights change
* in the same area at the same time.
*
* Results:
* None.
*
* Side effects:
* Information is recorded so that specified area will have its
* highlight information erased and redrawn the next time that
* WindUpdate is called.
*
* ----------------------------------------------------------------------------
*/
void
DBWHLRedraw(rootDef, area, erase)
CellDef *rootDef; /* Highlight information will be redrawn in
* all windows for which this is the root
* cell definition.
*/
Rect *area; /* The area over which to redraw. Highlights
* will be redrawn in this area plus enough
* surrounding area to catch degenerate boxes
* (drawn as crosses) and labels that may
* stick out from their attachment points.
*/
bool erase; /* TRUE means we should erase are before
* redrawing it. FALSE means that either the
* client has erased the area, or there's no
* need to erase it because all that's
* happening is to add new information to the
* display.
*/
{
extern CellDef *dbwhlDef;
extern bool dbwhlErase;
extern int dbwhlRedrawFunc();
Rect ourArea;
dbwhlDef = rootDef; /* Must pass to search function. */
dbwhlErase = erase;
/* If we're passed a NULL area, expand it by one unit in both
* directions so that we're certain to have non-zero area.
* Otherwise the various search procedures have big troubles.
*/
ourArea = *area;
if (ourArea.r_xbot >= ourArea.r_xtop)
{
ourArea.r_xtop = ourArea.r_xbot + 1;
ourArea.r_xbot--;
}
if (ourArea.r_ybot >= ourArea.r_ytop)
{
ourArea.r_ytop = ourArea.r_ybot + 1;
ourArea.r_ybot--;
}
(void) WindSearch(DBWclientID, (ClientData) NULL, &ourArea,
dbwhlRedrawFunc, (ClientData) &ourArea);
}
CellDef *dbwhlDef;
bool dbwhlErase;
/* This procedure records the area to be erased (if any) and the
* area to be redisplayed (which is larger than the area to be
* erased).
*/
int
dbwhlRedrawFunc(window, area)
MagWindow *window; /* Window to redraw. */
Rect *area; /* Passed as client data. */
{
Rect erase, expand, redraw;
DBWclientRec *crec = (DBWclientRec *) window->w_clientData;
if (WINDOW_DEF(window) != dbwhlDef) return 0;
/* The area that we erase must be large enough to include material
* that sticks out from the area of the highlights. There are two
* ways that material sticks out: (a) zero-size boxes are drawn as
* crosses, and the crosses stick outside of the box's area; (b)
* labels are attached to points or rectangles, but the text usually
* extends far beyond the attachment point.
*/
WindSurfaceToScreen(window, area, &erase);
expand = GrCrossRect;
(void) GeoInclude(&crec->dbw_expandAmounts, &expand);
if (dbwhlErase)
{
bool needErase = TRUE;
erase.r_xbot += expand.r_xbot;
erase.r_ybot += expand.r_ybot;
erase.r_xtop += expand.r_xtop;
erase.r_ytop += expand.r_ytop;
/* On some displays (e.g. black-and-white ones), highlights use
* the same color planes as other information. If this is the
* case, redisplay everything (this will redisplay highlights too,
* so there's nothing additional to do here).
*
* This is also the case if we use backing store but the backing
* store has been removed due to becoming invalid, such as when
* an attempt is made to redraw into an obscured or unmapped
* window.
*/
if (((GrGetBackingStorePtr == NULL) &&
((GrStyleTable[STYLE_ERASEHIGHLIGHTS].mask &
GrStyleTable[STYLE_ERASEALLBUTTOOLS].mask) != 0)) ||
((GrGetBackingStorePtr != NULL) &&
window->w_backingStore == (ClientData)NULL))
{
DBWAreaChanged(dbwhlDef, area, crec->dbw_bitmask,
(TileTypeBitMask *) NULL);
WindAnotherUpdatePlease = TRUE;
return 0;
}
DBPaintPlane(crec->dbw_hlErase, &erase,
DBStdPaintTbl(TT_ERROR_P, PL_DRC_ERROR),
(PaintUndoInfo *) NULL);
}
/* The area whose highlights must be redrawn is the area erased, but
* it must be expanded again to include the fact that we may have
* just erased a piece of a label that stuck out from some other point.
* This area gets translated back into database coordinates and saved
* in dbwhlRedrawPlane, but first it gets expanded by one more unit just to
* eliminate edge effects: all impacted highlights are now guaranteed
* to OVERLAP an area in dbwhlRedrawPlane, not just touch.
*/
erase.r_xbot -= expand.r_xtop;
erase.r_ybot -= expand.r_ytop;
erase.r_xtop -= expand.r_xbot;
erase.r_ytop -= expand.r_ybot;
(void) WindScreenToSurface(window, &erase, &redraw);
GEO_EXPAND(&redraw, 1, &redraw);
DBPaintPlane(crec->dbw_hlRedraw, &redraw,
DBStdPaintTbl(TT_ERROR_P, PL_DRC_ERROR),
(PaintUndoInfo *) NULL);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* DBWHLRedrawPrepWindow --
*
* This procedure is similar to DBWHLRedraw. However, it is
* intended to indicate areas to redraw highlights for a
* single window only. This is required by the backing store
* mechanism when a window is scrolled, and the part of the
* window area that remains visible is refreshed from backing
* store. This area does not need to have layout redrawn, but
* does need to have all hightlights redrawn, since the
* highlights aren't saved in backing store.
*
* Results:
* None.
*
* Side effects:
* Information is recorded so that specified area will have its
* highlight information erased and redrawn the next time that
* WindUpdate is called.
*
* ----------------------------------------------------------------------------
*/
void
DBWHLRedrawPrepWindow(MagWindow *window, Rect *area)
{
extern CellDef *dbwhlDef;
extern bool dbwhlErase;
extern int dbwhlRedrawFunc();
dbwhlDef = WINDOW_DEF(window);
dbwhlErase = FALSE;
dbwhlRedrawFunc(window, area);
}
/*
* ----------------------------------------------------------------------------
*
* DBWHLRedrawWind --
*
* This procedure is called to redraw highlight information in a
* particular window. It is normally called as part of WindUpdate
* by DBWHLUpdate. The areas to be erased and redrawn must already
* be present in the clientData record.
*
* Results:
* Always returns 0 to keep searches from aborting.
*
* Side effects:
* The plane dbw_hlPlane indicates which highlight areas must be
* redrawn for this window. Any highlights that touch any of these
* areas are redrawn. The plane is then cleared.
*
* ----------------------------------------------------------------------------
*/
/*ARGSUSED*/
int
Add ClientData parameter to indirect-call callbacks for WASM WASM call_indirect enforces an exact type match between the caller and the callee. Many Magic callbacks had K&R-style () forward declarations and a single-argument definition, but were passed to iterators that always push a trailing ClientData argument. Native builds tolerated the mismatch via loose prototypes; WASM traps with "indirect call signature mismatch". Added the missing ClientData (or, where the concrete type is known, FindRegion *) parameter to: * calma/CalmaRead.c, calma/CalmaWrite.c, calma/CalmaWriteZ.c — calmaWriteInitFunc * cif/CIFwrite.c — cifWriteInitFunc * commands/CmdSubrs.c — cmdWindSet * database/DBtimestmp.c — dbStampFunc * dbwind/DBWelement.c — dbwElementAlways1 * dbwind/DBWfdback.c — dbwfbWindFunc * dbwind/DBWhlights.c — DBWHLRedrawWind * ext2spice/ext2hier.c — spcnodeHierVisit * extract/ExtBasic.c — extSDTileFunc, extTransPerimFunc, extAnnularTileFunc, extResistorTileFunc * extract/ExtMain.c — extDefInitFunc * extract/ExtTimes.c — extTimesInitFunc Also adjusted commands/CmdE.c and commands/CmdTZ.c: SelectExpand was being called with four arguments (the legacy surroundFlag), but its real signature has been three arguments for years (the surround mode is encoded in the expandType bit). The fourth argument was redundant (DB_EXPAND_SURROUND in arg 2 is the source of truth) and rejected by WASM. Native behavior is unchanged. The added parameters are unused in the function bodies; they exist only to satisfy the indirect-call signature.
2026-05-04 13:29:11 +02:00
DBWHLRedrawWind(window, clientData)
MagWindow *window; /* Window in which to redraw highlights. */
ClientData clientData; /* UNUSED */
{
int i;
DBWclientRec *crec;
extern int dbwhlEraseFunc(); /* Forward reference. */
GrLock(window, TRUE);
crec = (DBWclientRec *) window->w_clientData;
/* First erase, then redraw: */
(void) DBSrPaintArea((Tile *) NULL, crec->dbw_hlErase, &TiPlaneRect,
&DBAllButSpaceBits, dbwhlEraseFunc, (ClientData)window);
/* Now call each client to redraw its own stuff. */
for (i = 0; i < MAXCLIENTS; i += 1)
{
if (dbwhlClients[i] == NULL) continue;
(void) (*(dbwhlClients[i]))(window, crec->dbw_hlRedraw);
}
DBClearPaintPlane(crec->dbw_hlErase);
DBClearPaintPlane(crec->dbw_hlRedraw);
GrUnlock(window);
return 0;
}
/* The procedure below erases highlight information for each tile that
* it's called with. Returns 0 to keep the search from aborting.
*/
int
dbwhlEraseFunc(tile, dinfo, window)
Tile *tile; /* Tile describing area to be erased. */
TileType dinfo; /* Split tile information (unused) */
MagWindow *window; /* Window that is being altered. */
{
Rect area;
bool needErase = TRUE;
TiToRect(tile, &area);
/* If the graphics package allows highlight areas to be */
/* cached in backing store, then we do a quick check to */
/* see if we can just copy the background back in and */
/* avoid repainting. */
if (GrGetBackingStorePtr != NULL)
if ((*GrGetBackingStorePtr)(window, &area))
needErase = FALSE;
if (needErase) GrClipBox(&area, STYLE_ERASEHIGHLIGHTS);
return 0;
}
/*
* ----------------------------------------------------------------------------
* DBWHLUpdate --
*
* This procedure is called once as part of each WindUpdate call.
* It checks for any windows that have highlight information that
* needs to be redrawn
*
* Results:
* None.
*
* Side effects:
* Highlights get redrawn on the screen.
* ----------------------------------------------------------------------------
*/
void
DBWHLUpdate()
{
extern int dbwhlUpdateWindowFunc();
/* Scan through all of the layout windows and redraw their
* highlight information, if necessary.
*/
(void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL,
DBWHLRedrawWind, (ClientData) NULL);
}