/*
 * main.c --
 *
 * The topmost module of the Magic VLSI tool.  This module
 * initializes the other modules and then calls the 'textio'
 * module to read and execute commands.
 *
 *     ********************************************************************* 
 *     * 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/main/main.c,v 1.8 2006/07/08 22:32:46 fang Exp $";
#endif  /* not lint */

#include <stdio.h>
#include <stdlib.h>
#ifndef SYSV
#include <strings.h>
#else
#include <string.h>
#endif


#include <sys/types.h>
#include <sys/times.h>
#include <sys/time.h>
#include "misc/magic.h"
#include "misc/magsgtty.h"
#include "main/main.h"
#include "utils/hash.h"
#include "textio/textio.h"
#include "utils/geometry.h"
#include "textio/txcommands.h"
#include "graphics/graphics.h"
#include "tiles/tile.h"
#include "tech/tech.h"
#include "database/database.h"
#include "drc/drc.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "commands/commands.h"
#include "signals/signals.h"
#include "utils/utils.h"
#include "utils/runstats.h"
#include "cif/cif.h"
#include "router/router.h"
#include "extract/extract.h"
#include "undo/undo.h"
#include "netmenu/netmenu.h"
#include "plow/plow.h"
#include "misc/paths.h"
#include "wiring/wiring.h"
#include "plot/plot.h"
#include "sim/sim.h"
#include "utils/doubleint.h"
#include "utils/list.h"
#include "mzrouter/mzrouter.h"
#include "lisp/lisp.h"
#include "utils/malloc.h"
#include "utils/finddisp.h"
#include "cmwind/cmwind.h"
#include "select/select.h"
#include "irouter/irouter.h"
#include "utils/saveimage.h"

#ifdef	LLNL
#include "art.h"
#endif	/* LLNL */


/*
 * Global data structures
 *
 */

global char	*Path = NULL;		/* Search path */
global char	*CellLibPath = NULL;	/* Used to find cells. */
global char	*SysLibPath = NULL;	/* Used to find color maps, styles, */
					/* technologies, etc. */

/*
 * Flag that tells if the '-D' (debugging) option is set.
 */

global bool mainDebug = FALSE;


/*
 * See the file main.h for a description of the information kept
 * pertaining to the edit cell.
 */

global CellUse	*EditCellUse = NULL;
global CellDef	*EditRootDef = NULL;
global Transform EditToRootTransform;
global Transform RootToEditTransform;


/*
 * data structures local to main.c
 *
 */

/* the following are used in saving our load image for fast startup */
static bool MainDoFreeze = FALSE;	/* TRUE if we should save our image */
static bool MainWasThawed = FALSE;	/* TRUE if this a restarted image */
static char *MainOrigFile;		/* File from which we were exec'd */
static char *MainSaveFile;		/* File to which image will be saved */
static char MainSaveDate[40];		/* When was image saved */

/* the filename specified on the command line */
static char *MainFileName = NULL;	

/* the first filename specified on the command line */
typedef struct filename {
    char *fn;
    struct filename *fn_prev;
} FileName;
FileName *CurrentName;

/* the filename for the graphics and mouse ports */
global char *MainGraphicsFile = NULL;
global char *MainMouseFile = NULL;

/* information about the color display. */
global char *MainDisplayType = NULL;
global char *MainMonType = NULL;


/* Copyright notice for the binary file. */
global char *MainCopyright = "\n--- MAGIC: Copyright (C) 1985, 1990 Regents of the University of California.  ---\n";


/* If TRUE, then Magic is as silent as possible.  This is only set to
 * TRUE by batch programs such as Mpack and Mocha Chip.
 */
global bool MainSilent = FALSE;

/* Forward declarations */
char *mainArg();
static void mainInitProfile(register int argc, register char **argv);

/*
 * ----------------------------------------------------------------------------
 * MainExit:
 *
 *	Magic's own exit procedure
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	We exit.
 * ----------------------------------------------------------------------------
 */

global
void
MainExit(int errNum)
{
#ifdef	MOCHA
    MochaExit(errNum);
#endif
    if (GrClosePtr != NULL) /* We are not guarenteed that everthing will
			     * be initialized already!
			     */
	GrClose();
#ifdef FILE_LOCKS
    flock_exit();
#endif
    TxResetTerminal();
    (void) fflush(stderr);
    (void) fflush(stdout);
    exit(errNum);
}


/*
 * ----------------------------------------------------------------------------
 * mainCheckCad:
 *
 *	See if ~cad exists.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 * ----------------------------------------------------------------------------
 */

