/*
 *		Version : 1.0
 *		Date		: 11/06/90
 */

#include <stdio.h>
#include <signal.h>
#include MUT_H
#include MPH_H
#include "mbk_extern.h"
#include "g_visu.h"
#include "g_extern.c"

/*******************************************************************************
*		g_error : prints an error message and exits							*
*******************************************************************************/
void g_error (mesg, code)
char *mesg;
int code;
{
	fprintf (stderr, "%s\n", mesg);
	EXIT (code);
}

/*******************************************************************************
*		update_BB : updates bounding box coordinates							 *
*******************************************************************************/
void update_BB (ptdesc)
X_RECT *ptdesc;
{
	if (ptdesc->X < xvisu)
		xvisu = ptdesc->X;

	if ((ptdesc->Y - ptdesc->DY) < yvisu)
		yvisu = ptdesc->Y - ptdesc->DY;

	if (ptdesc->Y > (yvisu + dyvisu))
		dyvisu = ptdesc->Y - yvisu;

	if ((ptdesc->X + ptdesc->DX) > (xvisu + dxvisu))
		dxvisu = (ptdesc->X + ptdesc->DX) - xvisu;
}

/*******************************************************************************
*		appart_win : checks if descriptor is included in a window			*
*******************************************************************************/
int appart_win (flag, xdesc, ydesc, dxdesc, dydesc, xwin, ywin, dxwin, dywin)
unsigned char *flag;
LAMBDA xdesc, ydesc, dxdesc, dydesc;
LAMBDA xwin, ywin, dxwin, dywin;
{
LAMBDA db, dg, deltax, deltay;

#ifdef TRACE
	fprintf(stderr,"appart_win : xdesc= %g ydesc= %g dxdesc= %g dydesc= %g\n",
				(float)xdesc/2,(float)ydesc/2,(float)dxdesc/2,(float)dydesc/2);
	fprintf(stderr,"			 xwin= %g ywin= %g dxwin= %g dywin= %g\n",
				(float)xwin/2,(float)ywin/2,(float)dxwin/2,(float)dywin/2);
#endif
	db = ydesc - ywin;
	dg = xdesc - xwin;
	*flag = 0;

	if (db < 0) {
		deltay = -db - dydesc;
		if (dg < 0) {		/* zone 4 */
			deltax = -dg - dxdesc;
			if (deltax <= 0 && deltay <= 0) { /* LEFT and BOTTOM are not set */
				if (-deltay <= dywin)
					*flag |= APTOP;
				if (-deltax <= dxwin)
					*flag |= APRIGHT;
				/* In case of surround descriptor, all flags are set to 0 */
#ifdef TRACE
				fprintf (stderr, "appart_win OUT : flag= %#x\n", *flag);
#endif
				return 4;
			}
		}
		else {		/* zone 3 */
			deltax = dg - dxwin;
			if (deltax <= 0 && deltay <= 0) { /* BOTTOM is not set */
				*flag |= APLEFT;
				if (dxdesc + deltax <= 0)
					*flag |= APRIGHT;
				if (-deltay <= dywin)
					*flag |= APTOP;
#ifdef TRACE
				fprintf (stderr, "appart_win OUT : flag= %#x\n", *flag);
#endif
				return 3;
			}
		}
	} else {
		deltay = db - dywin;
		if (dg < 0) {		/* zone 1 */
			deltax = -dg - dxdesc;
			if (deltax <= 0 && deltay <= 0) { /* LEFT is not set */
				*flag |= APBOTTOM;
				if (-deltax <= dxwin)
					*flag |= APRIGHT;
				if (dydesc + deltay <= 0)
					*flag |= APTOP;
#ifdef TRACE
				fprintf (stderr, "appart_win OUT : flag= %#x\n", *flag);
#endif
				return 1;
			}
		} else {		/* zone 2 */
			deltax = dg - dxwin;
			if (deltax <= 0 && deltay <= 0) {
				*flag |= APLEFT;
				*flag |= APBOTTOM;
				if (dxdesc + deltax <= 0)
					*flag |= APRIGHT;
				if (dydesc + deltay <= 0)
					*flag |= APTOP;
#ifdef TRACE
				fprintf (stderr, "appart_win OUT : flag= %#x\n", *flag);
#endif
				return 2;
			}
		}
	}
#ifdef TRACE
	fprintf (stderr, "appart_win OUT : flag= %#x\n", *flag);
#endif
	return 0;
}

