[net.sources] PCB part 10 of 10

agn@cmu-cs-unh.ARPA (Andreas Nowatzyk) (08/14/85)

#
# type    sh /usru0/agn/pcb/usenet/part10   to unpack this archive.
#
echo extracting pwork.c...
cat >pwork.c <<'!E!O!F!'
/***************************************************************\
*								*
*	PCB program						*
*								*
*	Work routine section					*
*								*
*	(c) 1985		A. Nowatzyk			*
*								*
\***************************************************************/

#include "pparm.h"
#include "pcdst.h"

extern int plt(), dot();
extern struct hole *fndh();

int sp[9][2] =	{ { 0,  0},	/* search pattern		*/
		  { 1,  0},
		  { 0,  1},
		  {-1,  0},
		  { 0, -1},
		  { 1,  1},
		  {-1,  1},
		  { 1, -1},
	 	  {-1, -1}  };

int wtph;			/* wire trace phase		*/
int snct;			/* sub net counter		*/


selnet (n)			/* select a net to work on	*/
    struct nlhd *n;
/************************************************************\
* 							     *
*   note: it is assumed that that nothing else is selected!  *
* 							     *
\************************************************************/
{
    register int i, x, y;
    int schk (), sel_plt ();
    register struct nlst *p;

/* printf("*t:selnet nodes=%d\n",n->l); */

    color (selb, selb);		/* prepare operation		 */
    V.cnet = n;			/* save current net		 */
    snct = 0;
    wtvf = sel_plt;
    wthf = schk;

    i = 0;			/* remove old marks		 */
    p = n -> lp;
    while (p) {
	p -> mk = (-1);
	++i;
	p = p -> n;
    }
    if (i != n -> l)
	err ("inconsistent net length", i, n -> l, 0, 0);

    for (p = n -> lp; p; p = p -> n) {	/* select the net	 */
	x = p -> c -> x;
	y = p -> c -> y;
	if (p -> mk == -1) {
	    wtrace (x, y, vec);
	    snct++;
	}
    }

    if ((!n -> f) && (snct <= 1)) {
	printf("sel: f inconcistency -- recovered\n");
	n -> f = 1;
    }

    return (snct <= 1);		/* snct = number of sub-nets	 */
}

sel_plt (x1, y1, x2, y2)	/* select plot (insert resb)	 */
    int x1, y1, x2, y2;
{
    if (wtsb == s2b) {		/* add resb for s2b		 */
	ccc = selb | resb;
	ccm = ~(selb | resb) & 255;
    }

    plt (x1, y1, x2, y2);

    ccc = selb;
    ccm = ~selb & 255;
}

schk (x, y)			/* select check			 */
    int x, y;
{
    struct hole *hp;

/* printf("schk: x=%d y=%d\n",x,y); */
/*
 * Note: The consistency checks may be removed (to save time)
 *       if the program is more debugged.
 */
    if (pcb[y][x] & selb)
/*	err ("schk: already selected", x, y, 0, 0);*/
	err_msg("select problem: please clean");

    if (pcb[y][x] & chb) {	/* compnent hole		 */
	hp = fndh (x, y);
	if (!hp)
	    err ("schk: couldn't find hole", x, y, 0, 0);
	if (hp -> n -> mk >= 0)
	    err ("schk: already marked", x, y, 0, 0);
	hp -> n -> mk = snct;
    }

    dpin (x, y);		/* select hole			 */

    return (0);
}

center (xh, yh)			/* center on hole		 */
    int *xh, *yh;
/******************************************************************\
* 								   *
*  Returns '1' if <x,y> is part of a hole. <x,y> will be adjusted  *
*  to the center of the hole. Returns '0' with unchanged <x,y>	   *
*  otherwise. This routine is not fooled by guard bits.		   *
* 								   *
\******************************************************************/
{
    int x, y;

    x = *xh;
    y = *yh;

    if (!(pcb[y][x] & ahb))	/* no hole at all		 */
	return (0);

    if (pcb[y][x - 1] & ahb) {
	if (!(pcb[y][x + 1] & ahb)) {
	    x--;
	    if (!(pcb[y][x - 1] & ahb))
		return (0);
	}}
    else {
	x++;
	if (!(pcb[y][x] & pcb[y][x + 1] & ahb))
	    return (0);
    }

    if (pcb[y - 1][x] & ahb) {
	if (!(pcb[y + 1][x] & ahb)) {
	    y--;
	    if (!(pcb[y - 1][x] & ahb))
		return (0);
	}}
    else {
	y++;
	if (!(pcb[y][x] & pcb[y + 1][x] & ahb))
	    return (0);
    }

    *xh = x;			/* center coordinates		 */
    *yh = y;

    return (1); 		/* this is a hole!		 */
}