void
mainCheckCad()
{
    char res[100];
    char *cad = "~cad";
    char *src, *dst;

    src = cad;
    dst = res;
    if (PaConvertTilde(&src, &dst, 95) == -1) {
	/* If ~cad does not exist (and/or has not been aliased to something
	 * that does exist via the CADHOME environment variable), then Magic 
	 * won't be able to find any of its system startup files.
	 * So complain and exit.
	 */
	TxError("Could not find ~cad - Magic unable to find its system startup files.\n");
	MainExit(1);
    }
}

/*
 * ----------------------------------------------------------------------------
 *
 * mainDoArgs:
 *
 *	Process command line arguments
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Global variables are modified
 *
 * Notes:
 *	In order to work properly with the -F flag, we need to
 *	use StrDup() to make copies of any arguments we want
 *	to be visible when we restart a frozen file.
 *
 * ----------------------------------------------------------------------------
 */

void
mainDoArgs(argc, argv)
int argc;
char **argv;
{
    bool haveDashI = FALSE;
    char *cp;

    argc--;
    while (argc-- > 0)
    {
	argv++;
	if (**argv == '-')
	{
	    switch (argv[0][1])
	    {
		case 'g':
		    if ((cp = mainArg(&argc, &argv, "tty name")) == NULL)
			MainExit(1);
		    MainGraphicsFile = StrDup((char **) NULL, cp);
		    if (!haveDashI)
			MainMouseFile = MainGraphicsFile;
		    break;

		case 'i':
		    haveDashI = TRUE;
		    if ((cp = mainArg(&argc, &argv, "tty name")) == NULL)
			MainExit(1);
		    MainMouseFile = StrDup((char **) NULL, cp);
		    break;

		case 'd':
		    if ((cp = mainArg(&argc, &argv, "display type")) ==NULL)
			MainExit(1);
		    MainDisplayType = StrDup((char **) NULL, cp);
		    break;

		case 'm':
		    if ((cp = mainArg(&argc, &argv, "monitor type")) ==NULL)
			MainExit(1);
		    MainMonType = StrDup((char **) NULL, cp);
		    break;

		/*
		 * Indicate that we should create a "freeze"
		 * file after doing all initialization.
		 */
		case 'F':
		    if ((cp = mainArg(&argc, &argv, "executable")) == NULL)
			goto badfopt;
		    MainOrigFile = StrDup((char **) NULL, cp);
		    argc--, argv++;
		    if (argc == 0 || argv[0][0] == '-')
			goto badfopt;
		    MainSaveFile = StrDup((char **) NULL, argv[0]);
		    MainDoFreeze = TRUE;
		    break;

		/*
		 * Change the technology.
		 */
		case 'T':
		    if ((cp = mainArg(&argc, &argv, "technology")) == NULL)
			MainExit(1);
		    TechDefault = StrDup((char **) NULL, cp);
		    break;

		/*
		 * Re-enable profiling until specifically disabled.
		 * This is now handled in mainInitProfile(), so we
		 * ignore it here.
		 */
		case 'P':
		    break;

		/* 
		 * We are being debugged.
		 */
		case 'D':
		    mainDebug = TRUE;
		    break;

		default:
		    TxError("Unknown option: '%s'\n", *argv);
		    TxError("Usage:  magic [-g gPort] [-d devType] [-m monType] [-i tabletPort] [-D] [-F objFile saveFile] [-T technology] [file]\n");
		    MainExit(1);
		    
	    }
	}
	else
	{
	    if (MainFileName == NULL) {
		MainFileName = StrDup((char **) NULL, *argv);
		CurrentName = (FileName *) mallocMagic(sizeof(FileName));
		CurrentName->fn = MainFileName;
		CurrentName->fn_prev = (FileName *) NULL;
	    }
	    else
	    {
		FileName *temporary;

		temporary = (FileName *) mallocMagic(sizeof(FileName));
		temporary->fn = StrDup((char **) NULL, *argv);
		temporary->fn_prev = CurrentName;
		CurrentName = temporary;
	    }

	    /* Remove suffix if the file name already has it */
	    {
		char *c,*d;

		for(c = CurrentName->fn; (*c) != '\0'; c++);
		for(d = DBSuffix; (*d) != '\0'; d++);
		while( (*c) == (*d) ) {
		    if (c == MainFileName) break;
		    if (d == DBSuffix) {
			(*c) = '\0';
			break;
		    }
		    c--;
		    d--;
		}
	    }
	}
    }

    return;

badfopt:
    TxError("-F requires load and save file names, e.g.,");
    TxError(" \"-F magic magicsave\"\n");
    MainExit(1);
}

