#ifndef lint
static char *SccsId = "@(#)outp_dll.c 4.2 (TU-Delft) 01/10/92";
#endif
/*
 *      Copyright 1990 by Delft University of Technology (DUT),
 *                      Delft, The Netherlands.
 * 
 *                        All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and
 * its  documentation  without  fee,  is  hereby  granted  for  non-
 * commercial purposes  only,  provided  that  the  above  copyright
 * notice  appear  in all copies and that both that copyright notice
 * and this permission notice appear  in  supporting  documentation,
 * and  that the name of DUT not be used in advertising or publicity
 * pertaining to distribution  of  the  software  without  specific,
 * written prior permission.
 * 
 * THE DUT DISCLAIMS ALL WARRANTIES WITH REGARD  TO  THIS  SOFTWARE,
 * INCLUDING  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
 * IN NO EVENT SHALL THE DUT BE LIABLE FOR ANY SPECIAL, INDIRECT  OR
 * CONSEQUENTIAL  DAMAGES  OR  ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION  OF  CONTRACT,
 * NEGLIGENCE  OR  OTHER  TORTIOUS  ACTION,  ARISING  OUT  OF  OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 * 
 * Author(s):
 *           S. de Graaf
 *           T.G.R. van Leuken
 *           P. Kist
 * 
 * 
 * Contact address:
 * 
 * 
 * Dimes Design and Test Centre     phone: + 31 (15) 78 1459
 * Delft University of Technology   fax:   + 31 (15) 62 3271
 * P.O. Box 5053 		    email: nelsis@dutentb.tudelft.nl
 * Feldmannweg 17, 2600 GB Delft    The Netherlands
 */
#include "incl.h"
#include "extern.h"

double  px[512], py[512];

static char *formatW = "%sw %s %s,%s";
static char *formatP = "%sp %s,%s";
static char *formatC = "%sc %s,%s %s";
static char *formatMS = "ms %s\n";
static char *formatME = "me\n";
static char *formatMC = "mc %s";
static char *formatSY = "sy %s";
static char *formatCX = " cx %s,%d";
static char *formatCY = " cy %s,%d";
static char *formatMX = " mx";
static char *formatRO = " ro %d";
static char *formatSC = " sc %d";
static char *formatTR = " tr %s,%s";

outp_dll (cell)
char *cell;
{
    static int firsttime = 1;
    if (u_mode && firsttime) {
	firsttime = 0;
	formatW[2] = 'W';
	formatP[2] = 'P';
	formatC[2] = 'C';
	formatMS[0] = 'M'; formatMS[1] = 'S';
	formatME[0] = 'M'; formatME[1] = 'E';
	formatMC[0] = 'M'; formatMC[1] = 'C';
	formatSY[0] = 'S'; formatSY[1] = 'Y';
	formatCX[1] = 'C'; formatCX[2] = 'X';
	formatCY[1] = 'C'; formatCY[2] = 'Y';
	formatMX[1] = 'M'; formatMX[2] = 'X';
	formatRO[1] = 'R'; formatRO[2] = 'O';
	formatSC[1] = 'S'; formatSC[2] = 'C';
	formatTR[1] = 'T'; formatTR[2] = 'R';
    }
    PF formatMS, ut_mode ? findnew (cell) : cell);
    dll_term_copy ();
    dll_box_copy ();
    dll_nor_copy (cell);
    dll_mc_copy (cell);
    PF formatME);
}

static
dll_term_copy ()
{
    register int    i, j;
    register char  *lc;
    double  xl, yb, xlen, ylen, dx, dy;
    register DM_STREAM *stream;

    stream = dmOpenStream (ckey, "term", "r");

    while (dmGetDesignData (stream, GEO_TERM) > 0) {

	lc = lay[gterm.layer_no];
	xl = resol * gterm.xl;
	yb = resol * gterm.yb;
	xlen = resol * (gterm.xr - gterm.xl);
	ylen = resol * (gterm.yt - gterm.yb);
	dx = resol * gterm.dx;
	dy = resol * gterm.dy;

	for (i = 0; i <= gterm.nx; ++i) {
	    for (j = 0; j <= gterm.ny; ++j) {
		PF "%s %s,%s %s,%s\n", lc,
		    dtoa (xl + i * dx), dtoa (yb + j * dy),
		    dtoa (xlen), dtoa (ylen));
	    }
	}
    }
    dmCloseStream (stream, COMPLETE);
}