wtrace(x, y, b)			/* wire trace			 */
/****************************************************************\
* 								 *
*   note: don't cross wires of the same net without connection.  *
* 								 *
\****************************************************************/
    int x, y, b;
{
    register int i, j, k;
/* printf("wtrace: x=%d y=%d\n",x,y); */

    b &= pcb[y][x];
    if (center (&x, &y) && (b = vec, wthf) && (*wthf) (x, y))
	return;			/* aborted on first hole	 */

    if (!(pcb[y][x] & b))	/* no wire			 */
	return;

    pcb[y][x] |= mrkb;		/* mark start			 */
    wtph = 0;			/* phase 0			 */

    for (i = 0; i < 8; ++i) {	/* mark wires			 */
	j = pcb[y + dr[i][1]][x + dr[i][0]];
	if (!(j & mrkb) && (j &= b)) {
	    if ((j & s1b) && vtrace (x, y, i, s1b))
		break;		/* abort exit			 */
	    if (j == s2b && vtrace (x, y, i, s2b))
		break;		/* abort exit			 */
	    if (j == vec) {
		wtsb = s2b;
		if (wtvf)
		    wtvf (x, y, x + dr[i][0], y + dr[i][1]);
		j = pcb[y + 2 * dr[i][1]][x + 2 * dr[i][0]];
		if (!(j & mrkb) && (j & s2b) &&
		    vtrace (x + dr[i][0], y + dr[i][1], i, s2b))
		    break;
		k = (i + 1) & 7;
		j = pcb[y + dr[i][1] + dr[k][1]][x + dr[i][0] + dr[k][0]];
		if (!(j & mrkb) && (j & s2b) &&
		    vtrace (x + dr[i][0], y + dr[i][1], k, s2b))
		    break;
		k = (i + 7) & 7;
		j = pcb[y + dr[i][1] + dr[k][1]][x + dr[i][0] + dr[k][0]];
		if (!(j & mrkb) && (j & s2b) &&
		    vtrace (x + dr[i][0], y + dr[i][1], k, s2b))
		    break;
	    }
	}
    }

    pcb[y][x] &= ~mrkb;		/* unmark start			 */
    wtph = 1;			/* phase 1			 */

    for (i = 0; i < 8; ++i) 	/* remove marks			 */
	if (pcb[y + dr[i][1]][x + dr[i][0]] & mrkb)
		vtrace (x, y, i, mrkb);

}

