/*
 * CmdAB.c --
 *
 * Commands with names beginning with the letters A through B.
 *
 *     ********************************************************************* 
 *     * Copyright (C) 1985, 1990 Regents of the University of California. * 
 *     * Permission to use, copy, modify, and distribute this              * 
 *     * software and its documentation for any purpose and without        * 
 *     * fee is hereby granted, provided that the above copyright          * 
 *     * notice appear in all copies.  The University of California        * 
 *     * makes no representations about the suitability of this            * 
 *     * software for any purpose.  It is provided "as is" without         * 
 *     * express or implied warranty.  Export of this software outside     * 
 *     * of the United States of America may require an export license.    * 
 *     *********************************************************************
 */

#ifndef lint
static char rcsid[] = "$Header: /ufs/repository/magic/commands/CmdAB.c,v 1.4 2001/01/12 22:12:16 jsolomon Exp $";
#endif  not lint

#include <stdio.h>

#include "magic/tclmagic.h"
#include "misc/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "main/main.h"
#include "commands/commands.h"
#include "utils/utils.h"
#include "textio/textio.h"
#include "drc/drc.h"
#include "cif/cif.h"
#include "graphics/graphics.h"
#include "textio/txcommands.h"
#include "utils/malloc.h"
#include "netlist/netlist.h"


/* ---------------------------------------------------------------------------
 *
 * CmdAddPath --
 *
 * Implement the "addpath" command:  append to the global cell search path.
 * (Usage superceded by extended "path" command; retained for compatibility)
 *
 * Usage:
 *	addpath path
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The search path used to find cells is appended to with the first
 *	command line argument.  See CmdLQ.CmdPath for more information.
 *
 * History:
 *	Contributed by Doug Pan and Prof. Mark Linton at Stanford.
 *
 * ---------------------------------------------------------------------------
 */
 /*ARGSUSED*/

Void
CmdAddPath( w, cmd )
    MagWindow *w;
    TxCommand *cmd;
{
    char *new;

    if (cmd->tx_argc != 2) {
	TxError("Usage: %s appended_search_path\n", cmd->tx_argv[0]);
	return;
    }
    PaAppend(&Path, cmd->tx_argv[1]);
}


/*
 * ----------------------------------------------------------------------------
 *
 * CmdArray --
 *
 * Implement the "array" command.  Make everything in the selection
 * into an array.  For paint and labels, just copy.  For subcells,
 * make each use into an arrayed use.
 *
 * Usage:
 *	array xlo xhi ylo yhi
 *	array xsize ysize
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Changes the edit cell.
 *
 * ----------------------------------------------------------------------------
 */

    /* ARGSUSED */
CmdArray(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    ArrayInfo a;
    Rect toolRect;

    if (cmd->tx_argc != 3 && cmd->tx_argc != 5) goto badusage;
    if (!StrIsInt(cmd->tx_argv[1]) || !StrIsInt(cmd->tx_argv[2])) 
	    goto badusage;
    if (cmd->tx_argc == 3)
    {
	a.ar_xlo = 0;
	a.ar_ylo = 0;
	a.ar_xhi = atoi(cmd->tx_argv[1]) - 1;
	a.ar_yhi = atoi(cmd->tx_argv[2]) - 1;
	if ( (a.ar_xhi < 0) || (a.ar_yhi < 0) ) goto badusage;
    }
    else
    {
	if (!StrIsInt(cmd->tx_argv[3]) || 
		!StrIsInt(cmd->tx_argv[4])) goto badusage;
	a.ar_xlo = atoi(cmd->tx_argv[1]);
	a.ar_xhi = atoi(cmd->tx_argv[2]);
	a.ar_ylo = atoi(cmd->tx_argv[3]);
	a.ar_yhi = atoi(cmd->tx_argv[4]);
    }

    if (!ToolGetBox((CellDef **) NULL, &toolRect))
    {
	TxError("Position the box to indicate the array spacing.\n");
	return;
    }
    a.ar_xsep = toolRect.r_xtop - toolRect.r_xbot;
    a.ar_ysep = toolRect.r_ytop - toolRect.r_ybot;

    SelectArray(&a);
    return;

badusage:
    TxError("Usage: array xlo xhi ylo yhi or array xsize ysize\n");
}

