/*
 * MBK : Peek management functions
 * Version : 1.0								
 * Date		: 11/06/90			 
 */
#include <stdio.h>
#include MUT_H
#include MPH_H
#include "mbk_extern.h"
#include "g_visu.h"
#include "g_extern.c"
#include "v_view.h"

/* Objects coordinates :
   coordinates computations are very much alike the one of g_user.c,
   the only difference is that the figure abutment box must be considered
   since coordinates should be good regarding the actual figure. */
void
	peek_seg_coord(ptseg, ptfig, x, y, dx, dy, ext)
phseg_list *ptseg;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy, ext;
{

	if (ptseg->TYPE == UP || ptseg->TYPE == DOWN) {
		*x = (2 * (ptseg->X1 - ptfig->XAB1) - ptseg->WIDTH) / SCALE_X;
		*y = 2 * (ptseg->Y1 - ptfig->YAB1) / SCALE_X - ext;
		*dx = 2 * ptseg->WIDTH / SCALE_X;
		*dy = 2 * ((ptseg->Y2 - ptseg->Y1) / SCALE_X + ext);
	} else {
		*x = 2 * (ptseg->X1 - ptfig->XAB1) / SCALE_X - ext;
		*y = (2 * (ptseg->Y1 - ptfig->YAB1) - ptseg->WIDTH) / SCALE_X;
		*dx = 2 * ((ptseg->X2 - ptseg->X1) / SCALE_X + ext);
		*dy = 2 * ptseg->WIDTH / SCALE_X;
	}
}

void
	peek_trans_coord(ptseg, ptfig, x, y, dx, dy, x1, y1, dx1, dy1, ext, ext1)
phseg_list *ptseg;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy, *x1, *y1, *dx1, *dy1, ext, ext1;
{
	if (ptseg->TYPE == UP || ptseg->TYPE == DOWN) {
		*x = (2 * (ptseg->X1 - ptfig->XAB1) - ptseg->WIDTH) / SCALE_X;
		*y = 2 * (ptseg->Y1 - ptfig->YAB1) / SCALE_X - ext;
		*dx = 2 * ptseg->WIDTH / SCALE_X;
		*dy = 2 * ((ptseg->Y2 - ptseg->Y1) / SCALE_X + ext);
		*x1 =
			(2 * (ptseg->X1 - ptfig->XAB1) - ptseg->WIDTH) / SCALE_X - WTRANS / 2;
		*y1 = 2 * (ptseg->Y1 - ptfig->YAB1) / SCALE_X - ext1 + RTRANS;
		*dx1 = 2 * ptseg->WIDTH / SCALE_X + WTRANS;
		*dy1 = 2 * ((ptseg->Y2 - ptseg->Y1) / SCALE_X + ext1 - RTRANS);
	} else {
		*x = 2 * (ptseg->X1 - ptfig->XAB1) / SCALE_X - ext;
		*y = (2 * (ptseg->Y1 - ptfig->YAB1) - ptseg->WIDTH) / SCALE_X;
		*dx = 2 * ((ptseg->X2 - ptseg->X1) / SCALE_X + ext);
		*dy = 2 * ptseg->WIDTH / SCALE_X;
		*x1 = 2 * (ptseg->X1 - ptfig->XAB1) / SCALE_X - ext1 + RTRANS;
		*y1 =
			(2 * (ptseg->Y1 - ptfig->YAB1) - ptseg->WIDTH) / SCALE_X - WTRANS / 2;
		*dx1 = 2 * ((ptseg->X2 - ptseg->X1) / SCALE_X + ext1 - RTRANS);
		*dy1 = 2 * ptseg->WIDTH / SCALE_X + WTRANS;
	}
}

void
	peek_ref_coord(ptref, ptfig, x, y, dx, dy)
phref_list *ptref;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy;
{
	*x = 2 * (ptref->XREF - ptfig->XAB1) / SCALE_X - SIZEVIA / 2;
	*y = 2 * (ptref->YREF - ptfig->YAB1) / SCALE_X - SIZEVIA / 2;
	*dx = *dy = SIZEVIA;
}

void
	peek_via_coord(ptvia, ptfig, x, y, dx, dy)