/*******************************************************************************
*		troncate : adjusts the descriptor coordinates to the window		*
*******************************************************************************/
void troncate (x, y, dx, dy, xwin, ywin, dxwin, dywin, flag)
LAMBDA *x, *y, *dx, *dy, xwin, ywin, dxwin, dywin;
unsigned char flag;
{
LAMBDA xdesc, ydesc;

#ifdef TRACE
	fprintf (stderr, "troncate : x= %g y= %g dx= %g dy= %g\n",
					 (float) *x / 2, (float) *y / 2, (float) *dx / 2, (float) *dy / 2);
	fprintf (stderr, "			 xwin= %g ywin= %g dxwin= %g dywin= %g\n,flag= %#x\n",
					 (float) xwin / 2, (float) ywin / 2, (float) dxwin / 2,
					 (float) dywin / 2, flag);
#endif

	xdesc = *x;
	ydesc = *y;
	if (flag == APSURROUND) {
		*x = xwin;
		*y = ywin;
		*dx = dxwin;
		*dy = dywin;
		return;
	}

	if (!(flag & APLEFT))
		*x = xwin;

	if (!(flag & APBOTTOM))
		*y = ywin;

	if (!(flag & APRIGHT))
		*dx = xwin + dxwin - *x;
	else
		*dx += xdesc - *x;

	if (!(flag & APTOP))
		*dy = ywin + dywin - *y;
	else
		*dy += ydesc - *y;

#ifdef TRACE
	fprintf(stderr, "troncate OUT : x= %g y= %g dx= %g dy= %g\n", 
				 (float) *x / 2, (float) *y / 2, (float) *dx / 2, (float) *dy / 2);
#endif
}

/***************************************************************************
*		make_sym : transforms the descr coord. in function of sym operation *
***************************************************************************/
void make_sym (x, y, dx, dy, dxab, dyab, sym)
LAMBDA *x, *y, dx, dy, dxab, dyab;
int sym;
{
	switch (sym) {
		case SYM_X:
			*x = -(*x) + dxab - dx;
			break;
		case SYM_Y:
			*y = -(*y) + dyab - dy;
			break;
		case SYMXY:
			*x = -(*x) + dxab - dx;
			*y = -(*y) + dyab - dy;
			break;
#ifdef DEBUG
		default:
			g_error ("make_sym : unknown transformation !", 1);
#endif
	}
}

/***************************************************************************
*		seg_coord : calculates the segment coordinates							*
***************************************************************************/
void seg_coord (ptseg, ptfig, x, y, dx, dy, ext)
phseg_list *ptseg;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy, ext;
{
#ifdef TRACE
	fprintf (stderr, "seg_coord : ptseg= %#x ptfig= %#x ext= %g\n", 
					 ptseg, ptfig, (float) ext / 2);
#endif

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

/***************************************************************************
*		trans_coord : calculates the transistor coordinates					*
***************************************************************************/
void 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) - ptseg->WIDTH) / SCALE_X;
		*y = 2 * (ptseg->Y1) / SCALE_X - ext;
		*dx = 2 * ptseg->WIDTH / SCALE_X;
		*dy = 2 * ((ptseg->Y2 - ptseg->Y1) / SCALE_X + ext);

		*x1 = (2 * (ptseg->X1) - ptseg->WIDTH) / SCALE_X - WTRANS / 2;
		*y1 = 2 * (ptseg->Y1) / 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) / SCALE_X - ext;
		*y = (2 * (ptseg->Y1) - ptseg->WIDTH) / SCALE_X;
		*dx = 2 * ((ptseg->X2 - ptseg->X1) / SCALE_X + ext);
		*dy = 2 * ptseg->WIDTH / SCALE_X;

		*x1 = 2 * (ptseg->X1) / SCALE_X - ext1 + RTRANS;
		*y1 = (2 * (ptseg->Y1) - ptseg->WIDTH) / SCALE_X - WTRANS / 2;
		*dx1 = 2 * ((ptseg->X2 - ptseg->X1) / SCALE_X + ext1 - RTRANS);
		*dy1 = 2 * ptseg->WIDTH / SCALE_X + WTRANS;
	}
}

