#ifndef lint
static char *SccsId = "@(#)input.c 4.10 (TU-Delft) 04/20/93";
#endif /* lint */
/**********************************************************

Name/Version      : space/4.10

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
		  : N.P. van der Meijs
Creation date     : 15-Mar-1988
Modified by       :
Modification date :


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1988. All rights reserved.
**********************************************************/
#include <stdio.h>
#include "dmincl.h"

#include "include/config.h"
#include "include/type.h"
#include "aux/aux.h"
#include "scan.h"

#ifdef GLN_ESCAPE
#include "aux/dmescape.h"
#endif /* GLN_ESCAPE */

struct e {
    edge_t    * edge;
    DM_STREAM * stream;
};

static struct e * edges = NULL;
static int        TERM_index = 0;

extern bool_t     optReadNetTerm;
extern bool_t     optRes;
extern bool_t     optCap3D;
extern int        nrOfMasks;
extern int	  nrOfExtConductors;
extern maskinfo_t * masktable;

private edge_t * doFetch ();
private void sortTerminals ();
private int compare ();

extern terminal_t ** TERM;
extern int nrOfTerminals;


#define Scale(x) ((coor_t) (scale * (x)))

void openInput (cellKey, scale)
DM_CELL * cellKey;
int scale;
{
    int i;
    terminal_t * t;
    DM_STREAM * bxxStream;
    /* Allocate the buffers */
    edges = NEW (struct e, nrOfMasks);

    /* open the individual streams per mask */

    for (i = 0; i < nrOfMasks; i++) {
	edges[i].stream = dmOpenStream 
	    (cellKey, mprintf ("%s_gln", masktable[i].name), "r");
	edges[i].edge   = doFetch (edges[i].stream, masktable[i].color);

	if (masktable[i].conductor >= 0) {

	    /* Read (possible) terminals that are defined for this mask */

	    bxxStream = NULL;
	    if (optReadNetTerm) {
		if (existDmStream (cellKey, 
				   mprintf ("n_%s_bxx", masktable[i].name))) {
		    bxxStream = dmOpenStream 
		       (cellKey, mprintf ("n_%s_bxx", masktable[i].name), "r");
		}
	    }
	    else {
		if (existDmStream (cellKey, 
				   mprintf ("t_%s_bxx", masktable[i].name))) {
		    bxxStream = dmOpenStream 
		       (cellKey, mprintf ("t_%s_bxx", masktable[i].name), "r");
		}
	    }

            if (bxxStream) {
		while (dmGetDesignData (bxxStream, GEO_BOXLAY) > 0) {
		    ASSERT (gboxlay.chk_type < nrOfTerminals);
		    t = TERM[gboxlay.chk_type];
		    t -> conductor = masktable[i].conductor;

		    if (optRes == TRUE || optCap3D == FALSE) {
			t -> x = (Scale (gboxlay.xl + gboxlay.xr)) / 2;
			t -> y = (Scale (gboxlay.yb + gboxlay.yt)) / 2;
		    }
		    else {
		       /* By putting terminals on left edge of their
			* box, we can hide terminals for the BE-mesh generation.
		        * This will give nicer meshes, better suited for
			* benchmarking.
			* An alternative could be some modification
			* of tileAddTerm.
			*/
			t -> x =  Scale (gboxlay.xl);
			t -> y = (Scale (gboxlay.yb + gboxlay.yt)) / 2;
		    }
		}
		
		dmCloseStream (bxxStream, COMPLETE);
	    }
	}
    }

    sortTerminals (TERM, nrOfTerminals);
}

void closeInput () {
    int i;

    for (i = 0; i < nrOfMasks; i++) {
	dmCloseStream (edges[i].stream, COMPLETE);
    }

    DISPOSE (edges);
}

edge_t * fetchEdge ()
{
    edge_t * edge;
    int i, min = 0;

    for (i = 1; i < nrOfMasks; i++) {
	if (edges [i].edge -> xl > edges [min].edge -> xl) continue;
	if (edges [i].edge -> xl < edges [min].edge -> xl) {min = i; continue;}
	if (edges [i].edge -> yl > edges [min].edge -> yl) continue;
	if (edges [i].edge -> yl < edges [min].edge -> yl) {min = i; continue;}
#ifndef MANHATTAN
	if (compareSlope (edges [i].edge, <, edges [min].edge)) min = i;
#endif /* MANHATTAN */
    }

    edge = edges [min].edge;
    edges [min].edge = doFetch (edges[min].stream, masktable[min].color);

    Debug (printEdge ("fetchEdge", edge));

    ASSERT (edge -> xl < edge -> xr 
	|| (edge -> xl == INF && edge -> xr == INF));
    return (edge);
}

private edge_t * doFetch (stream, color)
DM_STREAM * stream;
mask_t color;
{
    extern edge_t * createEdge ();

    int k = -1;

    k = dmGetDesignData (stream, GEO_GLN);

    if (k > 0) {
	scanInfo.edges++;
	return (createEdge ((coor_t) ggln.xl, (coor_t) ggln.yl,
	      (coor_t) ggln.xr, (coor_t) ggln.yr, (mask_t) color));
    }

    else if (k == 0)
	return (createEdge (INF, INF, INF, INF, 0));  /* EOF */

    else say ("gln read error"), die ();

    return (NULL);
}


terminal_t * fetchTerm ()
{
    Debug (fprintf (stderr, "fetch term\n"));

    if (TERM_index < nrOfTerminals)
	return (TERM[TERM_index++]);

    else {
	terminal_t * term = NEW (terminal_t, 1);
	term -> x = term -> y = INF;
	return (term);
    }
}

private void sortTerminals (base, nelem)
terminal_t ** base;
int nelem;
{
    int compare ();

    qsort ((char *) base, nelem, sizeof (terminal_t *), compare);
    TERM_index = 0;
}

private int compare (t1, t2)	/* compare two terminals on x and then y */
terminal_t ** t1, **t2;
{
    /* smallest first */
    if ((*t2) -> x > (*t1) -> x) return (-1);
    if ((*t2) -> x < (*t1) -> x) return ( 1);
    if ((*t2) -> y > (*t1) -> y) return (-1);
    if ((*t2) -> y < (*t1) -> y) return ( 1);
    return (0);
}