/*
 * ----------------------------------------------------------------------------
 *
 * mainArg --
 *
 * Pull off an argument from the (argc, argv) pair and also check
 * to make sure it's not another flag (i.e, it doesn't begin with
 * a '-').
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	See the comments in ArgStr() in the utils module -- they
 *	apply here.
 *
 * ----------------------------------------------------------------------------
 */

char *
mainArg(pargc, pargv, mesg)
    int *pargc;
    char ***pargv;
    char *mesg;
{
    char option, *cp;

    option = (*pargv)[0][1];
    cp = ArgStr(pargc, pargv, mesg);
    if (cp == NULL)
	return (char *) NULL;

    if (*cp == '-')
    {
	TxError("Bad name after '-%c' option: '%s'\n", option, cp);
	return (char *) NULL;
    }

    return cp;
}

/* Variables used in freezing and thawing Magic. */
static char *savedDisplayType, *savedMonType, *savedTechName;

/*
 * ----------------------------------------------------------------------------
 * mainInitBeforeArgs:
 *
 *	Initializes things before argument processing.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	All sorts of initialization.  Most initialization, however, is done
 *	in 'mainInitAfterArgs'.
 * ----------------------------------------------------------------------------
 */

void
mainInitBeforeArgs(argc, argv)
    int argc;
    char *argv[];
{
    if (Path == NULL)
	Path = StrDup((char **) NULL, ".");

    mainInitProfile(argc, argv);

    /* initialize text display */
    TxInit();
    TxSetTerminal();

    /* Initialize double-precision package. */
    DoubleInit();

    /* Initialize Lisp module. (rajit@cs.caltch.edu) */
    LispInit();

    /* Identify version first thing */
    TxPrintf("\nMagic %s - Compiled on %s.", MagicVersion, MagicCompileTime);
    if (MainWasThawed)
        TxPrintf("Image saved %s", MainSaveDate);
    TxPrintf("\n");

    /* Make sure ~cad, (or its alias) exists */
    mainCheckCad();


    if (MainWasThawed)
    {
	savedDisplayType = MainDisplayType;
	savedMonType = MainMonType;
	savedTechName = TechDefault;
    }

    /*
     * Get preliminary info on the graphics display.
     * This may be overriden later.
     */
    GrGuessDisplayType(&MainGraphicsFile, &MainMouseFile, 
	&MainDisplayType, &MainMonType);
    FindDisplay((char *)NULL, "displays", CAD_LIB_PATH, &MainGraphicsFile,
	&MainMouseFile, &MainDisplayType, &MainMonType);
}


/*
 * ----------------------------------------------------------------------------
 * mainInitAfterArgs:
 *
 *	Initializes things after argument processing.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	All sorts of initialization.
 * ----------------------------------------------------------------------------
 */