/*
 * ----------------------------------------------------------------------------
 *
 * CmdBox --
 *
 * Box command.
 *
 * Usage:
 *	box [values]
 *	box left [distance]
 *	box up [distance]
 *	box right [distance]
 *	box down [distance]
 *	box width [num]
 *	box height [num]
 *	box llx lly urx ury	(in edit cell coordinates)
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Modifies the location of the box tool.
 *
 * ----------------------------------------------------------------------------
 */
 /*ARGSUSED*/

#define INCL	16
#define INCR	17
#define INCU	18
#define INCD	19
#define DECL	20
#define DECR	21
#define DECU	22
#define DECD	23

CmdBox(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    static char *boxDirNames[] = { "left", "right", "up", "down", 
	"width", "height", "+left", "+right", "+up", "+down",
	 "-left", "-right", "-up", "-down", 0 };
    static int boxDirs[] = { GEO_WEST, GEO_EAST, GEO_NORTH, GEO_SOUTH,
	GEO_SOUTHWEST, GEO_NORTHWEST, INCL, INCR, INCU, INCD,
	DECL, DECR, DECU, DECD };
    Rect rootBox, editbox, *eboxptr;
    CellDef *rootBoxDef;
    int width, height, area, llx, lly, urx, ury;
    float iscale, oscale;

#ifdef MAGIC_WRAPPER
    bool retbox = FALSE;
#endif

    if ((cmd->tx_argc > 3) && (cmd->tx_argc != 5))
    {
	goto badusage;
    }

    windCheckOnlyWindow(&w);

    if (cmd->tx_argc != 5)
    {
	if (!ToolGetBox(&rootBoxDef, &rootBox))
	{
	    TxError("Box tool must be present\n");
	    return;
	}
    }
    else if (w == NULL)
    {
	TxError("Cursor not in a window.\n");
	return;
    }
    else rootBoxDef = ((CellUse *) w->w_surfaceID)->cu_def;

    if (cmd->tx_argc == 5)
    {
	Rect r;
	r.r_xbot = cmdParseCoord(cmd->tx_argv[1]);
	r.r_ybot = cmdParseCoord(cmd->tx_argv[2]);
	r.r_xtop = cmdParseCoord(cmd->tx_argv[3]);
	r.r_ytop = cmdParseCoord(cmd->tx_argv[4]);
	if (EditRootDef == rootBoxDef)
	    GeoTransRect(&EditToRootTransform, &r, &rootBox);
	else rootBox = r;
    }
#ifdef MAGIC_WRAPPER
    else if ((cmd->tx_argc == 2) && (cmd->tx_argv[1][0] == 'v'))
    {
	retbox = TRUE;	/* Don't print; just return the box values */
    }
#endif
    else if (cmd->tx_argc > 1)
    {
	int direction, distance;

	direction = Lookup(cmd->tx_argv[1], boxDirNames);
	if (direction < 0)
	    goto badusage;

	if (cmd->tx_argc == 3)
	    distance = cmdParseCoord(cmd->tx_argv[2]);
	else
	{
	    switch (boxDirs[direction])
	    {
		case GEO_WEST:
		case GEO_EAST:
		    distance = rootBox.r_xtop - rootBox.r_xbot;
		    break;
		case GEO_NORTH:
		case GEO_SOUTH:
		    distance = rootBox.r_ytop - rootBox.r_ybot;
		    break;
		case INCL:
		case INCR:
		case INCU:
		case INCD:
		case DECL:
		case DECR:
		case DECU:
		case DECD:
		    distance = DBLambda[1] / DBLambda[0];
		    if (distance == 0) distance = 1;
		    break;
	    }
	}

	switch (boxDirs[direction])
	{
	    case GEO_WEST:
		rootBox.r_xbot -= distance;
		rootBox.r_xtop -= distance;
		break;
	    case GEO_EAST:
		rootBox.r_xbot += distance;
		rootBox.r_xtop += distance;
		break;
	    case GEO_SOUTH:
		rootBox.r_ybot -= distance;
		rootBox.r_ytop -= distance;
		break;
	    case GEO_NORTH:
		rootBox.r_ybot += distance;
		rootBox.r_ytop += distance;
		break;
	    case GEO_SOUTHWEST:
		if (cmd->tx_argc == 3) 
		    rootBox.r_xtop = rootBox.r_xbot + distance;
		break;
	    case GEO_NORTHWEST:
		if (cmd->tx_argc == 3) 
		    rootBox.r_ytop = rootBox.r_ybot + distance;
		break;
	    case INCL:
		rootBox.r_xbot -= distance;
		break;
	    case INCR:
		rootBox.r_xtop += distance;
		break;
	    case INCU:
		rootBox.r_ytop += distance;
		break;
	    case INCD:
		rootBox.r_ybot -= distance;
		break;
	    case DECL:
		rootBox.r_xbot += distance;
		break;
	    case DECR:
		rootBox.r_xtop -= distance;
		break;
	    case DECU:
		rootBox.r_ytop -= distance;
		break;
	    case DECD:
		rootBox.r_ybot += distance;
		break;
	}
    }

#ifdef MAGIC_WRAPPER
    if (!retbox)
    {
#endif
	ToolMoveBox(TOOL_BL, &rootBox.r_ll, FALSE, rootBoxDef);
	ToolMoveCorner(TOOL_TR, &rootBox.r_ur, FALSE, rootBoxDef);
#ifdef MAGIC_WRAPPER
    }
#endif

    width = rootBox.r_xtop-rootBox.r_xbot;
    height = rootBox.r_ytop-rootBox.r_ybot;
    area = (rootBox.r_ytop-rootBox.r_ybot)*(rootBox.r_xtop-rootBox.r_xbot);

    if (EditRootDef == rootBoxDef)
    {
	eboxptr = &editbox;
	(void) ToolGetEditBox(eboxptr);
#ifdef MAGIC_WRAPPER
	if (!retbox)
#endif
	TxPrintf("Edit cell box:\n");
    }
    else
    {
	eboxptr = &rootBox;
#ifdef MAGIC_WRAPPER
	if (!retbox)
#endif
	TxPrintf("Root cell box:\n");
    }

#ifdef MAGIC_WRAPPER
    if (!retbox)
    {
#endif

    iscale = (float)DBLambda[0] / (float)DBLambda[1];
    oscale = CIFGetOutputScale(1000);	/* 1000 for conversion to um */

    TxPrintf("           width x height  (   llx,  lly  ), (   urx,  ury  )");
    if (area > 0)
	TxPrintf("  area (units^2)");

    TxPrintf("\n\nmicrons:  %6.2f x %-6.2f  (% 6.2f, % -6.2f), (% 6.2f, % -6.2f)",
		(float)width *oscale, (float)height * oscale,
		(float)eboxptr->r_xbot * oscale, (float)eboxptr->r_ybot * oscale,
		(float)eboxptr->r_xtop * oscale, (float)eboxptr->r_ytop * oscale);
    if (area > 0)
	TxPrintf("  %-10.2f", (float)area * oscale * oscale);

    TxPrintf("\nlambda:");
    if (DBLambda[0] != DBLambda[1])
    {
	TxPrintf("   %6.2f x %-6.2f  (% 6.2f, % -6.2f), (% 6.2f, % -6.2f)",
		(float)width * iscale, (float)height * iscale,
		(float)eboxptr->r_xbot * iscale, (float)eboxptr->r_ybot * iscale,
		(float)eboxptr->r_xtop * iscale, (float)eboxptr->r_ytop * iscale);
	if (area > 0)
	    TxPrintf("  %-10.2f", (float)area * iscale * iscale);
	TxPrintf("\ninternal:");
    }
    else
	TxPrintf("  ");

    TxPrintf(" %6d x %-6d  (% 6d, % -6d), (% 6d, % -6d)",
		width, height,
		eboxptr->r_xbot, eboxptr->r_ybot,
		eboxptr->r_xtop, eboxptr->r_ytop);
    if (area > 0)
	TxPrintf("  %-10d", area);
    TxPrintf("\n");

#ifdef MAGIC_WRAPPER
    }
    else
    {
	/* Return a list of llx, lly, urx, and ury */ 
	char *boxvalues = (char *)Tcl_Alloc(50);
	sprintf(boxvalues, "%d %d %d %d", eboxptr->r_xbot, eboxptr->r_ybot,
		eboxptr->r_xtop, eboxptr->r_ytop);
	Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
    }
#endif

    return;

badusage:
    TxError("Usage: box [[+/-]direction [distance]]\n");
    TxError("   or: box [width | height] [size]\n");
    TxError("   or: box llx lly urx ury     "
	"(location in edit cell coordinates)\n");

#ifdef MAGIC_WRAPPER
    TxError("   or: box values\n");
#endif
    return;
}