vtrace (x, y, r, b)		/* vector trace		*/
    int x, y, r, b;
{
    register int i, j, x1, y1,
		 dx, dy;	/* direction vector		 */
    int     k,
	    in1, in2,		/* inhit diag. branches		 */
            x2, y2;

    static int  sm[8][4]	/* search mask			 */
			    = {	{0x0e, 0x0c, 0x06, 0x02},
				{0xe0, 0x60, 0xc0, 0x80},
				{0x38, 0x30, 0x18, 0x08},
				{0x83, 0x81, 0x03, 0x02},
				{0xe0, 0xc0, 0x60, 0x20},
				{0x0e, 0x06, 0x0c, 0x08},
				{0x83, 0x03, 0x81, 0x80},
				{0x38, 0x18, 0x30, 0x20}   };

    static int	smd[8][3]	/* search mask (diagonals)	 */
			    = { {0x1c, 0x04, 0x08},
				{0xc1, 0x01, 0x80},
				{0x70, 0x10, 0x20},
				{0x07, 0x04, 0x02},
				{0xc1, 0x40, 0x80},
				{0x1c, 0x10, 0x08},
				{0x07, 0x01, 0x02},
				{0x70, 0x40, 0x20}  };

/* printf("vtrace: x=%d y=%d r=%d b=%2x\n",x,y,r,b); */

    dx = dr[r][0];		/* save array look up's		 */
    dy = dr[r][1];

    x1 = x + dx;		/* scan vector			 */
    y1 = y + dy;
    i = 1;			/* reset length counter		 */

    if (wtph) {			/* phase 1			 */

	if (!(pcb[y1][x1] & mrkb))
	    return (0);		/* already done			 */

	do {
	    pcb[y1][x1] &= ~mrkb;
				/* remove marks			 */
	    x1 += dx;
	    y1 += dy;
	    ++i;
	} while (pcb[y1][x1] & mrkb); }

    else {			/* phase 0			 */

	if (pcb[y1][x1] & mrkb)
	    return (0);		/* already done			 */

	do {
	    j = pcb[y1][x1] |= mrkb;/* insert marks		 */

	    if ((j & ahb) && (pcb[y1 + 1][x1 + 1] & ahb) &&
		    (pcb[y1 - 1][x1 - 1] & ahb) && vhole (x1, y1, b))
		return (1);	/* trace abort			 */

	    x1 += dx;
	    y1 += dy;
	    ++i;
	    j = pcb[y1][x1];
	} while ((j & b) && !(j & mrkb));

	wtsb = b;		/* interface to trace routines	 */
	if (wtvf)		/* execute v-fuction (if any) 	 */
	    (*wtvf) (x, y, x1 - dx, y1 - dy);
    }

    if (r & 1) {		/* diagonal scan (tricky)	 */
	r--;			/* lets start at 0		 */
	i--;
	x2 = x + (dx - dy) / 2;
	x1 = x2 + dx;
	y2 = y + (dx + dy) / 2;
	y1 = y2 + dy;
	for (j = 0; j < i; j++) {
	    if (pcb[y1][x1] & b) {
		k = smd[r][0];
		if (j == i - 1)
		    k &= smd[r][1];
		if (ckv (x1, y1, k, b))
		    return (1);
	    }
	    x1 += dx;
	    y1 += dy;
	}
	x1 = x + dx - dy;
	y1 = y + dy + dx;
	in2 = pcb[y2][x2];
	for (j = 0; j < i; j++) {
	    x2 += dx;
	    y2 += dy;
	    in1 = in2;
	    in2 = pcb[y2][x2];
	    if ((pcb[y1][x1] & b & ~(in1 | in2)) &&
		    ckv (x1, y1, smd[r][2], b))
		return (1);
	    x1 += dx;
	    y1 += dy;
	}

	r++;
	x2 = x + (dx + dy) / 2;
	x1 = x2 + dx;
	y2 = y + (dy - dx) / 2;
	y1 = y2 + dy;
	for (j = 0; j < i; j++) {
	    if (pcb[y1][x1] & b) {
		k = smd[r][0];
		if (j == i - 1)
		    k &= smd[r][1];
		if (ckv (x1, y1, k, b))
		    return (1);
	    }
	    x1 += dx;
	    y1 += dy;
	}
	x1 = x + dx + dy;
	y1 = y + dy - dx;
	in2 = pcb[y2][x2];
	for (j = 0; j < i; j++) {
	    x2 += dx;
	    y2 += dy;
	    in1 = in2;
	    in2 = pcb[y2][x2];
	    if ((pcb[y1][x1] & b & ~(in1 | in2)) &&
		    ckv (x1, y1, smd[r][2], b))
		return (1);
	    x1 += dx;
	    y1 += dy;
	} }

    else {
	x1 = x + dx - dy;
	y1 = y + dy + dx;
	for (j = 0; j < i; ++j) {
	/* look for other wires		 */
	    if (pcb[y1][x1] & b) {
		k = sm[r][0];
		if (!j)
		    k &= sm[r][1];
		if (j == i - 2)
		    k &= sm[r][2];
		if (j == i - 1)
		    k &= sm[r][3];
		if (ckv (x1, y1, k, b))
		    return (1);
	    }
	    x1 += dx;
	    y1 += dy;
	}

	x1 = x + dx + dy;
	y1 = y + dy - dx;
	r++;
	for (j = 0; j < i; ++j) {/* just an other look		 */
	    if (pcb[y1][x1] & b) {
		k = sm[r][0];
		if (!j)
		    k &= sm[r][1];
		if (j == i - 2)
		    k &= sm[r][2];
		if (j == i - 1)
		    k &= sm[r][3];
		if (ckv (x1, y1, k, b))
		    return (1);
	    }
	    x1 += dx;
	    y1 += dy;
	}
    }
    return (0);
}

vhole (x, y, b)			/* some kind of interconnect hole*/
    int x, y, b;
{
    register int i, j, k;
/* printf("vhole: x=%d y=%d b=%2x\n",x,y,b); */
    if (wthf && wthf (x, y))	/* abort requested ?		 */
	return (1);

    b = vec ^ b;		/* change side			 */

    if (!(pcb[y][x] & b))	/* wire present ?		 */
	return (0);

    for (i = 0; i < 8; ++i) {
	j = pcb[y + dr[i][1]][x + dr[i][0]];
	if (j & b) {
	    if (j & (b ^ vec)) {/* this hack caused by single marker	 */
		wtsb = b;
		if (wtvf)
		    wtvf (x, y, x + dr[i][0], y + dr[i][1]);
                for (j = 0; j < 8; ++j) {
		    k = pcb[y + dr[i][1] + dr[j][1]][x + dr[i][0] + dr[j][0]];
		    if (!(k & (ahb | mrkb)) && (k & vec)) {
			if ((k & b) &&
			    vtrace(x + dr[i][0], y + dr[i][1], j, b)) {
			    pcb[y + dr[i][1]][x + dr[i][0]] |= mrkb;
			    return 1;
			}
			if ((k & (b ^ vec)) &&
			    vtrace(x + dr[i][0], y + dr[i][1], j, b ^ vec)) {
			    pcb[y + dr[i][1]][x + dr[i][0]] |= mrkb;
			    return 1;
			}
		    }
		}}
	    else if (vtrace (x, y, i, b))
		return 1;
	}
    }

    return (0);
}