void
mainInitAfterArgs(void)
{
    char *home;
    char startupFileName[100];
    char tmppath[150];
    FILE *f;
    void (*nullProc)(void) = 0;

#ifdef FILE_LOCKS
    flock_init();
#endif

    /* If no technology has been specified yet, try to read one from
     * the initial cell, or else assign a default.
     */

    if ((TechDefault == NULL) && (MainFileName != NULL))
	(void) StrDup(&TechDefault, DBGetTech(MainFileName));
    if (TechDefault == NULL)
	TechDefault = "scmos";

    /* Pass technology name to Lisp interpreter (rajit@cs.caltech.edu) */
    LispSetTech (TechDefault);

    (void) sprintf(tmppath, MAGIC_LIB_PATH, TechDefault);
    StrDup(&CellLibPath, tmppath);
    StrDup(&SysLibPath, MAGIC_SYS_PATH);

    /* TxPrintf("Using technology \"%s\".\n", TechDefault); */
    
    if (MainGraphicsFile == NULL) MainGraphicsFile = "/dev/null";
    if (MainMouseFile == NULL) MainMouseFile = MainGraphicsFile;

    /* catch signals, must come after mainDoArgs & before SigWatchFile */
    SigInit();

    /* set up graphics */
    if ( !GrSetDisplay(MainDisplayType, MainGraphicsFile, MainMouseFile) )
    {
	MainExit(1);
    }

    if (!MainWasThawed)
    {
	SectionID sec_tech, sec_planes, sec_types, sec_styles;
	SectionID sec_connect, sec_contact, sec_compose;
	SectionID sec_cifinput, sec_cifoutput;
	SectionID sec_drc, sec_extract, sec_wiring, sec_router;
	SectionID sec_plow, sec_plot, sec_mzrouter;
#ifdef	LLNL
#ifdef ART
	SectionID sec_art;
#endif /* ART */
#endif	/* LLNL */

	/* initialize technology */
	TechInit();
	TechAddClient("tech", DBTechInit, DBTechSetTech, nullProc,
			(SectionID) 0, &sec_tech, FALSE);
	TechAddClient("version", nullProc, DBTechSetVersion, nullProc,
			(SectionID) 0, (int *)0, TRUE);
	TechAddClient("planes",	DBTechInitPlane, DBTechAddPlane, nullProc,
			(SectionID) 0, &sec_planes, FALSE);
	TechAddClient("types", DBTechInitType, DBTechAddType, DBTechFinalType,
			sec_planes, &sec_types, FALSE);

	TechAddClient("styles", DBWTechInit, DBWTechAddStyle, nullProc,
			sec_types, &sec_styles, FALSE);

	TechAddClient("contact", DBTechInitContact,
			DBTechAddContact, DBTechFinalContact,
			sec_types|sec_planes, &sec_contact, FALSE);

	TechAddClient("compose", DBTechInitCompose,
			DBTechAddCompose, DBTechFinalCompose,
			sec_types|sec_planes|sec_contact, &sec_compose, FALSE);

	TechAddClient("connect", DBTechInitConnect,
			DBTechAddConnect, DBTechFinalConnect,
			sec_types|sec_planes|sec_contact, &sec_connect, FALSE);

#ifdef NO_CIF
	TechAddClient("cifoutput", nullProc,nullProc,nullProc,
			(SectionID) 0, &sec_cifoutput, FALSE);
	
	TechAddClient("cifinput", nullProc,nullProc,nullProc,
		     (SectionID) 0, &sec_cifinput, FALSE);
#else
	TechAddClient("cifoutput", CIFTechInit, CIFTechLine, CIFTechFinal,
			(SectionID) 0, &sec_cifoutput, FALSE);
	
	TechAddClient("cifinput", CIFReadTechInit, CIFReadTechLine,
		    CIFReadTechFinal, (SectionID) 0, &sec_cifinput, FALSE);
#endif
#ifdef NO_ROUTE
	TechAddClient("mzrouter", nullProc,nullProc,nullProc,
			sec_types|sec_planes, &sec_mzrouter, FALSE);
#else
	TechAddClient("mzrouter", MZTechInit, MZTechLine, MZTechFinal,
			sec_types|sec_planes, &sec_mzrouter, FALSE);
#endif
	TechAddClient("drc", DRCTechInit, DRCTechAddRule, DRCTechFinal,
			sec_types|sec_planes, &sec_drc, FALSE);
#ifdef NO_PLOW
	TechAddClient("drc", nullProc,nullProc,nullProc,
			(SectionID) 0, (SectionID *) 0, FALSE);
#else
	TechAddClient("drc", PlowDRCInit, PlowDRCLine, PlowDRCFinal,
			(SectionID) 0, (SectionID *) 0, FALSE);
#endif
#ifdef NO_ROUTE
	TechAddClient("drc", nullProc,nullProc,nullProc,
			sec_mzrouter, (SectionID *) 0, FALSE);
#else
	TechAddClient("drc", MZDRCInit, MZDRCLine, nullProc,
			sec_mzrouter, (SectionID *) 0, FALSE);
#endif
#ifdef NO_EXT
	TechAddClient("extract", nullProc, nullProc,nullProc,
			sec_types|sec_connect, &sec_extract, FALSE);
#else
	TechAddClient("extract", nullProc, ExtTechLine, ExtTechFinal,
			sec_types|sec_connect, &sec_extract, FALSE);
#endif
	
	TechAddClient("wiring", WireTechInit, WireTechLine, WireTechFinal,
			sec_types, &sec_wiring, FALSE);

#ifdef NO_ROUTE
	TechAddClient("router", nullProc,nullProc,nullProc,
			sec_types, &sec_router, FALSE);
#else
	TechAddClient("router", RtrTechInit, RtrTechLine, RtrTechFinal,
			sec_types, &sec_router, FALSE);
#endif
#ifdef NO_PLOW
	TechAddClient("plowing", nullProc,nullProc,nullProc,
			sec_types|sec_connect|sec_contact, &sec_plow, FALSE);
#else
	TechAddClient("plowing", PlowTechInit, PlowTechLine, PlowTechFinal,
			sec_types|sec_connect|sec_contact, &sec_plow, FALSE);
#endif	
#ifdef NO_PLOT
	TechAddClient("plot", nullProc,nullProc,nullProc,
			sec_types, &sec_plot, FALSE);
#else
	TechAddClient("plot", PlotTechInit, PlotTechLine, PlotTechFinal,
			sec_types, &sec_plot, FALSE);
#endif

#ifdef	LLNL
#ifdef ART
	TechAddClient("art", ArtTechInit, ArtTechLine, ArtTechFinal,
			sec_types|sec_planes, &sec_art, FALSE);
#endif /* ART */
#endif	/* LLNL */
    }

    if (!MainWasThawed || strcmp(TechDefault, savedTechName) != 0)
    {
	if (!TechLoad(TechDefault))
	{
	    TxError("Cannot load technology \"%s\"\n", TechDefault);
	    MainExit(0);
	}
    }
    if (DBTechName != 0) {
	TxPrintf("Using technology \"%s\"", DBTechName);
	if (DBTechVersion != 0) TxPrintf(", version %s.", DBTechVersion);
	TxPrintf("\n");
    }
    if (DBTechDescription != 0) TxPrintf("%s\n", DBTechDescription);

    if (MainWasThawed && strcmp(savedDisplayType, MainDisplayType) == 0)
    {
	GrResetStyles();
    }
    else
    {
	if (GrLoadStyles(DBWStyleType, ".", SysLibPath) != 0)
		MainExit(1);
    }

    if (MainWasThawed && (strcmp(savedMonType, MainMonType) == 0)
	    && (strcmp(savedTechName, TechDefault) == 0)
	    && (strcmp(savedDisplayType, MainDisplayType) == 0))
    {
	GrResetCMap();
    }
    else
    {
	if (!GrReadCMap(DBWStyleType, (char *) NULL, MainMonType,
		".", SysLibPath))
	{
	    MainExit(1);
	}
    }
    if (!GrLoadCursors(".", SysLibPath)) MainExit(1);
    GrSetCursor(0);

    if (!MainWasThawed)
    {
	/* initialize the undo package */
	(void) UndoInit((char *) NULL, (char *) NULL);

	/* initialize windows */
	WindInit();

	/* initialize commands */
	CmdInit();

	/* Initalize the interface between windows and its clients */
	DBWinit();
	CMWinit();

	/* Initialize the circuit extractor */
#ifndef NO_EXT
	ExtInit();
#endif

	/* Initialize plowing */
#ifndef NO_PLOW
	PlowInit();
#endif
	/* Initialize selection */
	SelectInit();

	/* Initialize the wiring module */
	WireInit();

#ifndef NO_ROUTE
	/* Initialize the netlist menu */
	NMinit();
#endif

	/* Initialize the design-rule checker */
	DRCInit();

	/* Initialize the maze router */
#ifndef NO_ROUTE
	MZInit();

	/* Initialize the interactive router - 
	   NOTE the mzrouter must be initialized prior to the irouter
	   so that default parameters will be completely setup */
	IRInit();
#endif

	/* Initialize the Mocha Chip system */
#ifdef	MOCHA
	MochaInit();
#endif

	/* Initialize the Sim Module */
	SimInit();


	/* Read in system startup file, if it exists. */
	TxSetPoint(GR_CURSOR_X, GR_CURSOR_Y, WIND_UNKNOWN_WINDOW);
	f = PaOpen(MAGIC_SYS_DOT, "r", (char *) NULL, ".",
	    (char *) NULL, (char **) NULL);
	if (f != NULL) { 
	    TxDispatch(f); 
	    (void) fclose(f);
	}

	/* Freeze our load image if requested */
	if (MainDoFreeze)
	{
	    time_t saveDate;

	    time(&saveDate);
	    strcpy(MainSaveDate, ctime(&saveDate));

	    /*
	     * When the thawed image starts up, we want to
	     * see that it was thawed (hence MainWasThawed should
	     * be TRUE), and also don't want to save it again (hence
	     * MainDoFreeze should be FALSE).
	     */
	    MainDoFreeze = FALSE;
	    MainWasThawed = TRUE;

	    /*
	     * Also close any open files so they can be re-used when
	     * this image is thawed again.  This will cause the mouse
	     * to be disabled for this session (although it will be OK
	     * when Magic is re-thawed), but a :reset command will fix
	     * that.
	     */
	    GrFlush();
	    GrClose();

	    /* Save the image */
	    TxPrintf("Saving load image in file '%s' ...", MainSaveFile);
	    (void) fflush(stdout);
	    if (!SaveImage(MainOrigFile, MainSaveFile))
	    {
		TxError("\nCannot save load image.\n");
		MainExit(1);
	    }
	    TxPrintf("Done\n");

	    /* Restore the environment so we can continue normally */
	    MainWasThawed = FALSE;
	}
    }

    /*
     * Strive for a wee bit more parallelism; let the graphics
     * display run while we're reading in startup files & initial cell.
     */
    GrFlush();

    /* Read in user's startup files, if there are any. */
    home = getenv("HOME");
    if (home != NULL)
    {
	(void) sprintf(startupFileName, "%s/.magicrc", home);
	f = PaOpen(startupFileName, "r", (char *) NULL, ".",
	    (char *) NULL, (char **) NULL);
	/* ".magicrc" back-ported from Magic-7.3+ (Fang) */
        if (f == NULL)
        {
            /* Try the (deprecated) name ".magic" */
            (void) sprintf(startupFileName, "%s/.magic", home);
            f = PaOpen(startupFileName, "r", (char *) NULL, ".",
                (char *) NULL, (char **) NULL);
            if (f != NULL)
                TxPrintf("Note:  Use of the file name \"~/.magic\" is deprecated."
                        "  Please change this to \"~/.magicrc\".\n");
        }
	if (f != NULL) {
	    TxDispatch(f); 
	    (void) fclose(f);
	}
    }
    f = PaOpen(".magicrc", "r", (char *) NULL, ".",
	(char *) NULL, (char **) NULL);
    if (f != NULL) {
	TxDispatch(f); 
	(void) fclose(f);
    }

    /*
     * Bring in a new cell to start up if one was given
     * on the command line
     */
    if (MainFileName) {
	FileName *temporary;

	while(CurrentName != NULL) {
	    temporary = CurrentName;
	    CurrentName = temporary->fn_prev;
	    DBWreload(temporary->fn);
	    freeMagic((char*) temporary);
	}
    }
    
    /* Create an initial box. */

    DBWSetBox(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox);

    /* Set the initial fence for undo-ing:  don't want to be able to
     * undo past this point.
     */
    UndoFlush();
    TxClearPoint();
}

