235 lines
7.3 KiB
C
235 lines
7.3 KiB
C
|
|
/*
|
|||
|
|
* search2.c --
|
|||
|
|
*
|
|||
|
|
* Area searching.
|
|||
|
|
*
|
|||
|
|
* *********************************************************************
|
|||
|
|
* * 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/tiles/search2.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 "tiles/tile.h"
|
|||
|
|
#include "utils/signals.h"
|
|||
|
|
|
|||
|
|
/* -------------------- Local function headers ------------------------ */
|
|||
|
|
|
|||
|
|
int tiSrAreaEnum();
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* --------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* TiSrArea --
|
|||
|
|
*
|
|||
|
|
* Find all tiles contained in or incident upon a given area.
|
|||
|
|
* Applies the given procedure to all tiles found. The procedure
|
|||
|
|
* should be of the following form:
|
|||
|
|
*
|
|||
|
|
* int
|
|||
|
|
* func(tile, cdata)
|
|||
|
|
* Tile *tile;
|
|||
|
|
* ClientData cdata;
|
|||
|
|
* {
|
|||
|
|
* }
|
|||
|
|
*
|
|||
|
|
* Func normally should return 0. If it returns 1 then the search
|
|||
|
|
* will be aborted.
|
|||
|
|
*
|
|||
|
|
* THIS PROCEDURE IS OBSOLETE EXCEPT FOR THE SUBCELL PLANE. USE
|
|||
|
|
* DBSrPaintArea() IF YOU WANT TO SEARCH FOR PAINT TILES.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* 0 is returned if the search completed normally. 1 is returned
|
|||
|
|
* if it aborted.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* Whatever side effects result from application of the
|
|||
|
|
* supplied procedure.
|
|||
|
|
*
|
|||
|
|
* NOTE:
|
|||
|
|
* The procedure called is free to do anything it wishes to tiles
|
|||
|
|
* which have already been visited in the area search, but it must
|
|||
|
|
* not affect anything about tiles not visited other than possibly
|
|||
|
|
* corner stitches to tiles already visited.
|
|||
|
|
*
|
|||
|
|
* *************************************************************************
|
|||
|
|
* *************************************************************************
|
|||
|
|
* **** ****
|
|||
|
|
* **** WARNING ****
|
|||
|
|
* **** ****
|
|||
|
|
* **** This code is INCREDIBLY sensitive to modification! ****
|
|||
|
|
* **** Change it only with the utmost caution, or you'll ****
|
|||
|
|
* **** be verrry sorry! ****
|
|||
|
|
* **** ****
|
|||
|
|
* *************************************************************************
|
|||
|
|
* *************************************************************************
|
|||
|
|
*
|
|||
|
|
* --------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
int
|
|||
|
|
TiSrArea(hintTile, plane, rect, func, arg)
|
|||
|
|
Tile *hintTile; /* Tile at which to begin search, if not NULL.
|
|||
|
|
* If this is NULL, use the hint tile supplied
|
|||
|
|
* with plane.
|
|||
|
|
*/
|
|||
|
|
Plane *plane; /* Plane in which tiles lie. This is used to
|
|||
|
|
* provide a hint tile in case hintTile == NULL.
|
|||
|
|
* The hint tile in the plane is updated to be
|
|||
|
|
* the last tile visited in the area enumeration.
|
|||
|
|
*/
|
|||
|
|
Rect *rect;/* Area to search */
|
|||
|
|
int (*func)(); /* Function to apply at each tile */
|
|||
|
|
ClientData arg; /* Additional argument to pass to (*func)() */
|
|||
|
|
{
|
|||
|
|
Point here;
|
|||
|
|
Tile *tp, *enumTR, *enumTile;
|
|||
|
|
int enumRight, enumBottom;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* We will scan from top to bottom along the left hand edge
|
|||
|
|
* of the search area, searching for tiles. Each tile we
|
|||
|
|
* find in this search will be enumerated.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
here.p_x = rect->r_xbot;
|
|||
|
|
here.p_y = rect->r_ytop - 1;
|
|||
|
|
enumTile = hintTile ? hintTile : plane->pl_hint;
|
|||
|
|
GOTOPOINT(enumTile, &here);
|
|||
|
|
plane->pl_hint = enumTile;
|
|||
|
|
|
|||
|
|
while (here.p_y >= rect->r_ybot)
|
|||
|
|
{
|
|||
|
|
if (SigInterruptPending) return 1;
|
|||
|
|
/*
|
|||
|
|
* Find the tile (tp) immediately below the one to be
|
|||
|
|
* enumerated (enumTile). This must be done before we enumerate
|
|||
|
|
* the tile, as the filter function applied to enumerate
|
|||
|
|
* it can result in its deallocation or modification in
|
|||
|
|
* some other way.
|
|||
|
|
*/
|
|||
|
|
here.p_y = BOTTOM(enumTile) - 1;
|
|||
|
|
tp = enumTile;
|
|||
|
|
GOTOPOINT(tp, &here);
|
|||
|
|
plane->pl_hint = tp;
|
|||
|
|
|
|||
|
|
enumRight = RIGHT(enumTile);
|
|||
|
|
enumBottom = BOTTOM(enumTile);
|
|||
|
|
enumTR = TR(enumTile);
|
|||
|
|
if ((*func)(enumTile, arg)) return 1;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* If the right boundary of the tile being enumerated is
|
|||
|
|
* inside of the search area, recursively enumerate
|
|||
|
|
* tiles to its right.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if (enumRight < rect->r_xtop)
|
|||
|
|
if (tiSrAreaEnum(enumTR, enumBottom, rect, func, arg))
|
|||
|
|
return 1;
|
|||
|
|
enumTile = tp;
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* --------------------------------------------------------------------
|
|||
|
|
*
|
|||
|
|
* tiSrAreaEnum --
|
|||
|
|
*
|
|||
|
|
* Perform the recursive edge search of the tile which has just been
|
|||
|
|
* enumerated in an area search. The arguments passed are the RT
|
|||
|
|
* corner stitch and bottom coordinate of the tile just enumerated.
|
|||
|
|
*
|
|||
|
|
* Results:
|
|||
|
|
* 0 is returned if the search completed normally, 1 if
|
|||
|
|
* it was aborted.
|
|||
|
|
*
|
|||
|
|
* Side effects:
|
|||
|
|
* Attempts to enumerate recursively each tile found in walking
|
|||
|
|
* along the right edge of the tile just enumerated. Whatever
|
|||
|
|
* side effects occur result from the application of the client's
|
|||
|
|
* filter function.
|
|||
|
|
*
|
|||
|
|
* --------------------------------------------------------------------
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
int
|
|||
|
|
tiSrAreaEnum(enumRT, enumBottom, rect, func, arg)
|
|||
|
|
Tile *enumRT; /* TR corner stitch of tile just enumerated */
|
|||
|
|
int enumBottom; /* Bottom coordinate of tile just enumerated */
|
|||
|
|
Rect *rect; /* Area to search */
|
|||
|
|
int (*func)(); /* Function to apply at each tile */
|
|||
|
|
ClientData arg; /* Additional argument to pass to (*func)() */
|
|||
|
|
{
|
|||
|
|
Tile *tp, *tpLB, *tpTR;
|
|||
|
|
int tpRight, tpNextTop, tpBottom, srchBottom;
|
|||
|
|
int atBottom = (enumBottom <= rect->r_ybot);
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* Begin examination of tiles along right edge.
|
|||
|
|
* A tile to the right of the one being enumerated is enumerable if:
|
|||
|
|
* - its bottom lies at or above that of the tile being enumerated, or,
|
|||
|
|
* - the bottom of the tile being enumerated lies at or below the
|
|||
|
|
* bottom of the search rectangle.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if ((srchBottom = enumBottom) < rect->r_ybot)
|
|||
|
|
srchBottom = rect->r_ybot;
|
|||
|
|
|
|||
|
|
for (tp = enumRT, tpNextTop = TOP(tp); tpNextTop > srchBottom; tp = tpLB)
|
|||
|
|
{
|
|||
|
|
if (SigInterruptPending) return 1;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* Since the client's filter function may result in this tile
|
|||
|
|
* being deallocated or otherwise modified, we must extract
|
|||
|
|
* all the information we will need from the tile before we
|
|||
|
|
* apply the filter function.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
tpLB = LB(tp);
|
|||
|
|
tpNextTop = TOP(tpLB); /* Since TOP(tpLB) comes from tp */
|
|||
|
|
|
|||
|
|
if (BOTTOM(tp) < rect->r_ytop && (atBottom || BOTTOM(tp) >= enumBottom))
|
|||
|
|
{
|
|||
|
|
/*
|
|||
|
|
* We extract more information from the tile, which we will use
|
|||
|
|
* after applying the filter function.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
tpRight = RIGHT(tp);
|
|||
|
|
tpBottom = BOTTOM(tp);
|
|||
|
|
tpTR = TR(tp);
|
|||
|
|
if ((*func)(tp, arg)) return 1;
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* If the right boundary of the tile being enumerated is
|
|||
|
|
* inside of the search area, recursively enumerate
|
|||
|
|
* tiles to its right.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if (tpRight < rect->r_xtop)
|
|||
|
|
if (tiSrAreaEnum(tpTR, tpBottom, rect, func, arg))
|
|||
|
|
return 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|