phvia_list *ptvia;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy;
{
	*x = 2 * (ptvia->XVIA - ptfig->XAB1) / SCALE_X - SIZEVIA / 2;
	*y = 2 * (ptvia->YVIA - ptfig->YAB1) / SCALE_X - SIZEVIA / 2;
	*dx = *dy = SIZEVIA;
}

void
	peek_con_coord(ptcon, ptfig, x, y, dx, dy)
phcon_list *ptcon;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy;
{
	switch (ptcon->ORIENT) {
		case NORTH:
			*x = (2 * (ptcon->XCON - ptfig->XAB1) - ptcon->WIDTH) / SCALE_X;
			*y = 2 * (ptcon->YCON - ptfig->YAB1) / SCALE_X - SIZECON;
			*dx = 2 * ptcon->WIDTH / SCALE_X;
			*dy = SIZECON;
			break;

		case SOUTH:
			*x = (2 * (ptcon->XCON - ptfig->XAB1) - ptcon->WIDTH) / SCALE_X;
			*y = 2 * (ptcon->YCON - ptfig->YAB1) / SCALE_X;
			*dx = 2 * ptcon->WIDTH / SCALE_X;
			*dy = SIZECON;
			break;

		case EAST:
			*x = 2 * (ptcon->XCON - ptfig->XAB1) / SCALE_X - SIZECON;
			*y = (2 * (ptcon->YCON - ptfig->YAB1) - ptcon->WIDTH) / SCALE_X;
			*dx = SIZECON;
			*dy = 2 * ptcon->WIDTH / SCALE_X;
			break;

		case WEST:
			*x = 2 * (ptcon->XCON - ptfig->XAB1) / SCALE_X;
			*y = (2 * (ptcon->YCON - ptfig->YAB1) - ptcon->WIDTH) / SCALE_X;
			*dx = SIZECON;
			*dy = 2 * ptcon->WIDTH / SCALE_X;
			break;
	}
}

/* special concern :
   In case one doesn't want an overlap of the actual figure contents on
   the peek, the figure structure is duplicated into the peek data structure
   so the layers are sorted the right way.
   There is no way to have names or any inspect information when this mode is
   in use. */
static int
	peekfig(xwin, ywin, dxwin, dywin)
int xwin, ywin, dxwin, dywin;
{
X_RECT *pt;
X_RECTPEEK *ptdesc, *aux;
LAMBDA x, y, dx, dy;
int i;
char flag;

	for (i = 0; i < GC_INSTANCE; i++) {
		pt = visu_db[i];
		while (pt) {
			x = pt->X;
			dx = pt->DX;
			dy = pt->DY;
			y = pt->Y - dy;
			if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
				ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
				/* Descriptors are adjusted to the peek window */
				troncate(&x, &y, &dx, &dy, xwin, ywin, dxwin, dywin, flag);
				ptdesc->X = x;
				ptdesc->DX = dx;
				ptdesc->DY = dy;
				ptdesc->Y = y + dy;
				ptdesc->TYPE = 0;
				aux = peek_db[i];
				peek_db[i] = ptdesc;
				ptdesc->NEXT = aux;
			}
			pt = pt->NEXT;
		}
	}
	return 1;
}

/* peek functions :
   insert mbk elements into the peek data structure. */
void
	peek_ref(ptfig, ptins, xwin, ywin, dxwin, dywin)
phfig_list *ptfig;
phins_list *ptins;
LAMBDA xwin, ywin, dxwin, dywin;
{
phref_list *ptref;
LAMBDA x, y, dx, dy, xins, yins, dxab, dyab;
X_RECTPEEK *ptdesc, *aux;
unsigned char layer, flag;
int sym;

	sym = ptins->TRANSF;
	dxab = 2 * (ptfig->XAB2 - ptfig->XAB1) / SCALE_X;
	dyab = 2 * (ptfig->YAB2 - ptfig->YAB1) / SCALE_X;
	xins = 2 * ptins->XINS / SCALE_X;
	yins = 2 * ptins->YINS / SCALE_X;

	ptref = ptfig->PHREF;
	while (ptref) {
		peek_ref_coord(ptref, ptfig, &x, &y, &dx, &dy);
		/* If the instance has a symmetry operation */
		if (sym != NOSYM)
			make_sym(&x, &y, dx, dy, dxab, dyab, sym);
		/* update ref coordinates in comparison with instance coordinates */
		x += xins;
		y += yins;
		if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
			ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
			/* Descriptors are adjusted to the peek window */
			troncate(&x, &y, &dx, &dy, xwin, ywin, dxwin, dywin, flag);
			ptdesc->X = x;
			ptdesc->DX = dx;
			ptdesc->DY = dy;
			ptdesc->Y = y + dy;
			ptdesc->TYPE = 64; /* REFERENCE */
			layer = get_layert(G_REF);
			/* Insert descriptor in peek database */
			aux = peek_db[layer];
			peek_db[layer] = ptdesc;
			ptdesc->NEXT = aux;
		}
		ptref = ptref->NEXT;
	}
}