ckv (x, y, s, b)		/* decide on a new direction	 */
    int  x, y, s, b;
{
    register int i, j, k;

/* printf("ckv: x=%d y=%d s=%2x b=%2x\n",x,y,s,b); */

    switch (s) {
	case 0: 
	    err ("ckv: internal program error", x, y, s, b);
	case 0x01: 
	    return (vtrace (x - dr[0][0], y - dr[0][1], 0, b));
	case 0x02: 
	    return (vtrace (x - dr[1][0], y - dr[1][1], 1, b));
	case 0x04: 
	    return (vtrace (x - dr[2][0], y - dr[2][1], 2, b));
	case 0x08: 
	    return (vtrace (x - dr[3][0], y - dr[3][1], 3, b));
	case 0x10: 
	    return (vtrace (x - dr[4][0], y - dr[4][1], 4, b));
	case 0x20: 
	    return (vtrace (x - dr[5][0], y - dr[5][1], 5, b));
	case 0x40: 
	    return (vtrace (x - dr[6][0], y - dr[6][1], 6, b));
	case 0x80: 
	    return (vtrace (x - dr[7][0], y - dr[7][1], 7, b));
	default: 		/* decide on most likely candidate	 */
	    j = 1;
	    if (wtph) {		/* phase 1				 */
		for (i = 0; i < 8; i++) {
				/* scan options 			 */
		    k = pcb[y + dr[i][1]][x + dr[i][0]];
		    if ((s & j) && (k & mrkb)) {
			return (vtrace (x - dr[i][0], y - dr[i][1], i, b));
		    }
		    j += j;
		} }
	    else {		/* phase 0				 */
		for (i = 0; i < 8; i++) {
				/* scan options 			 */
		    k = pcb[y + dr[i][1]][x + dr[i][0]];
		    if ((s & j) && (k & b) && !(k & mrkb)) {
			return (vtrace (x - dr[i][0], y - dr[i][1], i, b));
		    }
		    j += j;
		}
	    }
	    j = 1;
	    for (i = 0; i < 8; i++) {
				/* single point - take first 		 */
		if (s & j)
		    return (vtrace (x - dr[i][0], y - dr[i][1], i, b));
		j += j;
	    }
    }

    return 0;			/* to keep lint happy		 */
}

static struct nlhd *net_ptr;	/* net-ptr for fndnet - calls	 */

struct nlhd *get_net (x, y, s)	/* get net-pointer 		 */
    int x, y, s;
{
    int fndnet();

    net_ptr = 0;
    wtvf = nil;			/* identify net			 */
    wthf = fndnet;
    wtrace (x, y, s);
    return (net_ptr);		/* success			 */
}

fndnet (x, y)			/* find net pointer		 */
    int x, y;
{
    struct hole *hp, *fndh();

    if (pcb[y][x] & ishb)
	return (0);		/* don't bother with ish's	 */

    hp = fndh (x, y);
    if (!hp)
	err ("fndnet: missing hole", x, y, 0, 0);
    if (!hp -> n) {		/* unconnected pin		 */
	if (pcb[y][x] & vec)
	    err ("fndnet: net connected to invalid pin", x, y, 0, 0);
	else 
	    return (1);		/* just a unused pin		 */
    }
    net_ptr = hp -> n -> nlp;	/* found it !			 */

    return (1);			/* abort search			 */
}

deseln (n)		/* de select a net		 */
    struct nlhd *n;
{
    register int  x, y;
    int des_plt (), dpin();
    register struct nlst *p;

    color (0, selb);
    wtvf = des_plt;
    wthf = dpin;
    for (p = n -> lp; p; p = p -> n) {
	x = p -> c -> x;
	y = p -> c -> y;
	if (pcb[y][x] & selb)
	    wtrace (x, y, vec);
    }
    V.cnet = nil;
}

des_plt (x1, y1, x2, y2)	/* de - select plot (rm resb)	 */
    int x1, y1, x2, y2;
{
    if (wtsb == s2b)		/* remove resb for s2b		 */
	ccm = ~(selb | resb) & 255;

    plt (x1, y1, x2, y2);

    ccm = ~selb & 255;
}


cchk (net)		/* check connectivity on a selected net	 */
/***********************************************************************\
* 								        *
* Note:	this routine could run faster if it uses context information    *
* 	of 'wire', however that would increase side effects.	        *
* 								        *
* 	snct becomes invalid (to save time, the count is stopped if     *
* 	there are more than 1 sub nets).			        *
* 
* 	
* 								        *
\***********************************************************************/
    struct nlhd *net;
{
    struct nlst *p;
    int     cchku ();
    register int x, y;

/* printf("cchk: called\n"); */

