2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* CmdAB.c --
|
|
|
|
|
*
|
|
|
|
|
* Commands with names beginning with the letters A through B.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * 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. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
2024-10-04 13:09:00 +02:00
|
|
|
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdAB.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
|
|
|
#include "utils/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 "utils/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 "utils/netlist.h"
|
|
|
|
|
#include "select/select.h"
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* ---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CmdAddPath --
|
|
|
|
|
*
|
|
|
|
|
* Implement the "addpath" command: append to the global cell search path.
|
2023-10-16 23:29:05 +02:00
|
|
|
* (Usage superseded by extended "path" command; retained for compatibility)
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
|
|
|
|
* 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
|
2024-10-04 13:03:23 +02:00
|
|
|
CmdAddPath(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
if (cmd->tx_argc != 2) {
|
|
|
|
|
TxError("Usage: %s appended_search_path\n", cmd->tx_argv[0]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
PaAppend(&Path, cmd->tx_argv[1]);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/* Linked-list structure for returning information about arrayed cells */
|
|
|
|
|
|
|
|
|
|
typedef struct LA1
|
|
|
|
|
{
|
|
|
|
|
CellUse *cellUse;
|
|
|
|
|
ArrayInfo arrayInfo;
|
|
|
|
|
struct LA1 *ar_next;
|
|
|
|
|
} LinkedArray;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* 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 | xsize ysize
|
|
|
|
|
*
|
|
|
|
|
* array count [xlo xhi ylo yhi | xsize ysize]
|
|
|
|
|
* array width [value]
|
|
|
|
|
* array height [value]
|
|
|
|
|
* array pitch [x y]
|
|
|
|
|
* array position [x y]
|
|
|
|
|
* array help
|
|
|
|
|
*
|
|
|
|
|
* array -list [count | width | height | pitch [x y] | position [x y]]
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Changes the edit cell.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define ARRAY_COUNT 0
|
|
|
|
|
#define ARRAY_WIDTH 1
|
|
|
|
|
#define ARRAY_HEIGHT 2
|
|
|
|
|
#define ARRAY_PITCH 3
|
|
|
|
|
#define ARRAY_POSITION 4
|
|
|
|
|
#define ARRAY_HELP 5
|
|
|
|
|
#define ARRAY_DEFAULT 6
|
|
|
|
|
|
|
|
|
|
void
|
2024-10-04 13:03:23 +02:00
|
|
|
CmdArray(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2024-10-10 21:21:19 +02:00
|
|
|
static const char * const cmdArrayOption[] = {
|
2017-04-25 14:41:48 +02:00
|
|
|
"count [[xlo] xhi [ylo] yhi] array subcells",
|
|
|
|
|
"width [value] set or return array x-spacing",
|
|
|
|
|
"height [value] set or return array y-spacing",
|
|
|
|
|
"pitch [x y] set or return array spacing",
|
|
|
|
|
"position [x y] set or return array origin",
|
|
|
|
|
"help print help information",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-10 21:21:19 +02:00
|
|
|
const char * const *msg;
|
2017-04-25 14:41:48 +02:00
|
|
|
int option, locargc, argstart;
|
|
|
|
|
bool doList = FALSE;
|
|
|
|
|
ArrayInfo a;
|
|
|
|
|
Rect toolRect;
|
|
|
|
|
LinkedArray *lahead = NULL, *la;
|
|
|
|
|
int xval, yval;
|
|
|
|
|
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
Tcl_Obj *tobj;
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-10-04 13:05:38 +02:00
|
|
|
extern int selGetArrayFunc(CellUse *selUse, CellUse *use, Transform *trans, LinkedArray **arg);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
locargc = cmd->tx_argc;
|
|
|
|
|
argstart = 1;
|
|
|
|
|
|
|
|
|
|
if (locargc <= 1)
|
|
|
|
|
goto badusage;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!strncmp(cmd->tx_argv[argstart], "-list", 5))
|
|
|
|
|
{
|
|
|
|
|
doList = TRUE;
|
|
|
|
|
locargc--;
|
|
|
|
|
argstart++;
|
|
|
|
|
}
|
|
|
|
|
if (locargc <= 1)
|
|
|
|
|
goto badusage; /* Prohibits "array -list" alone */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
option = Lookup(cmd->tx_argv[argstart], cmdArrayOption);
|
|
|
|
|
if (option < 0) {
|
|
|
|
|
if (locargc == 3 || locargc == 5)
|
|
|
|
|
option = ARRAY_DEFAULT;
|
|
|
|
|
else
|
|
|
|
|
goto badusage;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!ToolGetEditBox((Rect *)NULL)) return;
|
|
|
|
|
|
|
|
|
|
/* Get all information about cell uses in the current selection */
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
(void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
|
2017-04-25 14:41:48 +02:00
|
|
|
selGetArrayFunc, (ClientData) &lahead);
|
|
|
|
|
|
|
|
|
|
/* Note: All "unimplemented functions" below will require a routine
|
|
|
|
|
* similar to "SelectArray", but which only operates on cells, and
|
|
|
|
|
* only changes specific parameters; i.e., the arrayInfo structure
|
|
|
|
|
* is generated separately for each selected cell, the values filled
|
|
|
|
|
* in with the current values for that cell, and then the requested
|
|
|
|
|
* parameter changed.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
switch (option)
|
|
|
|
|
{
|
|
|
|
|
case ARRAY_COUNT:
|
|
|
|
|
if (locargc == 2)
|
|
|
|
|
{
|
|
|
|
|
for (la = lahead; la != NULL; la = la->ar_next)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
if (doList)
|
|
|
|
|
{
|
|
|
|
|
tobj = Tcl_NewListObj(0, NULL);
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_xlo));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_xhi));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_ylo));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_yhi));
|
|
|
|
|
Tcl_SetObjResult(magicinterp, tobj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
if (la->cellUse->cu_id != NULL)
|
|
|
|
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
|
|
|
|
else
|
|
|
|
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
|
|
|
|
TxPrintf("x index %d to %d, y index %d to %d\n",
|
|
|
|
|
la->arrayInfo.ar_xlo,
|
|
|
|
|
la->arrayInfo.ar_xhi,
|
|
|
|
|
la->arrayInfo.ar_ylo,
|
|
|
|
|
la->arrayInfo.ar_yhi);
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if ((locargc != 4) && (locargc != 6))
|
|
|
|
|
goto badusage;
|
|
|
|
|
|
|
|
|
|
if (!StrIsInt(cmd->tx_argv[argstart + 1])
|
2020-05-23 23:13:14 +02:00
|
|
|
|| !StrIsInt(cmd->tx_argv[argstart + 2]))
|
2017-04-25 14:41:48 +02:00
|
|
|
goto badusage;
|
|
|
|
|
|
|
|
|
|
if (locargc == 4)
|
|
|
|
|
{
|
|
|
|
|
a.ar_xlo = 0;
|
|
|
|
|
a.ar_ylo = 0;
|
|
|
|
|
a.ar_xhi = atoi(cmd->tx_argv[argstart + 1]) - 1;
|
|
|
|
|
a.ar_yhi = atoi(cmd->tx_argv[argstart + 2]) - 1;
|
|
|
|
|
if ( (a.ar_xhi < 0) || (a.ar_yhi < 0) ) goto badusage;
|
|
|
|
|
}
|
|
|
|
|
else if (locargc == 6)
|
|
|
|
|
{
|
2020-05-23 23:13:14 +02:00
|
|
|
if (!StrIsInt(cmd->tx_argv[argstart + 3]) ||
|
2017-04-25 14:41:48 +02:00
|
|
|
!StrIsInt(cmd->tx_argv[argstart + 4])) goto badusage;
|
|
|
|
|
a.ar_xlo = atoi(cmd->tx_argv[argstart + 1]);
|
|
|
|
|
a.ar_xhi = atoi(cmd->tx_argv[argstart + 2]);
|
|
|
|
|
a.ar_ylo = atoi(cmd->tx_argv[argstart + 3]);
|
|
|
|
|
a.ar_yhi = atoi(cmd->tx_argv[argstart + 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);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARRAY_WIDTH:
|
|
|
|
|
if (locargc == 2)
|
|
|
|
|
{
|
|
|
|
|
for (la = lahead; la != NULL; la = la->ar_next)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
if (doList)
|
|
|
|
|
{
|
|
|
|
|
tobj = Tcl_NewListObj(0, NULL);
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
|
|
|
|
Tcl_SetObjResult(magicinterp, tobj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
if (la->cellUse->cu_id != NULL)
|
|
|
|
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
|
|
|
|
else
|
|
|
|
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
|
|
|
|
TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((locargc != 3) || (!StrIsInt(cmd->tx_argv[argstart + 1])))
|
|
|
|
|
goto badusage;
|
|
|
|
|
|
|
|
|
|
xval = atoi(cmd->tx_argv[argstart + 1]);
|
|
|
|
|
yval = atoi(cmd->tx_argv[argstart + 2]);
|
|
|
|
|
|
|
|
|
|
TxPrintf("Unimplemented function.\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARRAY_HEIGHT:
|
|
|
|
|
if (locargc == 2)
|
|
|
|
|
{
|
|
|
|
|
for (la = lahead; la != NULL; la = la->ar_next)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
if (doList)
|
|
|
|
|
{
|
|
|
|
|
tobj = Tcl_NewListObj(0, NULL);
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
|
|
|
|
Tcl_SetObjResult(magicinterp, tobj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
if (la->cellUse->cu_id != NULL)
|
|
|
|
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
|
|
|
|
else
|
|
|
|
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
|
|
|
|
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((locargc != 3) || (!StrIsInt(cmd->tx_argv[argstart + 1])))
|
|
|
|
|
goto badusage;
|
|
|
|
|
|
|
|
|
|
xval = atoi(cmd->tx_argv[argstart + 1]);
|
|
|
|
|
yval = atoi(cmd->tx_argv[argstart + 2]);
|
|
|
|
|
|
|
|
|
|
TxPrintf("Unimplemented function.\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARRAY_PITCH:
|
|
|
|
|
if (locargc == 2)
|
|
|
|
|
{
|
|
|
|
|
for (la = lahead; la != NULL; la = la->ar_next)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
if (doList)
|
|
|
|
|
{
|
|
|
|
|
tobj = Tcl_NewListObj(0, NULL);
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
|
|
|
|
Tcl_SetObjResult(magicinterp, tobj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
if (la->cellUse->cu_id != NULL)
|
|
|
|
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
|
|
|
|
else
|
|
|
|
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
|
|
|
|
TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
|
|
|
|
|
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((locargc != 4) || (!StrIsInt(cmd->tx_argv[argstart + 1])) ||
|
|
|
|
|
(!StrIsInt(cmd->tx_argv[argstart + 2])))
|
|
|
|
|
goto badusage;
|
|
|
|
|
|
|
|
|
|
xval = atoi(cmd->tx_argv[argstart + 1]);
|
|
|
|
|
yval = atoi(cmd->tx_argv[argstart + 2]);
|
|
|
|
|
|
|
|
|
|
TxPrintf("Unimplemented function.\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARRAY_POSITION:
|
|
|
|
|
if (locargc == 2)
|
|
|
|
|
{
|
|
|
|
|
for (la = lahead; la != NULL; la = la->ar_next)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
if (doList)
|
|
|
|
|
{
|
|
|
|
|
tobj = Tcl_NewListObj(0, NULL);
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
|
|
|
|
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
|
|
|
Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
|
|
|
|
|
Tcl_SetObjResult(magicinterp, tobj);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#endif
|
|
|
|
|
if (la->cellUse->cu_id != NULL)
|
|
|
|
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
|
|
|
|
else
|
|
|
|
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
|
|
|
|
TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
|
|
|
|
|
TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((locargc != 4) || (!StrIsInt(cmd->tx_argv[argstart + 1])) ||
|
|
|
|
|
(!StrIsInt(cmd->tx_argv[argstart + 2])))
|
|
|
|
|
goto badusage;
|
|
|
|
|
|
|
|
|
|
xval = atoi(cmd->tx_argv[argstart + 1]);
|
|
|
|
|
yval = atoi(cmd->tx_argv[argstart + 2]);
|
|
|
|
|
|
|
|
|
|
TxPrintf("Unimplemented function.\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARRAY_DEFAULT:
|
|
|
|
|
if (!StrIsInt(cmd->tx_argv[argstart])
|
2020-05-23 23:13:14 +02:00
|
|
|
|| !StrIsInt(cmd->tx_argv[argstart + 1]))
|
2017-04-25 14:41:48 +02:00
|
|
|
goto badusage;
|
|
|
|
|
if (locargc == 3)
|
|
|
|
|
{
|
|
|
|
|
a.ar_xlo = 0;
|
|
|
|
|
a.ar_ylo = 0;
|
|
|
|
|
a.ar_xhi = atoi(cmd->tx_argv[argstart]) - 1;
|
|
|
|
|
a.ar_yhi = atoi(cmd->tx_argv[argstart + 1]) - 1;
|
|
|
|
|
if ( (a.ar_xhi < 0) || (a.ar_yhi < 0) ) goto badusage;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-05-23 23:13:14 +02:00
|
|
|
if (!StrIsInt(cmd->tx_argv[argstart + 2]) ||
|
2017-04-25 14:41:48 +02:00
|
|
|
!StrIsInt(cmd->tx_argv[argstart + 3])) goto badusage;
|
|
|
|
|
a.ar_xlo = atoi(cmd->tx_argv[argstart]);
|
|
|
|
|
a.ar_xhi = atoi(cmd->tx_argv[argstart + 1]);
|
|
|
|
|
a.ar_ylo = atoi(cmd->tx_argv[argstart + 2]);
|
|
|
|
|
a.ar_yhi = atoi(cmd->tx_argv[argstart + 3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ARRAY_HELP:
|
|
|
|
|
badusage:
|
|
|
|
|
for (msg = &(cmdArrayOption[0]); *msg != NULL; msg++)
|
|
|
|
|
{
|
|
|
|
|
TxPrintf(" %s\n", *msg);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freelist:
|
|
|
|
|
la = lahead;
|
|
|
|
|
while (la != NULL)
|
|
|
|
|
{
|
|
|
|
|
freeMagic((char *)la);
|
|
|
|
|
la = la->ar_next;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
* Procedure returning information on arrayed selection
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2024-10-04 13:03:23 +02:00
|
|
|
selGetArrayFunc(
|
|
|
|
|
CellUse *selUse,
|
|
|
|
|
CellUse *use,
|
|
|
|
|
Transform *trans,
|
|
|
|
|
LinkedArray **arg)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
/* Check "use" for array information and pass this to arrayInfo */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
LinkedArray *la;
|
|
|
|
|
int xlo, xhi, ylo, yhi, xsep, ysep, t;
|
|
|
|
|
|
|
|
|
|
la = (LinkedArray *)mallocMagic(sizeof(LinkedArray));
|
|
|
|
|
|
|
|
|
|
xlo = use->cu_xlo;
|
|
|
|
|
ylo = use->cu_ylo;
|
|
|
|
|
xhi = use->cu_xhi;
|
|
|
|
|
yhi = use->cu_yhi;
|
|
|
|
|
|
|
|
|
|
/* preserve x and y relative to root */
|
|
|
|
|
|
|
|
|
|
if (trans->t_a == 0)
|
|
|
|
|
{
|
|
|
|
|
t = xlo; xlo = ylo; ylo = t;
|
|
|
|
|
t = xhi; xhi = yhi; yhi = t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
la->arrayInfo.ar_xlo = xlo;
|
|
|
|
|
la->arrayInfo.ar_xhi = xhi;
|
|
|
|
|
la->arrayInfo.ar_ylo = ylo;
|
|
|
|
|
la->arrayInfo.ar_yhi = yhi;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/* Reverse the transformation in DBMakeArray */
|
|
|
|
|
|
|
|
|
|
ysep = (trans->t_d * use->cu_xsep - trans->t_a * use->cu_ysep);
|
|
|
|
|
ysep /= (trans->t_d * trans->t_b - trans->t_a * trans->t_e);
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (trans->t_a == 0)
|
|
|
|
|
xsep = (use->cu_ysep - trans->t_e * ysep) / trans->t_d;
|
|
|
|
|
else
|
|
|
|
|
xsep = (use->cu_xsep - trans->t_b * ysep) / trans->t_a;
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
la->arrayInfo.ar_xsep = xsep;
|
|
|
|
|
la->arrayInfo.ar_ysep = ysep;
|
|
|
|
|
|
|
|
|
|
la->cellUse = use;
|
|
|
|
|
la->ar_next = (*arg);
|
|
|
|
|
(*arg) = la;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* CmdBox --
|
|
|
|
|
*
|
|
|
|
|
* Box command.
|
|
|
|
|
*
|
|
|
|
|
* Usage:
|
|
|
|
|
* box width [num]
|
|
|
|
|
* box height [num]
|
|
|
|
|
* box size [width height]
|
|
|
|
|
* box position [llx lly] [-edit]
|
|
|
|
|
* box values [llx lly urx ury] [-edit]
|
2020-10-08 19:50:14 +02:00
|
|
|
* box remove
|
2020-10-07 21:37:31 +02:00
|
|
|
* box select
|
2017-04-25 14:41:48 +02:00
|
|
|
*
|
|
|
|
|
* box <direction> <distance> | cursor
|
|
|
|
|
*
|
|
|
|
|
* box move <direction> <distance> | cursor
|
|
|
|
|
* box grow <direction> <distance>
|
|
|
|
|
* box shrink <direction> <distance>
|
|
|
|
|
*
|
|
|
|
|
* box [llx lly urx ury] [-edit]
|
|
|
|
|
*
|
|
|
|
|
* Coordinates and sizes may be specified in any of the following
|
|
|
|
|
* units: none (internal), "i" (internal), "l" (lambda), or any
|
|
|
|
|
* metric units (e.g., "um"). Coordinates may be integer or
|
|
|
|
|
* floating-point (e.g., "20i" or "1.5mm"). There should be no
|
|
|
|
|
* space between the value and the unit specifier (i.e., "20l",
|
|
|
|
|
* not "20 l").
|
|
|
|
|
*
|
|
|
|
|
* Coordinates are usually reported relative to the root cell of
|
|
|
|
|
* the window, unless the "-edit" switch is given.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Box values are printed to the console.
|
|
|
|
|
* Tcl version returns values for the first five cases above when
|
|
|
|
|
* the optional value or values are not present.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* May modify the location of the box tool.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define BOX_WIDTH 0
|
|
|
|
|
#define BOX_HEIGHT 1
|
|
|
|
|
#define BOX_SIZE 2
|
|
|
|
|
#define BOX_POSITION 3
|
|
|
|
|
#define BOX_VALUES 4
|
2020-10-08 19:50:14 +02:00
|
|
|
#define BOX_REMOVE 5
|
|
|
|
|
#define BOX_SELECT 6
|
|
|
|
|
#define BOX_MOVE 7
|
|
|
|
|
#define BOX_GROW 8
|
|
|
|
|
#define BOX_SHRINK 9
|
|
|
|
|
#define BOX_CORNER 10
|
|
|
|
|
#define BOX_EXISTS 11
|
|
|
|
|
#define BOX_HELP 12
|
|
|
|
|
#define BOX_DEFAULT 13
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
void
|
2024-10-04 13:03:23 +02:00
|
|
|
CmdBox(
|
|
|
|
|
MagWindow *w,
|
|
|
|
|
TxCommand *cmd)
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
2024-10-10 21:21:19 +02:00
|
|
|
static const char * const cmdBoxOption[] = {
|
2017-04-25 14:41:48 +02:00
|
|
|
"width [value] set or return box width",
|
|
|
|
|
"height [value] set or return box height",
|
|
|
|
|
"size [width height] set or return box size",
|
|
|
|
|
"position [llx lly] [-edit] set or return box position",
|
|
|
|
|
"values [llx lly urx ury] [-edit] set or return box coordinates",
|
2020-10-08 19:50:14 +02:00
|
|
|
"remove remove cursor box from display",
|
2020-10-07 21:37:31 +02:00
|
|
|
"select set box to selection bounding box",
|
2017-04-25 14:41:48 +02:00
|
|
|
"move <direction> <distance> move box position",
|
|
|
|
|
"grow <direction> <distance> expand box size",
|
|
|
|
|
"shrink <direction> <distance> shrink box size",
|
|
|
|
|
"corner <direction> <distance> set box corner",
|
|
|
|
|
"exists is the cursor box present?",
|
|
|
|
|
"help print help information",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CellDef *rootBoxDef;
|
2022-01-27 22:57:23 +01:00
|
|
|
Rect rootBox, editbox, savebox, *boxptr;
|
2017-04-25 14:41:48 +02:00
|
|
|
Point ll;
|
|
|
|
|
int option, direction, distancex, distancey;
|
|
|
|
|
int width, height;
|
|
|
|
|
dlong area;
|
|
|
|
|
int argc;
|
|
|
|
|
int tcorner;
|
|
|
|
|
float iscale, oscale;
|
|
|
|
|
bool needBox = TRUE; /* require that box be defined */
|
|
|
|
|
bool refEdit = FALSE; /* referenced to edit cell coordinates */
|
|
|
|
|
bool cursorRef = FALSE; /* reference position is the cursor */
|
2024-10-10 21:21:19 +02:00
|
|
|
const char * const *msg;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
argc = cmd->tx_argc;
|
|
|
|
|
if (argc > 7) goto badusage;
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Check for the request to report in edit cell coordinates */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
if (!strncmp(cmd->tx_argv[argc - 1], "-edit", 5))
|
|
|
|
|
{
|
|
|
|
|
refEdit = TRUE;
|
|
|
|
|
argc--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Parse command for options */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
if (argc == 1)
|
|
|
|
|
option = BOX_DEFAULT;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
option = Lookup(cmd->tx_argv[1], cmdBoxOption);
|
|
|
|
|
|
|
|
|
|
/* This hack allows 'h' to be used as a synonym for "height" */
|
|
|
|
|
/* 'w' already works for width because no other options begin */
|
|
|
|
|
/* with "w". But the addition of option "help" presents an */
|
|
|
|
|
/* ambiguity. */
|
|
|
|
|
|
|
|
|
|
if (option == -1 && cmd->tx_argv[1][0] == 'h')
|
|
|
|
|
option = BOX_HEIGHT;
|
|
|
|
|
else if (option < 0)
|
|
|
|
|
option = BOX_DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
windCheckOnlyWindow(&w, DBWclientID);
|
|
|
|
|
|
2020-10-08 19:50:14 +02:00
|
|
|
if (option == BOX_REMOVE)
|
|
|
|
|
{
|
|
|
|
|
DBWSetBox((CellDef *)NULL, &GeoNullRect);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Check for the command options which do not require a box */
|
|
|
|
|
/* to be present. */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
switch (option)
|
|
|
|
|
{
|
|
|
|
|
case BOX_MOVE:
|
|
|
|
|
case BOX_GROW:
|
|
|
|
|
case BOX_SHRINK:
|
|
|
|
|
case BOX_CORNER:
|
|
|
|
|
if (!strncmp(cmd->tx_argv[argc - 1], "cursor", 6))
|
|
|
|
|
{
|
|
|
|
|
needBox = FALSE;
|
|
|
|
|
cursorRef = TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BOX_DEFAULT:
|
|
|
|
|
if (argc == 5) needBox = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
case BOX_VALUES:
|
|
|
|
|
if (argc == 6) needBox = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
case BOX_EXISTS:
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0",
|
|
|
|
|
NULL);
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
if (needBox)
|
|
|
|
|
{
|
|
|
|
|
if (refEdit)
|
|
|
|
|
if (!ToolGetEditBox(&editbox))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
Rect r;
|
|
|
|
|
|
|
|
|
|
if (argc >= 5)
|
|
|
|
|
{
|
|
|
|
|
r.r_xbot = cmdParseCoord(w, cmd->tx_argv[argc - 4], FALSE, TRUE);
|
|
|
|
|
r.r_ybot = cmdParseCoord(w, cmd->tx_argv[argc - 3], FALSE, FALSE);
|
|
|
|
|
r.r_xtop = cmdParseCoord(w, cmd->tx_argv[argc - 2], FALSE, TRUE);
|
|
|
|
|
r.r_ytop = cmdParseCoord(w, cmd->tx_argv[argc - 1], FALSE, FALSE);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If we got here, then we requested a box or corner move
|
|
|
|
|
* to the cursor position, but there was no box present.
|
|
|
|
|
* To keep users from becoming bewildered at this point,
|
|
|
|
|
* we generate a zero-size box at the origin and work from
|
|
|
|
|
* there.
|
|
|
|
|
*/
|
|
|
|
|
r.r_xbot = r.r_ybot = r.r_xtop = r.r_ytop = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rootBoxDef = ((CellUse *) w->w_surfaceID)->cu_def;
|
|
|
|
|
if (refEdit)
|
|
|
|
|
{
|
|
|
|
|
GeoTransRect(&EditToRootTransform, &r, &rootBox);
|
|
|
|
|
refEdit = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else rootBox = r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Edit cell or Root cell? */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
boxptr = (refEdit) ? &editbox : &rootBox;
|
2022-01-27 22:57:23 +01:00
|
|
|
savebox = *boxptr;
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Parse arguments according to class */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
switch (option)
|
|
|
|
|
{
|
|
|
|
|
case BOX_MOVE:
|
|
|
|
|
case BOX_GROW:
|
|
|
|
|
case BOX_SHRINK:
|
|
|
|
|
case BOX_CORNER:
|
|
|
|
|
if (argc != 4) goto badusage;
|
|
|
|
|
direction = GeoNameToPos(cmd->tx_argv[2], FALSE, TRUE);
|
|
|
|
|
if (direction < 0) return;
|
|
|
|
|
else if (cursorRef)
|
|
|
|
|
{
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GEO_SOUTHWEST:
|
|
|
|
|
tcorner = TOOL_BL;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHEAST:
|
|
|
|
|
tcorner = TOOL_TR;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHWEST:
|
|
|
|
|
tcorner = TOOL_TL;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHEAST:
|
|
|
|
|
tcorner = TOOL_BR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
switch(option)
|
|
|
|
|
{
|
|
|
|
|
case BOX_MOVE:
|
|
|
|
|
ToolMoveBox(tcorner, &cmd->tx_p, TRUE, rootBoxDef);
|
|
|
|
|
break;
|
|
|
|
|
case BOX_CORNER:
|
|
|
|
|
ToolMoveCorner(tcorner, &cmd->tx_p, TRUE, rootBoxDef);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-07-08 23:34:00 +02:00
|
|
|
|
|
|
|
|
/* Recast command as "box values" for logging purposes */
|
|
|
|
|
ToolGetBox(&rootBoxDef, &rootBox);
|
|
|
|
|
sprintf(cmd->tx_argstring, "box values %di %di %di %di",
|
|
|
|
|
rootBox.r_xbot, rootBox.r_ybot,
|
|
|
|
|
rootBox.r_xtop, rootBox.r_ytop);
|
|
|
|
|
TxRebuildCommand(cmd);
|
2017-04-25 14:41:48 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (DBWSnapToGrid != DBW_SNAP_USER)
|
|
|
|
|
{
|
|
|
|
|
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
|
|
|
|
distancey = distancex;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GEO_EAST: case GEO_WEST:
|
|
|
|
|
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, TRUE);
|
|
|
|
|
distancey = distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTH: case GEO_SOUTH:
|
|
|
|
|
distancey = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
|
|
|
|
distancex = distancey;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, TRUE);
|
|
|
|
|
distancey = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((distancex == 0) && (distancey == 0)) return;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
switch (option)
|
|
|
|
|
{
|
|
|
|
|
case BOX_WIDTH:
|
|
|
|
|
if (argc == 2)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
char *boxvalues = (char *)Tcl_Alloc(50);
|
|
|
|
|
sprintf(boxvalues, "%d",
|
|
|
|
|
boxptr->r_xtop - boxptr->r_xbot);
|
|
|
|
|
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("%s box width is %d\n",
|
|
|
|
|
(refEdit) ? "Edit" : "Root",
|
|
|
|
|
boxptr->r_xtop - boxptr->r_xbot);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (argc != 3) goto badusage;
|
|
|
|
|
width = cmdParseCoord(w, cmd->tx_argv[2], TRUE, TRUE);
|
|
|
|
|
boxptr->r_xtop = boxptr->r_xbot + width;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_HEIGHT:
|
|
|
|
|
if (argc == 2)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
char *boxvalues = (char *)Tcl_Alloc(50);
|
|
|
|
|
sprintf(boxvalues, "%d",
|
|
|
|
|
boxptr->r_ytop - boxptr->r_ybot);
|
|
|
|
|
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("%s box height is %d\n",
|
|
|
|
|
(refEdit) ? "Edit" : "Root",
|
|
|
|
|
boxptr->r_ytop - boxptr->r_ybot);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (argc != 3) goto badusage;
|
|
|
|
|
height = cmdParseCoord(w, cmd->tx_argv[2], TRUE, FALSE);
|
|
|
|
|
boxptr->r_ytop = boxptr->r_ybot + height;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_SIZE:
|
|
|
|
|
if (argc == 2)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
char *boxvalues = (char *)Tcl_Alloc(50);
|
|
|
|
|
sprintf(boxvalues, "%d %d",
|
|
|
|
|
boxptr->r_xtop - boxptr->r_xbot,
|
|
|
|
|
boxptr->r_ytop - boxptr->r_ybot);
|
|
|
|
|
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("%s box size is %d x %d\n",
|
|
|
|
|
(refEdit) ? "Edit" : "Root",
|
|
|
|
|
boxptr->r_xtop - boxptr->r_xbot,
|
|
|
|
|
boxptr->r_ytop - boxptr->r_ybot);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (argc != 4) goto badusage;
|
|
|
|
|
width = cmdParseCoord(w, cmd->tx_argv[2], TRUE, TRUE);
|
|
|
|
|
height = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
|
|
|
|
boxptr->r_xtop = boxptr->r_xbot + width;
|
|
|
|
|
boxptr->r_ytop = boxptr->r_ybot + height;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_POSITION:
|
|
|
|
|
if (argc == 2)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
char *boxvalues = (char *)Tcl_Alloc(50);
|
|
|
|
|
sprintf(boxvalues, "%d %d",
|
|
|
|
|
boxptr->r_xbot, boxptr->r_ybot);
|
|
|
|
|
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("%s box lower-left corner at (%d, %d)\n",
|
|
|
|
|
(refEdit) ? "Edit" : "Root",
|
|
|
|
|
boxptr->r_xbot, boxptr->r_ybot);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (argc != 4) goto badusage;
|
|
|
|
|
width = boxptr->r_xtop - boxptr->r_xbot;
|
|
|
|
|
height = boxptr->r_ytop - boxptr->r_ybot;
|
|
|
|
|
ll.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
|
|
|
|
|
ll.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
|
|
|
|
|
boxptr->r_xbot = ll.p_x;
|
|
|
|
|
boxptr->r_ybot = ll.p_y;
|
|
|
|
|
boxptr->r_xtop = boxptr->r_xbot + width;
|
|
|
|
|
boxptr->r_ytop = boxptr->r_ybot + height;
|
|
|
|
|
break;
|
|
|
|
|
|
2020-10-07 21:37:31 +02:00
|
|
|
case BOX_SELECT:
|
|
|
|
|
if (argc == 2)
|
|
|
|
|
{
|
|
|
|
|
Rect selarea;
|
|
|
|
|
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
|
|
|
|
boxptr->r_xbot = selarea.r_xbot;
|
|
|
|
|
boxptr->r_ybot = selarea.r_ybot;
|
|
|
|
|
boxptr->r_xtop = selarea.r_xtop;
|
|
|
|
|
boxptr->r_ytop = selarea.r_ytop;
|
|
|
|
|
}
|
|
|
|
|
else goto badusage;
|
|
|
|
|
break;
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
case BOX_VALUES:
|
|
|
|
|
if (argc == 2)
|
|
|
|
|
{
|
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
|
char *boxvalues = (char *)Tcl_Alloc(50);
|
|
|
|
|
sprintf(boxvalues, "%d %d %d %d",
|
|
|
|
|
boxptr->r_xbot, boxptr->r_ybot,
|
|
|
|
|
boxptr->r_xtop, boxptr->r_ytop);
|
|
|
|
|
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
|
|
|
#else
|
|
|
|
|
TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
|
|
|
|
|
(refEdit) ? "Edit" : "Root",
|
|
|
|
|
boxptr->r_xbot, boxptr->r_ybot,
|
|
|
|
|
boxptr->r_xtop, boxptr->r_ytop);
|
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (argc != 6) goto badusage;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_MOVE:
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GEO_NORTH:
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTH:
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_EAST:
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_WEST:
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHEAST:
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHWEST:
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHEAST:
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHWEST:
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_GROW:
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GEO_NORTH:
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTH:
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_EAST:
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_WEST:
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHEAST:
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHWEST:
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHEAST:
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHWEST:
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_CENTER:
|
|
|
|
|
boxptr->r_ytop += distancey;
|
|
|
|
|
boxptr->r_ybot -= distancey;
|
|
|
|
|
boxptr->r_xtop += distancex;
|
|
|
|
|
boxptr->r_xbot -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_CORNER:
|
|
|
|
|
ll.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
|
|
|
|
|
ll.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GEO_SOUTHWEST:
|
|
|
|
|
tcorner = TOOL_BL;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHEAST:
|
|
|
|
|
tcorner = TOOL_TR;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHWEST:
|
|
|
|
|
tcorner = TOOL_TL;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHEAST:
|
|
|
|
|
tcorner = TOOL_BR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ToolMoveCorner(tcorner, &ll, FALSE, rootBoxDef);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case BOX_SHRINK:
|
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GEO_NORTH:
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTH:
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_EAST:
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_WEST:
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHEAST:
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_NORTHWEST:
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHEAST:
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_SOUTHWEST:
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
break;
|
|
|
|
|
case GEO_CENTER:
|
|
|
|
|
boxptr->r_ytop -= distancey;
|
|
|
|
|
boxptr->r_xtop -= distancex;
|
|
|
|
|
boxptr->r_ybot += distancey;
|
|
|
|
|
boxptr->r_xbot += distancex;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_DEFAULT:
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Print box values to the screen ("box" w/no options only) */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
width = boxptr->r_xtop - boxptr->r_xbot;
|
|
|
|
|
height = boxptr->r_ytop - boxptr->r_ybot;
|
|
|
|
|
area = (dlong)width * (dlong)height;
|
|
|
|
|
|
|
|
|
|
TxPrintf("%s cell box:\n", (refEdit) ? "Edit" : "Root");
|
|
|
|
|
|
|
|
|
|
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)");
|
|
|
|
|
|
2022-01-21 16:44:13 +01:00
|
|
|
TxPrintf("\n\nmicrons: %6.3f x %-6.3f (% 6.3f, % -6.3f), "
|
|
|
|
|
"(% 6.3f, % -6.3f)",
|
2017-04-25 14:41:48 +02:00
|
|
|
(float)width *oscale, (float)height * oscale,
|
|
|
|
|
(float)boxptr->r_xbot * oscale, (float)boxptr->r_ybot * oscale,
|
|
|
|
|
(float)boxptr->r_xtop * oscale, (float)boxptr->r_ytop * oscale);
|
|
|
|
|
if (area > 0)
|
2022-01-21 16:44:13 +01:00
|
|
|
TxPrintf(" %-10.3f", (float)area * oscale * oscale);
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
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)boxptr->r_xbot * iscale,
|
|
|
|
|
(float)boxptr->r_ybot * iscale,
|
|
|
|
|
(float)boxptr->r_xtop * iscale,
|
|
|
|
|
(float)boxptr->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,
|
|
|
|
|
boxptr->r_xbot, boxptr->r_ybot,
|
|
|
|
|
boxptr->r_xtop, boxptr->r_ytop);
|
|
|
|
|
if (area > 0)
|
2025-01-06 17:27:10 +01:00
|
|
|
TxPrintf(" %-10"DLONG_PREFIX"d", area);
|
2017-04-25 14:41:48 +02:00
|
|
|
TxPrintf("\n");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BOX_HELP:
|
|
|
|
|
badusage:
|
|
|
|
|
for (msg = &(cmdBoxOption[0]); *msg != NULL; msg++)
|
|
|
|
|
{
|
|
|
|
|
TxPrintf(" %s\n", *msg);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Return to root coordinates, if working in edit coords */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
if (refEdit)
|
|
|
|
|
GeoTransRect(&EditToRootTransform, &editbox, &rootBox);
|
|
|
|
|
|
2022-01-27 22:57:23 +01:00
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Check for numerical overflow in box values */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
if (boxptr->r_ll.p_x < (MINFINITY + 2) || boxptr->r_ll.p_x > (INFINITY - 2) ||
|
|
|
|
|
boxptr->r_ll.p_y < (MINFINITY + 2) || boxptr->r_ll.p_y > (INFINITY - 2))
|
|
|
|
|
{
|
|
|
|
|
*boxptr = savebox;
|
|
|
|
|
TxError("Box out of bounds.\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
/* Change the position of the box in the layout window */
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
if (argc != 1) /* Don't bother to move if only reporting */
|
|
|
|
|
{
|
|
|
|
|
ToolMoveBox(TOOL_BL, &rootBox.r_ll, FALSE, rootBoxDef);
|
|
|
|
|
ToolMoveCorner(TOOL_TR, &rootBox.r_ur, FALSE, rootBoxDef);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------*/
|