void
	peek_via(ptfig, ptins, xwin, ywin, dxwin, dywin)
phfig_list *ptfig;
phins_list *ptins;
LAMBDA xwin, ywin, dxwin, dywin;
{
phvia_list *ptvia;
LAMBDA x, y, dx, dy, xins, yins, dxab, dyab;
X_RECTPEEK *ptdesc, *aux;
unsigned char layer, type, flag;
int sym;

	sym = ptins->TRANSF;
	dxab = 2 * (ptfig->XAB2 - ptfig->XAB1) / SCALE_X;
	dyab = 2 * (ptfig->YAB2 - ptfig->YAB1) / SCALE_X;
	xins = 2 * ptins->XINS / SCALE_X;
	yins = 2 * ptins->YINS / SCALE_X;

	ptvia = ptfig->PHVIA;
	while (ptvia) {
		peek_via_coord(ptvia, ptfig, &x, &y, &dx, &dy);
		if (sym != NOSYM)
			make_sym(&x, &y, dx, dy, dxab, dyab, sym);
		/* update via coordinates in comparison with instance coordinates */
		x += xins;
		y += yins;

		if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
			/* Descriptors are adjusted to the peek window */
			troncate(&x, &y, &dx, &dy, xwin, ywin, dxwin, dywin, flag);
			if (ptvia->TYPE < C_X_N) {
				ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
				ptdesc->X = x;
				ptdesc->Y = y + dy;
				ptdesc->DX = dx;
				ptdesc->DY = dy;
				ptdesc->TYPE = VIA | (ptvia->TYPE << 4);
				switch (ptvia->TYPE) {
					case CONT_POLY :
						type = G_CONT_POLY; 
						break;
					case CONT_DIF_N : 
						type = G_CONT_DIFN; 
						break;
					case CONT_DIF_P : 
						type = G_CONT_DIFP; 
						break;
					case CONT_BODY_N : 
						type = G_CONT_BODY_N; 
						break;
					case CONT_BODY_P : 
						type = G_CONT_BODY_P; 
						break;
					case CONT_VIA : 
						type = G_CONT_VIA; 
						break;
					case CONT_VIA2 : 
						type = G_CONT_VIA2; 
						break;
				}
				layer = get_layert(type);
				/* Insert descriptor in peek database */
				aux = peek_db[layer];
				peek_db[layer] = ptdesc;
				ptdesc->NEXT = aux;
			} else {
				int layer = get_layert(G_GATE);
				/* gate part of macro */
				ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
				ptdesc->X = x + 1;
				ptdesc->Y = y + dy - 1;
				ptdesc->DX = dx - 2;
				ptdesc->DY = dy - 2;
				ptdesc->TYPE = VIA | (ptvia->TYPE << 3);
				aux = peek_db[layer];
				peek_db[layer] = ptdesc;
				ptdesc->NEXT = aux;
				/* dif part of macro */
				layer = get_layert(ptvia->TYPE == C_X_N ? NDIF : PDIF);
				ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
				ptdesc->X = x - 3;
				ptdesc->Y = y + dy + 3;
				ptdesc->DX = dx + 6;
				ptdesc->DY = dy + 6;
				ptdesc->TYPE = 0xFF; /* VIA | (ptvia->TYPE << 4);*/
				aux = peek_db[layer];
				peek_db[layer] = ptdesc;
				ptdesc->NEXT = aux;
			} 
		}
		ptvia = ptvia->NEXT;
	}
}

void
	peek_trans(ptfig, ptseg, ptins, indicepoly, indicedif,
					xwin, ywin, dxwin, dywin)
