static char *SccsId = "@(#)stretch.c 3.1 (TU-Delft) 04/16/87";
/**********************************************************

Name/Version      : sldm/3.1

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

Author(s)         : N. van der Meijs
Creation date     : 17-Oct-1984
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) 1984 , All rights reserved
**********************************************************/
# include "sldm.h"


/*
** doStretch - actually compute stretch values 
**
** This routine is called for every combination of
** box (or terminal) and stretch line.
** It computes for every such combination the amount of
** stretching that is needed.
** The caller accumulates these values for every box.
**
** When the box or terminal can't be stretched, 
** i.e. because the stretch line only partially intersects
** the box, the value CANT is returned, and the caller
** must take appropriate action.
** In case of a box, this action is to split the box,
** but a terminal can't be split.
*/

doStretch (d_lo, d_hi, l, r, b, t, layer, sp)
int    *d_hi,
       *d_lo;
int     l, r, b, t;
int     layer;
STRETCH * sp;
{

    int     result = OK;   /* return value, can also be CANT */
    int     place;         /* return value of position */
    int     icount;        /* return value of intersect */
    boolean checkLayer ();
    boolean checkModifier ();

#ifdef DEBUG
    static char *pos[] = {
	"NULL",
	"HIGHER",
	"HEDGE",
	"MID",
	"LEDGE",
	"LOWER",
	"NEXT"
    };
    if (DEBUG) {
	fprintf (stderr,
"\ndoStretch: d_lo: %d, d_hi: %d, lrbt: %d %d %d %d, layer: %c\n",
		*d_lo, *d_hi, l, r, b, t, layer);
	fprintf (stderr,
"lo: %d hi: %d pos: %d val: %d dir: %c p_mod: '%s' m_mod: '%s'\n",
		sp -> lo,
		sp -> hi,
		sp -> pos,
		sp -> val,
		sp -> dir,
		sp -> p_mod,
		sp -> m_mod);

	fprintf (stderr, "intersect: %d, position: '%s'\n",
		intersect (l, r, b, t, sp),
		pos[position (l, r, b, t, sp)]);
    }
#endif DEBUG

    if (!checkLayer (layer, sp)) {
	return (OK);	   /* stretch line not active on
			      this layer */
    }

    if ((icount = intersect (l, r, b, t, sp)) == 0) {
	return (OK);	   /* stretch line does not
			      intersect the box */
    }

    if (icount != 1 && icount != 2) {
	PANIC ("bad icount: %d", icount);
    }

    place = position (l, r, b, t, sp);

    switch (place) {
	case HIGHER: 	   /* do nothing */
	    break;
	case HEDGE: 
	    if (!checkModifier ('-', layer, sp))
		break;
	/* else    : same as case MID */
	case MID: 
	    if (icount == 2)
		*d_hi += sp -> val;
	    else 
		result = CANT;
	    break;
	case LEDGE: 
	    if (icount == 2) {
		*d_hi += sp -> val;
		if (!checkModifier ('+', layer, sp))
		    *d_lo += sp -> val;
	    }
	    else 
		result = CANT;
	    break;
	case LOWER: 
	    if (icount == 2) {
		*d_hi += sp -> val;
		*d_lo += sp -> val;
	    }
	    else 
		result = CANT;
	    break;
	default: 
	    PANIC ("bad place %d", place);
	    break;
    }

#ifdef DEBUG
    if (result == CANT && DEBUG)
	fprintf (stderr, "CANT\n");
#endif DEBUG

    return (result);
}

/* checkModifier - check plus, min or touch modifier */

static  boolean checkModifier (mode, layer, sp)
int         mode,          /* check +, - or =  modifier */
            layer;         /* layer of box */
STRETCH * sp;	           /* addres of STRETCH node */
{
    char   *strchr ();
    char   *mod;
    switch (mode) {
	case '+': 
	    mod = sp -> p_mod;
	    break;
	case '-': 
	    mod = sp -> m_mod;
	    break;
	case '=': 
	    mod = sp -> t_mod;
	    break;
	default: 
	    PANIC ("bad mode: %d", mode);
	    return (FALSE);
	    break;
    }
    return (strchr (mod, layer)
	    != (char *) NULL ? TRUE : FALSE);
}

/* checkLayer - check layer */

static  boolean checkLayer (layer, sp)
int     layer;	           /* layer of box */
STRETCH * sp;	           /* addres of STRETCH node */
{

    if (sp -> layer == 0 || sp -> layer == layer)
	return (TRUE);
    else 
	return (FALSE);
}