    for (p = net -> lp; p; p = p -> n)
        p -> mk = 1;		/* set all marks to 1		 */

    wtvf = nil;			/* reset all marks to 0		 */
    wthf = cchku;
    x = net -> lp -> c -> x;
    y = net -> lp -> c -> y;
    wtrace (x, y, vec);

    for (p = net -> lp; p; p = p -> n)
	if (p -> mk)
	    return (0);		/* stop at the first counter example */

    return (1);			/* net is connected		 */
}

cchku (x, y)			/* connectivity check		 */
    int x, y;
{
    struct hole *hp;
/* printf("cchku: x=%d y=%d\n",x,y); */
    if (pcb[y][x] & chb) {
	hp = fndh (x, y);
	if (hp)
	    hp -> n -> mk = 0;
	else
	    err ("cchku: invalid connection", x, y, V.cnet, 0);
    }

    return (0);
}

struct nlhd *choose()		/* choose a net for work	*/
{
    int     ii, i, j, k, c[6], l[6], wcx, wcy;
    struct nlhd *p, *ck_lrnb();
    static int  lst = 0;

/*******************************************************\
* 						        *
*  preferences:	0. check learn buffer		        *
* 	   	1. within current window	        *
* 		2. window sized within current frame    *
* 		3. within current frame		        *
* 		4. window sized			        *
* 		5. frame sized			        *
* 		6. any net			        *
* 		7. last net (if it is incomplete)       *
* 						        *
\*******************************************************/

    p = ck_lrnb ();		/* something lerned ?		 */
    if (p)
	return (p);

    for (i=0; i < 6; (c[i] = -1, l[i++] = xmax + ymax));

    wcx = wx + 256 / cz;
    wcy = wy + 241 / cz;

    for (ii = 0; ii < V.nnh; ii++) {
	i = (ii + lst) % V.nnh;	/* do a circular shift		 */

	if (!NH[i].f && (i != lst || V.nnh < 2)) {
	    k = abs (wcx - (NH[i].x1 + NH[i].x1) / 2) +
		abs (wcy - (NH[i].y1 + NH[i].y1) / 2);
	    if ((wx <= NH[i].x1) && (wx + 512 / cz > NH[i].x2) && 
                (wy <= NH[i].y1) && (wy + 482 / cz > NH[i].y2)) {
		c[0] = i;	/* within current window	 */
		break;
	    }
	    j = ((NH[i].x2 - NH[i].x1) < 512 / cz) &&
		((NH[i].y2 - NH[i].y1) < 482 / cz);
	    if ((fx <= NH[i].x1) && (fx + 512 > NH[i].x2) &&
		(fy <= NH[i].y1) && (fy + 512 > NH[i].y2)) {
		if (j) {
		    if (k < l[1]) {
			c[1] = i;	/* window sized in currend frame */
			l[1] = k;}}
		else {
		    if (k < l[2]) {
			l[2] = k;
			c[2] = i;}}}	/* within current frame		 */
	    else if (j) {
		if (k < l[3]) {
		     l[3] = k;
		     c[3] = i;}}	/* just window sized		 */
	    else if (((NH[i].x2 - NH[i].x1) < 512) &&
		     ((NH[i].y2 - NH[i].y1) < 512)) {
		if (k < l[4]) {
		    l[4] = k;
		    c[4] = i;}}	/* just frame sized		 */
	    else if (k < l[5]) {
		l[5] = k;
		c[5] = i;}		/* just an incomplete net	 */
	}
    }

    for (i = 0; i < 6; ++i)	/* select highest priority	 */
	if (c[i] >= 0) {
	    lst = c[i];
	    return (&NH[lst]);
	}

    if ((lst > 0) && !NH[lst].f)
	return (&NH[lst]);	/* resort to previous net	 */

    return (nil);		/* no net found			 */
}

static struct nlhd *net_t_del;	/* net to delete		 */