phfig_list *ptfig;
phseg_list *ptseg;
phins_list *ptins;
unsigned char indicepoly, indicedif;
LAMBDA xwin, ywin, dxwin, dywin;
{
LAMBDA x, y, dx, dy, x1, y1, dx1, dy1, xins, yins, dxab, dyab;
X_RECTPEEK *ptdesc, *aux;
unsigned char flag;
int sym;

	sym = ptins->TRANSF;
	dxab = 2 * (ptfig->XAB2 - ptfig->XAB1) / SCALE_X;
	dyab = 2 * (ptfig->YAB2 - ptfig->YAB1) / SCALE_X;
	xins = 2 * ptins->XINS / SCALE_X;
	yins = 2 * ptins->YINS / SCALE_X;
	/* calculates the two segments coordinates that compose the transistor */
	peek_trans_coord(ptseg, ptfig, &x, &y, &dx, &dy, &x1, &y1, &dx1, &dy1,
			tablayer[indicepoly].EXT, tablayer[indicedif].EXT);
	/* If the instance has a symmetry operation */
	if (sym != NOSYM) {
		make_sym(&x, &y, dx, dy, dxab, dyab, sym);
		make_sym(&x1, &y1, dx1, dy1, dxab, dyab, sym);
	}
	/* update segments coordinates in comparison with instance coordinates */
	x += xins;
	y += yins;
	x1 += xins;
	y1 += yins;
	if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
		ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
		/* Descriptors are adjusted to the peek window */
		troncate(&x, &y, &dx, &dy, xwin, ywin, dxwin, dywin, flag);
		ptdesc->X = x;
		ptdesc->Y = y + dy;
		ptdesc->DX = dx;
		ptdesc->DY = dy;
		/* Insert descriptor in peek database */
		aux = peek_db[indicepoly];
		peek_db[indicepoly] = ptdesc;
		ptdesc->NEXT = aux;
	}
	/* Same thing for the second segment */
	if (appart_win(&flag, x1, y1, dx1, dy1, xwin, ywin, dxwin, dywin)) {
		ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
		troncate(&x1, &y1, &dx1, &dy1, xwin, ywin, dxwin, dywin, flag);
		ptdesc->X = x1;
		ptdesc->Y = y1 + dy1;
		ptdesc->DX = dx1;
		ptdesc->DY = dy1;

		aux = peek_db[indicedif];
		peek_db[indicedif] = ptdesc;
		ptdesc->NEXT = aux;
	}
}

void
	peek_seg(ptfig, ptins, xwin, ywin, dxwin, dywin)
phfig_list *ptfig;
phins_list *ptins;
LAMBDA xwin, ywin, dxwin, dywin;
{
phseg_list *ptseg;
LAMBDA x, y, dx, dy, xins, yins, dxab, dyab;
X_RECTPEEK *ptdesc, *aux;
unsigned char layer, flag;
int sym;

	sym = ptins->TRANSF;
	dxab = 2 * (ptfig->XAB2 - ptfig->XAB1) / SCALE_X;
	dyab = 2 * (ptfig->YAB2 - ptfig->YAB1) / SCALE_X;
	xins = 2 * ptins->XINS / SCALE_X;
	yins = 2 * ptins->YINS / SCALE_X;

	ptseg = ptfig->PHSEG;
	while (ptseg) {
	/* Scan if the segment is a transistor or not */
		if (ptseg->LAYER == PTRANS)
			peek_trans(ptfig, ptseg, ptins,
							get_layert(G_GATE), get_layert(PDIF),
							xwin, ywin, dxwin, dywin);
		else if (ptseg->LAYER == NTRANS)
			peek_trans(ptfig, ptseg, ptins,
							get_layert(G_GATE), get_layert(NDIF),
							xwin, ywin, dxwin, dywin);
		else {
			layer = get_layert(ptseg->LAYER);
			peek_seg_coord(ptseg, ptfig, &x, &y, &dx, &dy, tablayer[layer].EXT);
		/* If the instance has a symmetry operation */
		if (sym != NOSYM)
			make_sym(&x, &y, dx, dy, dxab, dyab, sym);
		/* update segment coordinates in comparison with instance coordinates */
		x += xins;
		y += yins;
		if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
			ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK)) ;
			/* Descriptors are adjusted to the peek window */
			troncate(&x, &y, &dx, &dy, xwin, ywin, dxwin, dywin, flag);
			ptdesc->X = x;
			ptdesc->DX = dx;
			ptdesc->DY = dy;
			ptdesc->Y = y + dy;
			/* Insert descriptor in peek database */
			aux = peek_db[layer];
			peek_db[layer] = ptdesc;
			ptdesc->NEXT = aux;
			}
		}
		ptseg = ptseg->NEXT;
	} 
}