/*
 * ----------------------------------------------------------------------------
 * mainFinish:
 *
 *	Finish up things for Magic.  This routine is NOT called on an
 *	error exit.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Various things, such as stopping measurement gathering.
 * ----------------------------------------------------------------------------
 */
void
mainFinished(void)
{
    /* Close up things */
#ifdef MALLOCTRACE
    mallocTraceDone();
#endif /* MALLOCTRACE */
    MainExit(0);
}

/*---------------------------------------------------------------------------
 * magicMain:
 *
 *	Top-level procedure of the Magic Layout System.  There is purposely
 *	not much in here so that we have more flexibility.  Also, it is
 *	not called 'main' so that other programs that use Magic may do
 *	something else.
 *
 * Results:	
 *	None.
 *
 * Side Effects:
 *	None.
 *
 * Note:  Try not to add code to this procedure.  Add it instead to one of the
 *	procedures that it calls.
 *
 *----------------------------------------------------------------------------
 */

void
magicMain(argc, argv)
    int argc;
    char *argv[];
{

#ifdef macII
    set42sig();
#endif /* macII */
    mainInitBeforeArgs(argc, argv);
    mainDoArgs(argc, argv);
    mainInitAfterArgs();
    TxDispatch( (FILE *) NULL);
    mainFinished();
}


/*
 * There is no 'moncontrol' call on many machines, but that is no big deal.
 * We just won't do performance monitoring.
 */

#ifdef NEED_MONCNTL
void
moncontrol(int mode) {}
#endif /* NEED_MONCNTL */

/*
 * ----------------------------------------------------------------------------
 *
 * mainInitProfile --
 *
 * Check for '-P' in the argument list.  If present, we override the
 * default action of Magic on startup, which is to turn off profiling
 * until explicitly enabled by the "*profile on" command.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May turn profiling on or off.
 *
 * ----------------------------------------------------------------------------
 */
void
mainInitProfile(argc, argv)
    register char **argv;
    register int argc;
{
    register char *arg;

    moncontrol(0);
    for (argv++; (arg = *argv++) && --argc > 0; )
	if (arg[0] == '-' && arg[1] == 'P')
	{
	    moncontrol(1);
	    return;
	}
}