del (x, y, b)			/* delete wire segment		 */
    int x, y, b;
{
    register int  i, j, x1, y1, x2, y2;
    int     k, delv (), delh ();
    struct  nlhd *get_net();

/* printf("del: x=%d y=%d\n",x,y); */

    x1 = y1 = (-1);
    for (i = 0; i < 9; ++i)	/* find a wire		 */
	if ((pcb[y + sp[i][1]][x + sp[i][0]] & b) && 
	    !(pcb[y + sp[i][1]][x + sp[i][0]] & selb)) {
		x1 = x + sp[i][0];
		y1 = y + sp[i][1];
		break;
	    }

    if (x1 < 0)
	return (1);		/* nothing to delete	 */

    b = pcb[y1][x1] & b;
    if (b == vec)
	b = top_side;		/* prefere top side	 */

    net_t_del = get_net (x1, y1, b);/* identify the net	 */

    if (!net_t_del) {		/* no net ?!?!		 */
	printf ("Deleting unconnected object\n");
	wtvf = delv;
	wthf = delh;
	wtrace (x1, y1, b);
	ckgp (x1, y1, b);
	return (0);
    }

    for (i = 0; i < 8; i++)	/* find direction	 */
	if (pcb[y1 + dr[i][1]][x1 + dr[i][0]] & b)
	    break;
    i = i % 8;

    x2 = x1;
    y2 = y1;
    while ((pcb[y2 + dr[i][1]][x2 + dr[i][0]] & b) &&
	   !(pcb[y2+1][x2+1] & pcb[y2-1][x2-1] & ahb)) {
	x2 += dr[i][0];		/* find one end		 */
	y2 += dr[i][1];
    }

    while ((pcb[y1 - dr[i][1]][x1 - dr[i][0]] & b) &&
	   !(pcb[y1+1][x1+1] & pcb[y1-1][x1-1] & ahb)) {
	x1 -= dr[i][0];		/* find other end	 */
	y1 -= dr[i][1];
    }

    k = abs (x1 - x2);
    k = k ? k : abs (y1 - y2);	/* get length		 */

    if (k > 1) {/* remove line */
	color (0, b);
	plt (x1 + dr[i][0], y1 + dr[i][1], x2 - dr[i][0], y2 - dr[i][1]);
    }

    j = cchk (net_t_del);	/* update conectivity		 */
    nettgo += j ^ net_t_del -> f;
    net_t_del -> f = j;
    nets_msg (nettgo);

    delc (x1, y1, b);		/* clean ends		 */
    delc (x2, y2, b);

    while (0 < --k) {		/* scan for branches	 */
	x1 += dr[i][0];
	y1 += dr[i][1];
	for (j = 0; j < 8; j++)
	     if (pcb[y1 + dr[j][1]][x1 + dr[j][0]] & b)
		delc (x1 + dr[j][0], y1 + dr[j][1], b);
    }

    return (0);
}

delv (x1, y1, x2, y2)	/* delete vector		 */
    int x1, y1, x2, y2;
{
    color (0, wtsb);	/* select color			 */
    plt (x1, y1, x2, y2);
}

delh (x, y)		/* delete hole			 */
    int x, y;
{
    if (pcb[y][x] & ishb) {
	color (0, ishb);
	dpin (x, y);
    }
    return (0);
}

delc (x, y, b)			/* clean deleted wire segments	 */
    int     x, y, b;
{
    struct nlhd *t, *get_net ();

/* printf ("delc: x=%d y=%d b=%2x\n", x, y, b); */


    t = get_net(x, y, b);	/* check connection		 */

    if (!t) {			/* dead wire: delete it		 */
	wtvf = delv;
	wthf = delh;
	wtrace (x, y, b);}
    else if (t != net_t_del) {	/* inconsistent connection !	 */
	printf ("delc: hey! inconsistent wire\n");
	return;			/* don't touch it		 */
    }

    ckgp (x, y, b);		/* clean the wire end		 */
}

home (xp, yp, xs, ys, xo, yo, b, ob)
/********************************\
* 				 *
*  try a home run to pin	 *
* 				 *
*  <xp,yp> current position	 *
*  <xs,ys> last position	 *
*  <xo,yo> origin of this trace	 *
*  <b>     desired side		 *
*  <ob>    last side		 *
* 				 *
\********************************/
    int xp, yp, xs, ys, xo, yo, b;
{
    int     i, j;

    for (i = xp - 3; i <= xp + 3; i += 3)/* look for a nearby pin */
	if ((i > 0) && (i < xmax))
	    for (j = yp - 3; j <= yp + 3; j += 3)
		if ((j > 0) && (j < ymax) && !(~pcb[j][i] & (chb | selb))) {
		    xp = i;
		    yp = j;
		    center (&xp, &yp);
		    i += 10;	/* break out			 */
		    break;
		}

    if (((xp == xo) && (yp == yo)) || (~pcb[yp][xp] & (chb | selb)))
	return (0);		/* do not head for the start point */
/*
 * note: this is the place to add a more powerful filter
 */

    if (!no_hrout)		/* use s-route			 */
	return (s_route (xs, ys, xp, yp));

    if (b & ~ob) {		/* need to change sides first	 */
	if (viaalg (b))
	    return (0);		/* sorry - no space for a hole	 */
    }

    i = abs (xs - xp);
    j = abs (ys - yp);
    i = (i < j) ? i : j;	/* largest square		 */

    if (i > 2) {		/* try diagonal approach	 */
	if (i == abs (xs - xp)) {
	    if (hpok (xs, ys, xp, (yp > ys) ? ys + i : ys - i, xp, yp, b))
		return (1);
	    if (hpok (xs, ys, xs, (yp > ys) ? yp - i : yp + i, xp, yp, b))
		return (1);
	}
	else {
	    if (hpok (xs, ys, (xp > xs) ? xs + i : xs - i, yp, xp, yp, b))
		return (1);
	    if (hpok (xs, ys, (xp > xs) ? xp - i : xp + i, ys, xp, yp, b))
		return (1);
	}
    }
    if (hpok (xs, ys, xs, yp, xp, yp, b))
	return (1);
    if (hpok (xs, ys, xp, ys, xp, yp, b))
	return (1);

    return (0);			/* it did not work	 */

}