/***************************************************************************
*		via_coord : calculates the via coordinates						 *
***************************************************************************/
void via_coord (ptvia, ptfig, x, y, dx, dy)
phvia_list *ptvia;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy;
{
	*x = 2 * (ptvia->XVIA) / SCALE_X - SIZEVIA / 2;
	*y = 2 * (ptvia->YVIA) / SCALE_X - SIZEVIA / 2;
	*dx = *dy = SIZEVIA;
}

/***************************************************************************
*		ref_coord : calculates the via coordinates						 *
***************************************************************************/
void ref_coord (ptref, ptfig, x, y, dx, dy)
phref_list *ptref;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy;
{
	*x = 2 * (ptref->XREF) / SCALE_X - SIZEVIA / 2;
	*y = 2 * (ptref->YREF) / SCALE_X - SIZEVIA / 2;
	*dx = *dy = SIZEVIA;
}

/***************************************************************************
*		con_coord : calculates the connector coordinates						*
***************************************************************************/
void 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) - ptcon->WIDTH) / SCALE_X;
			*y = 2 * (ptcon->YCON) / SCALE_X - SIZECON / 2;
			*dx = 2 * ptcon->WIDTH / SCALE_X;
			*dy = SIZECON;
			break;

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

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

		case WEST:
			*x = 2 * (ptcon->XCON) / SCALE_X - SIZECON / 2;
			*y = (2 * (ptcon->YCON) - ptcon->WIDTH) / SCALE_X;
			*dx = SIZECON;
			*dy = 2 * ptcon->WIDTH / SCALE_X;
			break;
#ifdef DEBUG
		default:
			g_error ("con_coord : unknow connector orientation !", 1);
#endif
	}
}

/***************************************************************************
*		get_layert : transforms the segment name to an order number		*
***************************************************************************/
unsigned char get_layert (layer)
char layer;
{
unsigned char i;

#ifdef TRACE
	fprintf (stderr, "get_layert : layer= %d\n", layer);
#endif
	for (i = 0; i < MAXLAYER; i++)
		if (layer == tablayer[i].LAYER_CODE)
			return i;
	return DEFAULT_LAYER;
}

/***************************************************************************
*		new_insref : Seeks the reference instance in the instance list			 *
***************************************************************************/
void new_insref ()
{
extern char run_mode;
void V_drawInsRef (), V_drawBox();
X_RECT *pt;

	pt = visu_db[get_layert(G_INS)];
	while (pt && ((phins_list *) pt->PTMBK != WORK_PHINS))
		pt = pt->NEXT;

	if (run_mode != RUN) {
		V_drawBox(ptinsref, (int)get_layert(G_INS));
		ptinsref = pt;
		V_drawInsRef();
	}
}
/* ins_con_coord : calculates the connector coordinates */
void ins_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 / 2;
			*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 - SIZECON / 2;
			*dx = 2 * ptcon->WIDTH / SCALE_X;
			*dy = SIZECON;
			break;

		case EAST:
			*x = 2 * (ptcon->XCON - ptfig->XAB1) / SCALE_X - SIZECON / 2;
			*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 - SIZECON / 2;
			*y = (2 * (ptcon->YCON - ptfig->YAB1) - ptcon->WIDTH) / SCALE_X;
			*dx = SIZECON;
			*dy = 2 * ptcon->WIDTH / SCALE_X;
			break;
#ifdef DEBUG
		default:
			g_error ("con_coord : unknow connector orientation !", 1);
#endif
	}
}

/* ins_seg_coord : calculates the segment coordinates */
void ins_seg_coord (ptseg, ptfig, x, y, dx, dy, ext)
phseg_list *ptseg;
phfig_list *ptfig;
LAMBDA *x, *y, *dx, *dy;
{

	switch (ptseg->TYPE) {
		case UP:
		case 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);
			break;

		case LEFT:
		case RIGHT:
			*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;
			break;
	}
}