static
dll_box_copy ()
{
    register int    i, j;
    register char  *lc;
    double  xl, yb, xlen, ylen, dx, dy;
    register DM_STREAM *stream;

    stream = dmOpenStream (ckey, "box", "r");

    while (dmGetDesignData (stream, GEO_BOX) > 0) {

	lc = lay[gbox.layer_no];
	xl = resol * gbox.xl;
	yb = resol * gbox.yb;
	xlen = resol * (gbox.xr - gbox.xl);
	ylen = resol * (gbox.yt - gbox.yb);
	dx = resol * gbox.dx;
	dy = resol * gbox.dy;

	for (i = 0; i <= gbox.nx; ++i) {
	    for (j = 0; j <= gbox.ny; ++j) {
		PF "%s %s,%s %s,%s\n", lc,
		    dtoa (xl + i * dx), dtoa (yb + j * dy),
		    dtoa (xlen), dtoa (ylen));
	    }
	}
    }
    dmCloseStream (stream, COMPLETE);
}

static
dll_nor_copy (cell)
char *cell;
{
    double  xs, ys, r1, r2, a1, a2, dx, dy;
    int     no_xy;
    register int i, j, k;
    register char  *lc;
    register DM_STREAM *stream;

    stream = dmOpenStream (ckey, "nor", "r");

    while (dmGetDesignData (stream, GEO_NOR_INI) > 0) {
	no_xy = gnor_ini.no_xy;
	lc = lay[gnor_ini.layer_no];
	dx = resol * gnor_ini.dx;
	dy = resol * gnor_ini.dy;

	if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
	    error (2, cell);
	xs = resol * gnor_xy.x;
	ys = resol * gnor_xy.y;

	switch (gnor_ini.elmt) {
	    case WIRE_NOR: 
		if (--no_xy < 2) error (9, cell);
		r1 = xs;
		if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
		    error (2, cell);
		xs = resol * gnor_xy.x;
		ys = resol * gnor_xy.y;
		if (--no_xy > 512) error (17, cell);
		for (i = 0; i < no_xy; ++i) {
		    if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
			error (2, cell);
		    px[i] = resol * gnor_xy.x;
		    py[i] = resol * gnor_xy.y;
		}
		for (i = 0; i <= gnor_ini.nx; ++i) {
		    for (j = 0; j <= gnor_ini.ny; ++j) {
			PF formatW, lc, dtoa (r1),
			    dtoa (xs + i * dx), dtoa (ys + j * dy));
			for (k = 0; k < no_xy; ++k)
			    PF " %s,%s", dtoa (px[k]), dtoa (py[k]));
			PF "\n");
		    }
		}
		break;
	    case SBOX_NOR: 
		if (no_xy != 2) error (9, cell);
		if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
		    error (2, cell);
		r1 = resol * gnor_xy.x;
		r2 = resol * gnor_xy.y;
		a1 = ((r1 - xs) + (r2 - ys)) / 2;

		for (i = 0; i <= gnor_ini.nx; ++i) {
		    for (j = 0; j <= gnor_ini.ny; ++j) {
			PF formatP, lc,
			    dtoa (xs + i * dx), dtoa (ys + j * dy));
			PF " %s,%s %s,%s",
			    dtoa (a1), dtoa (a1),
			    dtoa (r1 - xs - a1), dtoa (r2 - ys - a1));
			PF " %s,%s %s,%s\n",
			    dtoa (-a1), dtoa (-a1),
			    dtoa (xs - r1 + a1), dtoa (ys - r2 + a1));
		    }
		}
		break;
	    case RECT_NOR: 
		if (no_xy != 4) error (9, cell);
	    case POLY_NOR: 
		if (no_xy < 3) error (9, cell);
		r1 = xs;
		r2 = ys;
		if (--no_xy >= 512) error (17, cell);
		for (i = 0; i < no_xy; ++i) {
		    if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
			error (2, cell);
		    a1 = resol * gnor_xy.x;
		    a2 = resol * gnor_xy.y;
		    px[i] = a1 - r1;
		    py[i] = a2 - r2;
		    r1 = a1;
		    r2 = a2;
		}
		px[i] = xs - r1;
		py[i] = ys - r2;

		for (i = 0; i <= gnor_ini.nx; ++i) {
		    for (j = 0; j <= gnor_ini.ny; ++j) {
			PF formatP, lc,
			    dtoa (xs + i * dx), dtoa (ys + j * dy));
			for (k = 0; k <= no_xy; ++k)
			    PF " %s,%s", dtoa (px[k]), dtoa (py[k]));
			PF "\n");
		    }
		}
		break;
	    case CIRCLE_NOR: 
		if (no_xy < 2 || no_xy > 4) error (9, cell);
		if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
		    error (2, cell);
		r1 = resol * gnor_xy.x;
		r2 = resol * gnor_xy.y;
		if (no_xy > 2) {
		    if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
			error (2, cell);
		    if (no_xy > 3) {
			if (dmGetDesignData (stream, GEO_NOR_XY) <= 0)
			    error (2, cell);
			a1 = gnor_xy.x;
			a2 = gnor_xy.y;
		    }
		}

		for (i = 0; i <= gnor_ini.nx; ++i) {
		    for (j = 0; j <= gnor_ini.ny; ++j) {
			PF formatC, lc,
			    dtoa (xs + i * dx), dtoa (ys + j * dy), dtoa (r1));
			if (no_xy > 3) {
			    if (a2 == 360)
				PF " %s %s\n", dtoa (r2), dtoa (a1));
			    else
				PF " %s %s %s\n", dtoa (r2), dtoa (a1), dtoa (a2));
			}
			else
			    if (r2 > 0)
				PF " %s\n", dtoa (r2));
			    else
				PF "\n");
		    }
		}
		break;
	    default: 
		error (6, cell);
	}
    }
    dmCloseStream (stream, COMPLETE);
}