hpok (x1, y1, x2, y2, x3, y3, b)/* check proposed home path	 */
int     x1,
        y1,
        x2,
        y2,
        x3,
        y3,
        b;
{
/* printf("hpok: x1=%d y1=%d x2=%d y2=%d x3=%d y3=%d b=%2x\n",
	x1,y1,x2,y2,x3,y3,b); */
    if (wayok (x1, y1, x2, y2, b) && wayok (x2, y2, x3, y3, b)) {
	color (b | selb, b | selb);
	plt (x1, y1, x2, y2);
	plt (x2, y2, x3, y3);
	return (1);
    }
    return (0);
}

wayok (x1, y1, x2, y2, b)	/* check one line		 */
int     x1,
        y1,
        x2,
        y2,
        b;
{
    int     i,
            j,
            dx,
            dy,
            dxd,
            dyd;
/* printf("wayok: x1=%d y1=%d x2=%d y2=%d b=%2x\n",x1,y1,x2,y2,b); */
    dx = (x1 < x2) - (x1 > x2);
    dy = (y1 < y2) - (y1 > y2);
    i = (abs (x1 - x2) > abs (y1 - y2)) ? abs (x1 - x2) : abs (y1 - y2);

    if (dx && dy) {		/* diagonal scan		 */
	dxd = (dx - dy) / 2;
	dyd = (dx + dy) / 2;
	for (j = 0; j < i; ++j) {/* check for illegal areas	 */
	    x1 += dx;
	    y1 += dy;
	    if (wayck (x1 + dx, y1 + dy, b))
		return (0);
	    if (wayck (x1 - dy, y1 + dx, b))
		return (0);
	    if (wayck (x1 + dy, y1 - dx, b))
		return (0);
	    if (wayck (x1 + dxd, y1 + dyd, b))
		return (0);
	    if (wayck (x1 + dyd, y1 - dxd, b))
		return (0);
	}
    }
    else {			/* horizontal / vertical check	 */
	for (j = 0; j < i; ++j) {/* check for illegal areas	 */
	    x1 += dx;
	    y1 += dy;
	    if (wayck (x1 + dx, y1 + dy, b))
		return (0);
	    if (wayck (x1 + dx - dy, y1 + dy + dx, b))
		return (0);
	    if (wayck (x1 + dx + dy, y1 + dy - dx, b))
		return (0);
	}
    }

    return (1);			/* check is ok			 */
}

wayck (x, y, b)			/* test illegal overlap		 */
int     x,
        y,
        b;
{
    int     i;
/* printf("wayck: x=%d y=%d b=%2x\n",x,y,b); */
    i = pcb[y][x];
    if (!(i & selb))
	return (i & (b | ahb));	/* return not 0 for an error	 */
    return (!(i & chb));
}

#define con(X, Y) prev_x+(pvws*((X)))/(i*cz), prev_y+(pvws*((Y)))/(i*cz)
static int prev_x = -1, prev_y;

prev (n, x, y)			/* display preview map		 */
    struct nlhd *n;
    int x, y;
{
    register int i, xx, yy;
    struct nlst *p;

    i = (V.BSX > V.BSY) ? V.BSX : V.BSY;
    prev_x = (x < wx) ? wx :
	     ((x > wx + (512 - pvws) / cz) ? wx + (512 - pvws) / cz : x);
    prev_y = (y < wy) ? wy :
	     ((y > wy + (482 - pvws) / cz) ? wy + (482 - pvws) / cz : y);
    color (resb, resb);

    plts (con (0, 0), con (V.BSX, 0));
    plts (con (V.BSX, 0), con (V.BSX, V.BSY));
    plts (con (V.BSX, V.BSY), con (0, V.BSY));
    plts (con (0, V.BSY), con (0, 0));

    plts (con (wx, wy),
	    con ((wx + 511 / cz > i) ? i : wx + 511 / cz, wy));
    plts (con ((wx + 511 / cz > i) ? i : wx + 511 / cz, wy),
	    con ((wx + 511 / cz > i) ? i : wx + 511 / cz,
		(wy + 481 / cz > i) ? i : wy + 481 / cz));
    plts (con ((wx + 511 / cz > i) ? i : wx + 511 / cz,
		(wy + 481 / cz > i) ? i : wy + 481 / cz),
	    con (wx, (wy + 481 / cz > i) ? i : wy + 481 / cz));
    plts (con (wx, (wy + 481 / cz > i) ? i : wy + 481 / cz),
	    con (wx, wy));

    p = n -> lp;
    while (p) {
	xx = p -> c -> x;
	yy = p -> c -> y;
	point (con (xx, yy));
	p = p -> n;
    }
}

