445 lines
14 KiB
C
445 lines
14 KiB
C
/* 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.
|
||
*
|
||
* ----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
DBWHLRedrawWind(window)
|
||
MagWindow *window; /* Window in which to redraw highlights. */
|
||
{
|
||
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, window)
|
||
Tile *tile; /* Tile describing area to be erased. */
|
||
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);
|
||
}
|