static
dll_mc_copy (cell)
char *cell;
{
    register int mir, rot, sfx, sfy;
    register DM_STREAM *stream;
    struct na_elmt *q;

    stream = dmOpenStream (ckey, "mc", "r");

    while (dmGetDesignData (stream, GEO_MC) > 0) {

	if (gmc.imported) {
	    if (!(q = findold (gmc.cell_name, ut_mode)))
		error (1, gmc.cell_name);
	    if (iclist)
		inst_alias (iclist, q -> name);
	    else
		iclist = inst_ic_elmt (q -> name);
	    PF formatSY, ut_mode ? q -> other -> name : q -> name);
	}
	else {
	    PF formatMC, ut_mode ? findnew (gmc.cell_name) : gmc.cell_name);
	}

	if (gmc.mtx[0] == 0) {
	    if (gmc.mtx[3] > 0) {
		if (gmc.mtx[1] > 0) {/* MX+R90 */
		    mir = 1;
		    rot = 90;
		    sfx = gmc.mtx[3];
		    sfy = gmc.mtx[1];
		}
		else {		/* R90 */
		    mir = 0;
		    rot = 90;
		    sfx = gmc.mtx[3];
		    sfy = -gmc.mtx[1];
		}
	    }
	    else {
		if (gmc.mtx[1] > 0) {/* R270 */
		    mir = 0;
		    rot = 270;
		    sfx = -gmc.mtx[3];
		    sfy = gmc.mtx[1];
		}
		else {		/* MX+R270 */
		    mir = 1;
		    rot = 270;
		    sfx = -gmc.mtx[3];
		    sfy = -gmc.mtx[1];
		}
	    }
	}
	else {
	    if (gmc.mtx[0] > 0) {
		if (gmc.mtx[4] > 0) {/* R0 */
		    mir = 0;
		    rot = 0;
		    sfx = gmc.mtx[0];
		    sfy = gmc.mtx[4];
		}
		else {		/* MX+R0 */
		    mir = 1;
		    rot = 0;
		    sfx = gmc.mtx[0];
		    sfy = -gmc.mtx[4];
		}
	    }
	    else {
		if (gmc.mtx[4] > 0) {/* MX+R180 */
		    mir = 1;
		    rot = 180;
		    sfx = -gmc.mtx[0];
		    sfy = gmc.mtx[4];
		}
		else {		/* R180 */
		    mir = 0;
		    rot = 180;
		    sfx = -gmc.mtx[0];
		    sfy = -gmc.mtx[4];
		}
	    }
	}

	if (mir) PF formatMX);
	if (rot) PF formatRO, rot);
	if (gmc.mtx[2] || gmc.mtx[5])
	    PF formatTR,
		dtoa (resol * gmc.mtx[2]), dtoa (resol * gmc.mtx[5]));

	if (sfx > 1 || sfy > 1) {
	    if (sfx == sfy) PF formatSC, sfx);
	    else error (18, cell);
	}

	if (gmc.nx) PF formatCX, dtoa (resol * gmc.dx), gmc.nx);
	if (gmc.ny) PF formatCY, dtoa (resol * gmc.dy), gmc.ny);
	PF "\n");
    }
    dmCloseStream (stream, COMPLETE);
}