unprev ()			/* un-display preview map	 */
{
    int i;
    if (prev_x >= 0) {
	i = (V.BSX > V.BSY) ? V.BSX : V.BSY;
	color (0, resb);
	rect (con (0, 0), con (i, i));
    }
}

#undef con

adjw (n)			/* adjust window		 */
    struct nlhd *n;
{
    int     tx, ty;

    if (no_adjw)
	return;

    if ((wx <= n -> x1) && (wx + 512 / cz > n -> x2) &&
	    (wy <= n -> y1) && (wy + 482 / cz > n -> y2))
	return;			/* everything is ok		 */

    if (((n -> x2 - n -> x1) < 510 / cz) &&
	    ((n -> y2 - n -> y1) < 480 / cz)) {
				/* fit's in readjusted window	 */
	if ((fx <= n -> x1) && (fx + 512 > n -> x2) &&
		(fy <= n -> y1) && (fy + 512 > n -> y2)) {
				/* fit's into current frame	 */
	    tx = (n -> x1 + n -> x2) / 2 - 256 / cz;
	    tx = (tx > fx + 511 - 512 / cz) ? fx + 511 - 512 / cz : tx;
	    tx = (tx < fx) ? fx : tx;
	    ty = (n -> y1 + n -> y2) / 2 - 242 / cz;
	    ty = (ty > fy + 511 - 512 / cz) ? fy + 511 - 512 / cz : ty;
	    ty = (ty < fy) ? fy : ty;
	    window (tx, ty); }
	else
	    window ((n -> x1 + n -> x2) / 2 - 256 / cz,
		    (n -> y1 + n -> y2) / 2 - 242 / cz);
	return;
    }

    if ((wx > n -> x2) || (wx + 512/cz < n -> x1) ||
	(wy > n -> y2) || (wy + 482/cz < n -> y1))
	window (n -> x1 - 10, n -> y1 - 10); /* doesnt fit in window */
    prev (n, V.BSX, V.BSY);
}

ckgp (x, y, b)		/* check for garbage points		 */
    int x, y, b;
/************************************************************\
* 							     *
*  This routine removes bits on plane <b> at location <x,y>  *
*  if they do not contribute to a connection. A via-hole     *
*  will be removed if it is redundant.			     *
* 							     *
\************************************************************/
{
    register int  i, j, k, p;

    p = pcb[y][x];
    if (!(p & b))
	return;			/* nothing to do		 */

    if (center (&x, &y)) {	/* this is a hole		 */

	color (0, b | selb);	/* scan arround hole		 */
	for (i = 0; i < 8; i++)	/* scan hole area		 */
	    ck_rdnb (x + dr[i][0], y + dr[i][1], b);
	color (0, (b ^ vec) | selb);/* just for fun: do other side */
	for (j = i = 0; i < 8; i++) {/* scan hole area */
	    ck_rdnb (x + dr[i][0], y + dr[i][1], b ^ vec);
	    j |= pcb[y + dr[i][1]][x + dr[i][0]];
	}

	if (~j & vec) {		/* remove center		 */
	    color (0, (~j & vec) | selb);
	    pxl (x, y);
	    if (p & ishb) {	/* remove via holes only	 */
		color (0, selb | ishb);
		dpin (x, y);
	    }
	}

	if (p & selb) {		/* undo deselect		 */
	    k = 1;
	    for (i = x - 1; i <= x + 1; ++i)
		for (j = y - 1; j <= y + 1; ++j)
		    if (pcb[j][i] & (ahb | vec)) {
			if (k) {
			    k = 0;
			    color (selb, selb);
			} pxl (i, j);
		    }
	}}
    else {			/* this is just a bit		 */
	color (0, b | (p & selb));
	ck_rdnb (x, y, b);
    }
}

char uc_tab[256] = {		/* table of useful connections	 */
		1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,
		1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,
		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,
		1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
		1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
		1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
		1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
		1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1  };

ck_rdnb (x, y, b)	/* check for redundant bit		*/
    int x, y, b;
/***********************************************************\
* 							    *
* The bit <b> at location <x,y> will be removed if it does  *
* not contribute to a electrical connection.		    *
* 							    *
\***********************************************************/
{   int i, j, k;

    for ((j = 1, i = k = 0); i < 8; (++i, j += j))
	k |= (pcb[y + dr[i][1]][x + dr[i][0]] & b) ? j : 0;
    if (uc_tab[k])
	pxl (x, y);
}
!E!O!F!