void
	peek_con(ptfig, ptins, xwin, ywin, dxwin, dywin)
phfig_list *ptfig;
phins_list *ptins;
LAMBDA xwin, ywin, dxwin, dywin;
{
phcon_list *ptcon;
LAMBDA x, y, dx, dy, xins, yins, dxab, dyab;
X_RECTPEEK *ptdesc, *aux;
unsigned char layer, flag;
int sym;

	sym = ptins->TRANSF;
	dxab = 2 * (ptfig->XAB2 - ptfig->XAB1) / SCALE_X;
	dyab = 2 * (ptfig->YAB2 - ptfig->YAB1) / SCALE_X;
	xins = 2 * ptins->XINS / SCALE_X;
	yins = 2 * ptins->YINS / SCALE_X;

	ptcon = ptfig->PHCON;
	while (ptcon) {
		peek_con_coord(ptcon, ptfig, &x, &y, &dx, &dy);
		/* If the instance has a symmetry operation */
		if (sym != NOSYM)
			make_sym(&x, &y, dx, dy, dxab, dyab, sym);
		/* update via coordinates in comparison with instance coordinates */
		x += xins;
		y += yins;
		if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
			ptdesc = (X_RECTPEEK *)mbkalloc(sizeof(X_RECTPEEK));
			/* Descriptors are adjusted to the peek window */
			troncate(&x, &y, &dx, &dy, xwin, ywin, dxwin, dywin, flag);
			ptdesc->X = x;
			ptdesc->DX = dx;
			ptdesc->DY = dy;
			ptdesc->Y = y + dy;
			/* Insert descriptor in peek database */
			layer = get_layert(ptcon->LAYER);
			aux = peek_db[layer];
			peek_db[layer] = ptdesc;
			ptdesc->NEXT = aux;
		}
		ptcon = ptcon->NEXT;
	}
}

/* peek :
   gets all instances in the peek window and flattens them. */
int
	peek(xwin, ywin, dxwin, dywin)
LAMBDA xwin, ywin, dxwin, dywin;
{
unsigned char flag;
LAMBDA x, y, dx, dy;
X_RECT *pt;
int insflag = 0;
phfig_list *ptfig, *dup_phfig();
phins_list *ptins;
char flat;
extern int C_atomicValue;
#define TRUE 0
#define FALSE 1

	/* Seeks instances that intersect the peek window ...  */
	pt = visu_db[get_layert(G_INS)];

	while (pt) {
		x = pt->X;
		dx = pt->DX;
		dy = pt->DY;
		y = pt->Y - dy;
		if (appart_win(&flag, x, y, dx, dy, xwin, ywin, dxwin, dywin)) {
			/* and flattens them */
			ptfig =
				dup_phfig(getphfig(((phins_list *)pt->PTMBK)->FIGNAME, 'A'), &flat);
			r_peek_flat(ptfig);
			ptins = (phins_list *)pt->PTMBK;
			peek_seg(ptfig, ptins, xwin, ywin, dxwin, dywin);
			peek_via(ptfig, ptins, xwin, ywin, dxwin, dywin);
			peek_ref(ptfig, ptins, xwin, ywin, dxwin, dywin);
			peek_con(ptfig, ptins, xwin, ywin, dxwin, dywin);
			insflag = 1;
		}
		pt = pt->NEXT;
	}

	if (C_atomicValue != 0)
		if (peekfig(xwin, ywin, dxwin, dywin) == 1)
			insflag = 1;
	return insflag;
}

/* unpeek :
   detroys the peek data structure. */
void
	unpeek()
{
int i;
X_RECTPEEK *ptdesc, *aux;

	for (i = 0; i <= DEFAULT_LAYER; i++) {
		ptdesc = peek_db[i];
		while (ptdesc) {
			aux = ptdesc->NEXT;
			mbkfree((void *)ptdesc);
			ptdesc = aux;
		}
		peek_db[i] = NULL;
	}
}
