static char *SccsId = "@(#)main.c 4.42 (TU-Delft) 04/21/93";
/**********************************************************

Name/Version      : simeye/4.42

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

Author(s)         : A.J. van Genderen
Creation date     : 29-May-1990
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) 1990 , All rights reserved
**********************************************************/
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dmincl.h>
#include <Intrinsic.h>
#define  XAW_BC  1        /* for sun */
#include <StringDefs.h>
#include <Command.h>
#include <Dialog.h>
#include <Text.h>
#include <AsciiText.h>

#include "define.h"
#include "type.h"
#include "extern.h"
#ifdef ESE
#include "eseOption.h"
#include "tversion.h"
#endif

extern char readSetMes[];

#ifndef ESE
char *argv0 = "simeye";
char *usg_msg = "\nUsage: %s [ X options ] [ -Llmcab ] [ cell ]\n\n";
#else
char *argv0 = "simeye";
char *usg_msg = "\nUsage: %s [ X options ] [ other options ] [ cell ]\n\n";
#endif

/* Some commands and variables and their defaults.
/* The default values may be overwitten in the file ".simeyerc".
*/

char *slsCommand = "sls $cell $cell.cmd";
char *spiceCommand = "nspice $cell $cell.cmd";
int slsLogicLevel = 2;
char *xdumpFile = "simeye.wd";
char *printCommand = "xtops -white 1 -in simeye.wd -out $cell.ps; pspr $cell.ps; rm simeye.wd";
char *printLabel = "$cell  $date  $time";
char *settingsFile = "simeye.set";

char *parseCommand ();

char *rcFile = ".simeyerc";
char *defaultCommandFile = "simeye.def.d";

Widget commands;
Widget canvas;
Widget canvasbd;
Widget total;
Widget toplevel;
Widget readw;
Widget simulw;
Widget dialogw;
Widget resw;
Widget pltw;
Widget slsw;
Widget slslogw;
Widget slslogtw;
Widget slstimw;
Widget slstimtw;
Widget spicew;
Widget spicetw;
Widget wmaxw;
Widget redraww;
Widget savewinw;
Widget loadwinw;
Widget zoominw;
Widget zoomoutw;
Widget pointerw;
Widget quitw;
Widget inputsw;
Widget shufflew;
Widget signalw;
Widget siglabelw;
Widget leftw;
Widget rightw;
Widget upw;
Widget downw;
Widget hcopyw;
int Logic;          
int Spice;
int Cmd;
int currLogic;      /*    for current contents  */
int Append;
int SimLevel;
int Level3Logic;
int UseSettings;
int doDetailZoom;
int tryNonCapital;
int usedNonCapital;
char slslogtype;
char slstimtype;
Widget clickedTypew;
Widget clickedSimw;
Widget clickedSimTypew;

Widget clickedCommandw;
int commandType;
int prevCommandType;

struct signal *Begin_signal = NULL;
struct signal *End_signal = NULL;
int Nr_signals;

long Begintime = 0;
long Endtime = 0;
long SimEndtime = 0;
double Timescaling = 0;
double Voltscaling = 0;
int Global_umin;
int Global_umax;

char inputname[128];

Grid stdWidthButton = 51;
Grid stdHeightButton = 20;
Grid defSepButton = 6;

Grid stdCanvasWidth = 628;
Grid stdCanvasHeight = 418;

int rdHandler = 0;
int simWasPressed = 0;

int s_simperiod;
double s_sigunit;

int use_io_views;

char *modNameOf ();

static Display *display;
static Window window;

static XtCallbackRec callbacks[2];
static Arg args[15];

static int opt_logic;
static int opt_timing;
static int opt_spice;
static int opt_analog;
static int opt_digital;

static lastErrMess[128];

DM_PROJECT *projKey = NULL;

#ifdef ESE
OptionSpec optionSpecs[] = {
    { "", NO, eseHelp, (void *) optionSpecs,
            "usage:     simeye [X options] [other options] [cell]\nOptions (may be abbreviated) are:"},
    { "%etext", NO, eseText, (void *) NULL,
            "    -%etext:                   print the '(int) & etext' number" },
    { "%help", NO, eseHelpAll, (void *) optionSpecs,
            "    -%help:                   print this list" },
    { "help", NO, eseHelp, (void *) optionSpecs,
            "    -help:                    print this list" },
    { "release", NO, esePrintString, (void *) TOOLVERSION,
            "    -release:                 print the release number of this tool"},
    { "logic", NO, eseTurnOn, (void *) & opt_logic,
            "    -logic:                   display sls logical output (default)"  },
    { "timing", NO, eseTurnOn, (void *) & opt_timing,
            "    -timing:                  display sls timing output"  },
    { "spice", NO, eseTurnOn, (void *) & opt_spice,
            "    -spice:                   display spice output"  },
    { "analog", NO, eseTurnOn, (void *) & opt_analog,
            "    -analog:                  use analog representation"  },
    { "digital", NO, eseTurnOn, (void *) & opt_analog,
            "    -digital:                 use digital representation"  },
    { "settings", NO, eseTurnOn, (void *) & UseSettings,
            "    -settings:                use settings when reading signals"  },
    { (char *) 0, (char) 0, (IFP) 0, (void *) 0, (char *) 0 },
};

char * eseCellName = NULL;
#endif

int main (argc, argv)
int argc;
char **argv;
{
    int n;
    char *s;
    XtArgVal bg;
    long mask;
    Grid width;
    Grid borderWidth;
    char buf[8];
    void redrawHandler ();
    int destroyHandler ();
    void wInvert ();
    void ClickType ();
    void ClickSim ();
    void ClickSimType ();
    void ClickSigType ();
    void Windowmax ();
    void Savewin ();
    void Loadwin ();
    void Zoomin ();
    void Zoomout ();
    void Redraw ();
    void Move ();
    void Pointer ();
    void Quit ();
    void Inputs ();
    void Read ();
    void Simulate ();
    void Shuffle ();
    void Hardcopy ();
    void drawStartup ();
    void rubberStartup ();
    int readSignals ();
    void die ();
    void readrcFile ();

    String dialogTranslations = 
        "Ctrl<Key>J:    end-of-line()\n\
         Ctrl<Key>M:    end-of-line()\n\
         Ctrl<Key>O:    end-of-line()\n\
         Ctrl<Key>V:    end-of-line()\n\
         Meta<Key>Z:    end-of-line()\n\
         <Key>Linefeed: end-of-line()\n\
         <Key>Return:   end-of-line()";

    static XrmOptionDescRec opTable[] = {
        {"-high_lowColor",  ".high_lowColor",  XrmoptionSepArg, (caddr_t)NULL},
        {"-undefinedColor", ".undefinedColor", XrmoptionSepArg, (caddr_t)NULL},
        {"-voltsColor",     ".voltsColor",     XrmoptionSepArg, (caddr_t)NULL}
    };
    static opTable_cnt = 3;

    toplevel = XtInitialize ("main", "Simeye", 
                             opTable, opTable_cnt, &argc, argv);

    Cmd = 0;

    /* defaults */

    Logic = 1;    
    Spice = 0;
    SimLevel = slsLogicLevel;
    slslogtype = 'D';
    slstimtype = 'D';
    Level3Logic = 1;
    sprintf (inputname, "");
    UseSettings = 0;
    doDetailZoom = 0;
    tryNonCapital = 0;

    /* end defaults */

    opt_logic = 0;
    opt_timing = 0;
    opt_spice = 0;
    opt_analog = 0;
    opt_digital = 0;

#ifndef ESE
    while (--argc > 0) {
        if ( (*++argv)[0] == '-' ) {
	    for (s = *argv + 1; *s != '\0'; s++) {
	        switch (*s) {

                    case 'L' :
			UseSettings = 1;
                        break;

                    case 'l' :
			opt_logic = 1;
                        break;

                    case 'm' :           /* t can not be used because of Xt */
			opt_timing = 1;
                        break;

                    case 'c' :
			opt_spice = 1;
                        break;

                    case 'a' :
			opt_analog = 1;
                        break;

                    case 'b' :           /* d can not be used because of Xt */
			opt_digital = 1;
                        break;

		    default: 
		        fprintf (stderr, 
				 "%s: illegal option: %c\n", argv0, *s);
		        fprintf (stderr, usg_msg, argv0);
		        die (1);
	        }
	    }
	}
	else {
	    sprintf (inputname, "%s", *argv);
	}
    }
#else
    if (eseOptionHandler (argc, argv, optionSpecs, 1, &eseCellName) > 0) {
	fprintf (stderr, usg_msg, argv0);
	die (1);
    }
    if (eseCellName) {
        sprintf (inputname, "%s", eseCellName);
    }
#endif

    dmInit (argv0);

    initIntrup ();

    projKey = dmOpenProject (DEFAULT_PROJECT, PROJ_READ);

    use_io_views = 0;
#if NCF_RELEASE >= 400
    {
        /* Unfortunately,

        if ((int)dmGetMetaDesignData (EXISTVIEW, projKey, VIEW) != 1) {
        }

           does not work since it calls dmError if the view does not exist.
        */

        DM_QDATA **view_list;
        int view_entry;
        int exist_views = 0;

        view_list = projKey -> views;
        for (view_entry = 0; view_list[view_entry] != NULL; ++view_entry) {
            if (strcmp (STIMULI, view_list[view_entry][0].point) == 0
             || strcmp (SIMOUT, view_list[view_entry][0].point) == 0) {
                exist_views++;
            }
        }

        if (exist_views == 2)
            use_io_views = 1;
    }
    if (use_io_views) {
	dmCloseProject (projKey, COMPLETE);
	projKey = dmOpenProject (DEFAULT_PROJECT, DEFAULT_MODE);
    }
#endif

    readrcFile ();

    if (opt_logic) {
	Spice = 0;
	SimLevel = slsLogicLevel;
    }
    else if (opt_timing) {
	Spice = 0;
	SimLevel = 3;
    }
    else if (opt_spice) {
	Spice = 1;
    }

    if (opt_analog && !Spice) {
	if (SimLevel == 3)
	    slstimtype = 'A';
	else 
	    slslogtype = 'A';
    }
    else if (opt_digital && !Spice) {
	if (SimLevel == 3)
	    slstimtype = 'D';
	else 
	    slslogtype = 'D';
    }

    if (Spice) {
	Logic = 0;
    }
    else if (!Spice) {
	if (SimLevel == 3)
	    Logic = (slstimtype == 'D');
	else
	    Logic = (slslogtype == 'D');
    }

    callbacks[1].callback = NULL;

    n = 0;
    total = XtCreateManagedWidget ("total", formWidgetClass, toplevel, 
				    args, n);

    n = 0;
    commands = XtCreateManagedWidget ("commands", formWidgetClass, total, 
				      args, n);

    n = 0;
    signalw = XtCreateManagedWidget ("cell", formWidgetClass, commands, 
				     args, n);

    n = 0;
    XtSetArg (args[n], XtNwidth, 100), n++;
    if (use_io_views)
	XtSetArg (args[n], XtNlabel, "sim output:"), n++;
    else
	XtSetArg (args[n], XtNlabel, "cell:"), n++;
    /* XtSetArg (args[n], XtNinternalHeight, 3), n++; */
    XtSetArg (args[n], XtNvertDistance, 1), n++;
    XtSetArg (args[n], XtNhorizDistance, 3), n++;
    siglabelw = XtCreateManagedWidget ("label", labelWidgetClass, 
				       signalw, args, n);

    n = 0;
    XtSetArg (args[n], XtNwidth, 100), n++;
    XtSetArg (args[n], XtNstring, inputname), n++;
    XtSetArg (args[n], XtNuseStringInPlace, True), n++;
    XtSetArg (args[n], XtNlength, 32), n++;
    XtSetArg (args[n], XtNeditType, XawtextEdit), n++;
    XtSetArg (args[n], XtNvertDistance, 1), n++;
    XtSetArg (args[n], XtNhorizDistance, 3), n++;
    XtSetArg (args[n], XtNfromVert, siglabelw), n++;
    dialogw = XtCreateManagedWidget ("input", asciiTextWidgetClass, 
				     signalw, args, n);

    XtOverrideTranslations (dialogw, 
                            XtParseTranslationTable (dialogTranslations));
    
#ifdef OLDSIMTYPE
    callbacks[0].callback = ClickType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 4 * stdWidthButton / 5 + 1), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNhorizDistance, 10), n++;
    XtSetArg (args[n], XtNfromHoriz, signalw), n++;
    pltw = XtCreateManagedWidget ("waves", commandWidgetClass, 
				   commands, args, n);

    callbacks[0].callback = ClickType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 4 * stdWidthButton / 5 + 1), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNhorizDistance, 10), n++;
    XtSetArg (args[n], XtNfromHoriz, signalw), n++;
    XtSetArg (args[n], XtNfromVert, pltw), n++;
    resw = XtCreateManagedWidget ("logic", commandWidgetClass, 
				   commands, args, n);

    callbacks[0].callback = ClickSim;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 4 * stdWidthButton / 5 + 1), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNhorizDistance, 11), n++;
    XtSetArg (args[n], XtNfromHoriz, resw), n++;
    spicew = XtCreateManagedWidget ("spice", commandWidgetClass, 
				    commands, args, n);

    callbacks[0].callback = ClickSim;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 4 * stdWidthButton / 5 + 1), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNhorizDistance, 11), n++;
    XtSetArg (args[n], XtNfromHoriz, resw), n++;
    XtSetArg (args[n], XtNfromVert, spicew), n++;
    slsw = XtCreateManagedWidget ("sls", commandWidgetClass, 
				   commands, args, n);
#else

    callbacks[0].callback = ClickSimType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 79), n++;
    XtSetArg (args[n], XtNheight, (2 * stdHeightButton - 6 + 9) / 3), n++;
    XtSetArg (args[n], XtNhorizDistance, 8), n++;
    XtSetArg (args[n], XtNfromHoriz, signalw), n++;
    XtSetArg (args[n], XtNlabel, "sls-logic"), n++;
    XtSetArg (args[n], XtNvertDistance, 3), n++;
    slslogw = XtCreateManagedWidget ("sls-logic", commandWidgetClass, 
				       commands, args, n);

    callbacks[0].callback = ClickSigType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 20), n++;
    XtSetArg (args[n], XtNheight, (2 * stdHeightButton - 6 + 9) / 3), n++;
    XtSetArg (args[n], XtNhorizDistance, 1), n++;
    XtSetArg (args[n], XtNfromHoriz, slslogw), n++;
    buf[0] = slslogtype;
    buf[1] = '\0';
    XtSetArg (args[n], XtNlabel, buf), n++;
    XtSetArg (args[n], XtNvertDistance, 3), n++;
    slslogtw = XtCreateManagedWidget ("sls-log-type", commandWidgetClass, 
				       commands, args, n);

    callbacks[0].callback = ClickSimType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 79), n++;
    XtSetArg (args[n], XtNheight, (2 * stdHeightButton - 6 + 9) / 3), n++;
    XtSetArg (args[n], XtNhorizDistance, 8), n++;
    XtSetArg (args[n], XtNfromHoriz, signalw), n++;
    XtSetArg (args[n], XtNvertDistance, 1), n++;
    XtSetArg (args[n], XtNfromVert, slslogw), n++;
    XtSetArg (args[n], XtNlabel, "sls-timing"), n++;
    slstimw = XtCreateManagedWidget ("sls-timing", commandWidgetClass, 
				       commands, args, n);

    callbacks[0].callback = ClickSigType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 20), n++;
    XtSetArg (args[n], XtNheight, (2 * stdHeightButton - 6 + 9) / 3), n++;
    XtSetArg (args[n], XtNhorizDistance, 1), n++;
    XtSetArg (args[n], XtNfromHoriz, slstimw), n++;
    XtSetArg (args[n], XtNvertDistance, 1), n++;
    XtSetArg (args[n], XtNfromVert, slslogtw), n++;
    buf[0] = slstimtype;
    buf[1] = '\0';
    XtSetArg (args[n], XtNlabel, buf), n++;
    slstimtw = XtCreateManagedWidget ("sls-tim-type", commandWidgetClass, 
				       commands, args, n);

    callbacks[0].callback = ClickSimType;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, 79), n++;
    XtSetArg (args[n], XtNheight, (2 * stdHeightButton - 6 + 9) / 3), n++;
    XtSetArg (args[n], XtNhorizDistance, 8), n++;
    XtSetArg (args[n], XtNfromHoriz, signalw), n++;
    XtSetArg (args[n], XtNvertDistance, 1), n++;
    XtSetArg (args[n], XtNfromVert, slstimw), n++;
    XtSetArg (args[n], XtNlabel, "spice"), n++;
    spicew = XtCreateManagedWidget ("spice", commandWidgetClass, 
				       commands, args, n);

    n = 0;
    XtSetArg (args[n], XtNwidth, 20), n++;
    XtSetArg (args[n], XtNheight, (2 * stdHeightButton - 6 + 9) / 3), n++;
    XtSetArg (args[n], XtNhorizDistance, 1), n++;
    XtSetArg (args[n], XtNfromHoriz, spicew), n++;
    XtSetArg (args[n], XtNvertDistance, 1), n++;
    XtSetArg (args[n], XtNfromVert, slstimtw), n++;
    buf[0] = 'A';
    buf[1] = '\0';
    XtSetArg (args[n], XtNlabel, buf), n++;
    spicetw = XtCreateManagedWidget ("spice-type", labelWidgetClass, 
				     commands, args, n);

#endif

    callbacks[0].callback = Simulate;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNhorizDistance, 6), n++;
    XtSetArg (args[n], XtNfromHoriz, slstimtw), n++;
    simulw = XtCreateManagedWidget ("run", commandWidgetClass, 
				     commands, args, n);

    callbacks[0].callback = Read;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromVert, simulw), n++;
    XtSetArg (args[n], XtNhorizDistance, 6), n++;
    XtSetArg (args[n], XtNfromHoriz, slstimtw), n++;
    readw = XtCreateManagedWidget ("read", commandWidgetClass, 
				   commands, args, n);

    callbacks[0].callback = Redraw;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, readw), n++;
    redraww = XtCreateManagedWidget ("redraw", commandWidgetClass, 
				     commands, args, n);

    callbacks[0].callback = Windowmax;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, readw), n++;
    XtSetArg (args[n], XtNfromVert, redraww), n++;
    wmaxw = XtCreateManagedWidget ("full", commandWidgetClass, 
				   commands, args, n);

    callbacks[0].callback = Zoomout;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, wmaxw), n++;
    zoomoutw = XtCreateManagedWidget ("out", commandWidgetClass, 
				      commands, args, n);

    callbacks[0].callback = Zoomin;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, wmaxw), n++;
    XtSetArg (args[n], XtNfromVert, zoomoutw), n++;
    zoominw = XtCreateManagedWidget ("in", commandWidgetClass, 
				     commands, args, n);

    callbacks[0].callback = Move;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, (stdWidthButton - defSepButton) / 2), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, zoomoutw), n++;
    upw = XtCreateManagedWidget ("/\\", commandWidgetClass, 
				    commands, args, n);

    callbacks[0].callback = Move;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, (stdWidthButton - defSepButton) / 2), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, upw), n++;
    downw = XtCreateManagedWidget ("\\/", commandWidgetClass, 
				    commands, args, n);

    callbacks[0].callback = Move;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, (stdWidthButton - defSepButton) / 2), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, zoomoutw), n++;
    XtSetArg (args[n], XtNfromVert, upw), n++;
    leftw = XtCreateManagedWidget ("<", commandWidgetClass, 
				    commands, args, n);

    callbacks[0].callback = Move;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, (stdWidthButton - defSepButton) / 2), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, leftw), n++;
    XtSetArg (args[n], XtNfromVert, upw), n++;
    rightw = XtCreateManagedWidget (">", commandWidgetClass, 
				    commands, args, n);

    callbacks[0].callback = Savewin;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, (stdWidthButton - defSepButton) / 2), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, rightw), n++;
    savewinw = XtCreateManagedWidget ("S", commandWidgetClass, 
				      commands, args, n);

    callbacks[0].callback = Loadwin;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, (stdWidthButton - defSepButton) / 2), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, savewinw), n++;
    loadwinw = XtCreateManagedWidget ("L", commandWidgetClass, 
				      commands, args, n);

    callbacks[0].callback = Shuffle;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++;
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, rightw), n++;
    XtSetArg (args[n], XtNfromVert, savewinw), n++;
    shufflew = XtCreateManagedWidget ("move", commandWidgetClass, 
				     commands, args, n);

    callbacks[0].callback = Hardcopy;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++; 
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++; 
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, loadwinw), n++;
    hcopyw = XtCreateManagedWidget ("print", commandWidgetClass, 
                                     commands, args, n);

    callbacks[0].callback = Pointer;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++; 
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++; 
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, shufflew), n++;
    XtSetArg (args[n], XtNfromVert, hcopyw), n++;
    pointerw = XtCreateManagedWidget ("value", commandWidgetClass, 
				      commands, args, n);

    callbacks[0].callback = Quit;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++; 
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++; 
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, hcopyw), n++;
    /* XtSetArg (args[n], XtNhorizDistance, 11), n++; */
    quitw = XtCreateManagedWidget ("quit", commandWidgetClass, 
                                    commands, args, n);

    callbacks[0].callback = Inputs;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++; 
    XtSetArg (args[n], XtNwidth, stdWidthButton), n++; 
    XtSetArg (args[n], XtNheight, stdHeightButton), n++;
    XtSetArg (args[n], XtNfromHoriz, hcopyw), n++;
    /* XtSetArg (args[n], XtNhorizDistance, 11), n++; */
    XtSetArg (args[n], XtNfromVert, quitw), n++;
    inputsw = XtCreateManagedWidget ("input", commandWidgetClass, 
                                    commands, args, n);

    n = 0;
    XtSetArg (args[n], XtNfromVert, commands), n++;
    XtSetArg (args[n], XtNdefaultDistance, 0), n++;
    XtSetArg (args[n], XtNresizable, True), n++;
    canvasbd = XtCreateManagedWidget ("canvas_bd", formWidgetClass, total, 
				      args, n);

    n = 0;
    XtSetArg (args[n], XtNwidth, stdCanvasWidth), n++;
    XtSetArg (args[n], XtNheight, stdCanvasHeight), n++;
    XtSetArg (args[n], XtNresizable, True), n++;
    canvas = XtCreateManagedWidget ("canvas", widgetClass, canvasbd, args, n);

    XtRealizeWidget (toplevel);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (siglabelw, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (siglabelw, args, n);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtSetArg (args[n], XtNborderWidth, 0), n++;
    XtGetValues (canvas, args, n);
    bg = args[0].value;
    borderWidth = args[1].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (canvas, args, n);

    n = 0;
    XtSetArg (args[n], XtNwidth, 0), n++;
    XtGetValues (commands, args, n);
    width = args[0].value - 2 * borderWidth;

    if (width != stdCanvasWidth) {
	/* this may happen because the border width of the command
	   buttons is not 1 */
	n = 0;
	XtSetArg (args[n], XtNwidth, width), n++;
	XtSetValues (canvas, args, n);
    }

#ifdef OLDSIMTYPE
    if (Logic) {
	wInvert (resw);
	clickedTypew = resw;
    }
    else {
	wInvert (pltw);
	clickedTypew = pltw;
    }

    if (Spice) {
	wInvert (spicew);
	clickedSimw = spicew;
    }
    else {
	wInvert (slsw);
	clickedSimw = slsw;
    }
#else
    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (slslogw, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (slslogw, args, n);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (slslogtw, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (slslogtw, args, n);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (slstimw, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (slstimw, args, n);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (slstimtw, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (slstimtw, args, n);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (spicew, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (spicew, args, n);

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtGetValues (spicetw, args, n);
    bg = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNborderColor, bg), n++;
    XtSetValues (spicetw, args, n);

    if (Spice) {
	wInvert (spicew);
	clickedSimTypew = spicew;
    }
    else {
	if (SimLevel == 1 || SimLevel == 2) {
	    wInvert (slslogw);
	    clickedSimTypew = slslogw;
	}
	else {
	    wInvert (slstimw);
	    clickedSimTypew = slstimw;
	}
    }
#endif

    currLogic = Logic;

    display = XtDisplay (toplevel);
    window = XtWindow (toplevel);

    drawStartup ();
    eventsStartup ();

    XSync (display, False);

    if (inputname[0] != '\0') {
	readSignals (0, 0);
    }

    /* activate a redraw handler for exposure and resize events */

    mask = ExposureMask;
    XtAddEventHandler (canvas, mask, False, redrawHandler, NULL);

    /* activate handler for fatal I/O errors 
       (e.g. when a XKillClient was done */

    XSetIOErrorHandler (destroyHandler);

    XtMainLoop ();

    return (0);
}

void redrawHandler (w, client_data, event)
Widget w;
caddr_t client_data;
XEvent *event;
{
    void clear ();
    void draw ();

    if (Begin_signal) {

	rdHandler = 1;

	clear ();
	draw (0, 0, 0, 0, 0);

        redrawEvent ();
 	                            /* wait and discard new events to */
	XSync (display, True);      /* prevent boots-trapping of the handler */
    }
    else {
	redrawListOrMessage ();
    }
}

int destroyHandler (display)
Display *display;
{
    int_hdl (SIGTERM);
}

void ClickType (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void wInvert ();

    wInvert (clickedTypew, 0, 0);

    if (w == resw) {
	Logic = 1;
    }
    else if (w == pltw) {
	Logic = 0;
    }

    wInvert (w, 0, 0);
    clickedTypew = w;
}

void ClickSim (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void wInvert ();

    wInvert (clickedSimw, 0, 0);

    if (w == spicew) {
	Spice = 1;
    }
    else if (w == slsw) {
	Spice = 0;
    }

    wInvert (w, 0, 0);
    clickedSimw = w;
}

void ClickSimType (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void wInvert ();

    if (!(clickedSimTypew == w && w == slstimw))
	wInvert (clickedSimTypew, 0, 0);

    if (w == slslogw) {
	Spice = 0;
	Logic = (slslogtype == 'D');
	SimLevel = slsLogicLevel;
	/* somethingChanged = 1;  why would this be necessary ? AvG 10Dec92 */
    }
    else if (w == slstimw) {
	Spice = 0;
	Logic = (slstimtype == 'D');
	SimLevel = 3;
	/* somethingChanged = 1;  why would this be necessary ? AvG 10Dec92 */
    }
    else if (w == spicew) {
	Spice = 1;
	Logic = 0;
	SimLevel = 3;
    }

    if (!(clickedSimTypew == w && w == slstimw)) {
	wInvert (w, 0, 0);
	clickedSimTypew = w;
    }
}

void ClickSigType (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    int n;
    char *labelvalue;

    if (w == slstimtw) {
	if (slstimtype == 'D')
	    labelvalue = "A";
	else
	    labelvalue = "D";
	slstimtype = labelvalue[0];

	if (slstimw == clickedSimTypew)
	    Logic = (slstimtype == 'D');
    }
    else {
	if (slslogtype == 'D')
	    labelvalue = "A";
	else
	    labelvalue = "D";
	slslogtype = labelvalue[0];

	if (slslogw == clickedSimTypew)
	    Logic = (slslogtype == 'D');
    }

    n = 0;
    XtSetArg (args[n], XtNlabel, labelvalue), n++;
    XtSetValues (w, args, n);
}

void wInvert (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    int n;
    XtArgVal fg;
    XtArgVal bg;

    n = 0;
    XtSetArg (args[n], XtNbackground, 0), n++;
    XtSetArg (args[n], XtNforeground, 0), n++;
    XtGetValues (w, args, n);
    bg = args[0].value;
    fg = args[1].value;

    n = 0;
    XtSetArg (args[n], XtNbackground, fg), n++;
    XtSetArg (args[n], XtNforeground, bg), n++;
    XtSetValues (w, args, n);
}

void Read (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    int readSignals ();

    if (clickedCommandw) {
	endCommand ();
    }

    readSignals (1, 0);
}

void Simulate (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    char *simulator;
    char commandfile[128];
    char act_commandfile[128];
    char tmp_commandfile[128];
    char command[128];
    char buf[128];
    int u;
    struct stat statbuf;
    void windowMessage ();
    int readSignals ();
    void clear ();

    if (clickedCommandw) {
	endCommand ();
    }

    if (editing) {
	if (somethingChanged) {
	    windowMessage ("finish edit mode first", -1);
	    return;
	}
	else {
	    /* First, execute 'Return' routine.
	       When this WRITE command is finished 'Simulate' will be 
	       called again in beginCommand.
	    */
	    simWasPressed = 1;
	    Return (NULL, NULL, NULL);
	    return;
	}
    }

    simWasPressed = 0;

    sprintf (commandfile, "%s.cmd", modNameOf (inputname));

    /* update commandfile for set commands, print commands, level etc. */

    updateCommandfile ();

    /* and prepare for simulation */

    clear ();

    delSigList (Begin_signal);    /* delete all signals */

    Nr_signals = 0;

    Begin_signal = NULL;
    End_signal = NULL;

    if (usedNonCapital && !use_io_views) { 
	sprintf (act_commandfile, "%s", commandfile);
	act_commandfile[0] = act_commandfile[0] - ('A' - 'a');
	sprintf (tmp_commandfile, "%d.cxx", getpid ());
	sprintf (command, "mv %s %s", act_commandfile, tmp_commandfile);
	system (command);
	sprintf (command, "arrexp %s > %s", tmp_commandfile, act_commandfile);
	if (system (command) != 0) {
	    windowMessage ("Cannot execute arrexp", -1);
	    goto end_of_simul;
	}
        sprintf (buf,
		 ".... simulating (using commandfile \"%s\" instead) ....", 
		 act_commandfile);
    }
    else
        strcpy (buf, ".... simulating ....");
    windowMessage (buf, -1);

    XFlush (display);

    /* Clean up previous simulation result */

    if (Spice) {
	sprintf (buf, "%s.ana", inputname);
	if (stat (buf, &statbuf) == 0) unlink (buf);
    }
    else {
	sprintf (buf, "%s.res", inputname);
	if (stat (buf, &statbuf) == 0) unlink (buf);
	sprintf (buf, "%s.plt", inputname);
	if (stat (buf, &statbuf) == 0) unlink (buf);
    }

    if (Spice) {
        simulator = spiceCommand;
    }
    else {
        simulator = slsCommand;
    }

    sprintf (command, "%s", parseCommand (simulator));

    u = runTool (command, "sim.diag", 
		 (!Spice && !use_io_views && s_simperiod > 0));
    if (u == 0) {
	windowMessage ("simulation ready", -1);
    }
    else if (u == -1) {
	windowMessage ("simulation aborted", -1);
    }
    else if (u == 1) {
	windowList ("sim.diag");
    }

end_of_simul:
    if (usedNonCapital && !use_io_views) {
	/* restore actual commandfile */
	sprintf (command, "mv %s %s", tmp_commandfile, act_commandfile);
	system (command);
    }
    usedNonCapital = 0;
}

void Windowmax (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    if (clickedCommandw) {
	endCommand ();
    }

    /* If necessary, clear will be executed in draw */

    draw ('m', 0, 0, 0, 0);
}

void Savewin (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    char buf[80];
    FILE *fp;
    struct signal *sig;

    if (clickedCommandw) {
	endCommand ();
    }

    if ((fp = fopen (parseCommand (settingsFile), "w")) == NULL) {
	sprintf (buf, "Cannot write %s", parseCommand (settingsFile));
	windowMessage (buf, -1);
	return;
    }

    fprintf (fp, "t_start: %ld\n", startTime);
    fprintf (fp, "t_stop: %ld\n", stopTime);
    sig = Top_signal;
    while (sig != NULL && sig -> prev != Bottom_signal) {
	fprintf (fp, "sig: %s\n", sig -> name);
	sig = sig -> next;
    }

    fclose (fp);

    windowMessage ("Settings saved", -1);
}

void Loadwin (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void draw ();
    void clear ();
    int loadSettings ();

    if (clickedCommandw) {
	endCommand ();
    }

    if (loadSettings ()) {

	clear ();

	draw ('a', 0, 0, 0, 0);

	windowMessage ("Settings loaded", -1);
    }
}

void Zoomin (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void rubberBox ();
    void clear ();

    if (clickedCommandw) {
	endCommand ();
    }

    commandType = ZOOMIN;
    beginCommand (w);
}

void Zoomout (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void rubberBox ();
    void clear ();

    if (clickedCommandw) {
	endCommand ();
    }

    commandType = ZOOMOUT;
    beginCommand (w);
}

void Redraw (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void draw ();
    void clear ();

    if (clickedCommandw) {
	endCommand ();
    }

    clear ();

    draw (0, 0, 0, 0, 0);
}

void Move (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void draw ();

    if (clickedCommandw) {
	endCommand ();
    }

    /* If necessary, clear will be executed in draw */

    if (w == leftw)
	draw ('l', 0, 0, 0, 0);
    else if (w == rightw)
	draw ('r', 0, 0, 0, 0);
    else if (w == upw)
	draw ('u', 0, 0, 0, 0);
    else if (w == downw)
	draw ('d', 0, 0, 0, 0);
}

void Pointer (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    if (clickedCommandw) {
	endCommand ();
    }

    commandType = MEASURE;
    beginCommand (w);
}

void Shuffle (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    if (clickedCommandw) {
	endCommand ();
    }

    commandType = SHUFFLE;
    beginCommand (w);
}

void Hardcopy (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    char command[128];
    Window win;

    if (clickedCommandw) {
	endCommand ();
    }

    win = XtWindow (canvas);

    if (printLabel && printLabel[0] != '\0') {
	windowMessage (parseCommand (printLabel), -1);
	XFlush (display);
    }

    sprintf (command, "xwd -id 0x%x -out %s 1> pr.diag 2>&1", 
		      win, parseCommand (xdumpFile));

    /* redirect both 'stdout' and 'stderr' to pr.diag */

    /* Printing is not done with runTool since more than one
       program may be called in one command.
    */

    if (system (command) == 0) {

        if (printCommand && printCommand[0] != '\0') {
	    sprintf (command, "%s 1> pr.diag 2>&1", 
			      parseCommand (printCommand));

	    windowMessage (".... printing ....", -1);

	    XFlush (display);

	    if (system (command) == 0) {

		windowMessage ("print ready", -1);
	    }
	    else {

		windowList ("pr.diag");
	    }
	}
	else {
	    windowMessage ("print ready", -1);
	}
    }
    else {

	windowList ("pr.diag");
    }
}

void Inputs (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    int readSet ();

    if (clickedCommandw) {
	endCommand ();
    }

    clear ();

    Append = 0;

    if (readSet (inputname) == 0) {
	if (readSetMes[0] != '\0')
	    windowMessage (readSetMes, -1);
	return;
    }

    if (!editing) {

	enableEditing ();

	Cmd = 1;
    }

    currLogic = 1;

    draw ('f', 0, 0, 0, 0);

    if (readSetMes[0] != '\0')
        windowMessage (readSetMes, -1);
}

void Quit (w, client_data, call_data)
Widget w;
caddr_t client_data;  /* unused */
caddr_t call_data;    /* unused */
{
    void die ();

    if (clickedCommandw) {
	endCommand ();
    }

    if (editing && somethingChanged) {
        commandType = QUITP;
	beginCommand (w);
    }
    else
	die (0);
}

int readSignals (flag, intermediate)
int flag;
int intermediate;
/*                    flag = 1 : check if shiftMask is pressed
/*                    intermediate = 0  : no intermediate read
/*                                 = 2  : start intermediate read
/*                                 = 1  : intermediate read
/*                                 = -1 : end intermediate read
*/
{
    Window root, child;
    Grid root_x, root_y;
    Grid win_x, win_y;
    int mask;
    int readLogic ();
    int readWaves ();
    int readSpice ();
    void draw ();
    void clear ();
    void windowMessage ();
    int loadSettings ();
    extern char windowMesBuf[];

    if (editing) {
	windowMessage ("no read in edit mode", -1);
	return (0);
    }

    if (flag)
	XQueryPointer (display, window, &root, &child, 
		       &root_x, &root_y, &win_x, &win_y, &mask);
    else
	mask = 0;

    if ((mask & ShiftMask) && Begin_signal != NULL)
	Append = 1;
    else
	Append = 0;

    if (intermediate == 0)
	clear ();

    if (Append && Logic != currLogic) {
	windowMessage ("Cannot merge logical and analog signals", -1);
	return (0);
    }

    if (editing && !Logic) {
	windowMessage ("Cannot edit analog signals", -1);
	return (0);
    }

    if (Logic) {
	if (Spice) {
	    windowMessage ("No logic signals for spice", -1);
	    return (0);
	}
	else {
	    if (readLogic (inputname, intermediate) == 0)
		return (0);
	}
    }
    else {
	if (Spice) {
	    if (readSpice (inputname, intermediate) == 0)
		return (0);
	}
	else {
	    if (readWaves (inputname, intermediate) == 0)
		return (0);
	}
    }

    Cmd = 0;

    currLogic = Logic;

    if (intermediate && s_simperiod > 0 && s_sigunit > 0) {
	Endtime = s_simperiod * s_sigunit / Timescaling;
    }

    if (UseSettings && (intermediate == 0 || intermediate == 2)) {
	if (loadSettings ()) {
            if (intermediate == 0)
                draw ('a', 0, 0, 0, 0);
            else
                draw ('b', 0, 0, 0, 0);
        }
	else {
	    draw ('f', 0, 0, 0, 0);
	    windowMessage (lastErrMess, -1);
	}
    }
    else {
        if (intermediate == 0)
            draw ('f', 0, 0, 0, 0);
        else if (intermediate == 2)
            draw ('s', 0, 0, 0, 0);
	else
	    draw ('t', 0, 0, 0, 0);
    }

    return (1);
}

void clear ()
{
    Display *display;
    Window window;

    window = XtWindow (canvas);
    display = XtDisplay (canvas);
    XClearWindow (display, window);
}

int loadSettings ()
{
    FILE *fp;
    char buf[128];
    char c;
    int error;
    char name[128];
    long newStartTime;
    long newStopTime;
    struct signal *sig;
    struct signal *newTop_signal;
    struct signal *newBottom_signal;
    int newCurr_nr_signals;
    void rcReadError ();

    if ((fp = fopen (parseCommand (settingsFile), "r")) == NULL) {
	sprintf (buf, "Cannot read %s", parseCommand (settingsFile));
	strcpy (lastErrMess, buf);
	windowMessage (buf, -1);
	return (0);
    }

    newTop_signal = NULL;
    newBottom_signal = NULL;
    newCurr_nr_signals = 0;

    while (fscanf (fp, "%s", buf) > 0) {

	error = 0;
	
	if (buf[0] == '#') {        /* comment, skip until end of line */
	    while ((c = getc (fp)) != '\n' && c != EOF);
	}

	if (strcmp (buf, "spice:") == 0) {
	}
	else if (strcmp (buf, "simlevel:") == 0) {
	}
	else if (strcmp (buf, "level3logic:") == 0) {
	}
	else if (strcmp (buf, "t_start:") == 0) {
	    if (fscanf (fp, "%ld", &newStartTime) <= 0)
		error = 1;
	}
	else if (strcmp (buf, "t_stop:") == 0) {
	    if (fscanf (fp, "%ld", &newStopTime) <= 0)
		error = 1;
	}
	else if (strcmp (buf, "sig:") == 0) {
	    if (fscanf (fp, "%s", name) <= 0)
		error = 1;
	    else {
		for (sig = (newBottom_signal ? 
			    newBottom_signal -> next : Begin_signal);
		     sig; sig = sig -> next) {
		    if (strcmp (sig -> name, name) == 0) 
			break;
		}
		if (sig) {
		    if (newTop_signal == NULL) {
			newTop_signal = sig;
			newBottom_signal = sig;
			if (sig != Begin_signal) {
			    if (sig == End_signal)
				End_signal = sig -> prev;
			    if (sig -> prev) 
				sig -> prev -> next = sig -> next;
			    if (sig -> next) 
				sig -> next -> prev = sig -> prev;
			    sig -> prev = NULL;
			    sig -> next = Begin_signal;
			    Begin_signal -> prev = sig;
			    Begin_signal = sig;
			}
		    }
		    else if (sig != newBottom_signal) {
			if (newBottom_signal -> next != sig) {
			    if (sig == End_signal)
				End_signal = sig -> prev;
			    if (sig == Begin_signal)
				Begin_signal = sig -> next;
			    if (sig -> prev) 
				sig -> prev -> next = sig -> next;
			    if (sig -> next) 
				sig -> next -> prev = sig -> prev;
			    sig -> prev = newBottom_signal;
			    sig -> next = newBottom_signal -> next;
			    if (newBottom_signal -> next)
				newBottom_signal -> next -> prev = sig;
			    else
				End_signal = sig;
			    newBottom_signal -> next = sig;
			}
			newBottom_signal = sig;
		    }
		    newCurr_nr_signals++;
		}
	    }
	}
	else {
	    rcReadError (parseCommand (settingsFile), buf);
	}

	if (error)
	    rcReadError (parseCommand (settingsFile), buf);

	while ((c = getc (fp)) != '\n' && c != EOF); 

	/* skip everything until end of line */
    }

    fclose (fp);

    if (newCurr_nr_signals == 0) {
	windowMessage ("Settings do not refer to current signals", -1); 
	strcpy (lastErrMess, "Settings do not refer to current signals");
	return (0);
    }

    startTime = newStartTime;
    stopTime = newStopTime;

    if (startTime < Begintime)
	startTime = Begintime;
    if (startTime >= Endtime)
	startTime = Endtime - 1;
    if (stopTime > Endtime)
	stopTime = Endtime;
    if (stopTime <= Begintime)
	stopTime = Begintime - 1;
    if (startTime >= stopTime)
	startTime = stopTime - 1;

    Top_signal = newTop_signal;
    Bottom_signal = newBottom_signal;
    Curr_nr_signals = newCurr_nr_signals;

    curr_umin = Global_umin;
    curr_umax = Global_umax;

    return (1);
}

void readrcFile ()
{
    char buf[256];
    char c;
    FILE *fp;
    char *fn;
    char *home;
    char *getenv ();
    void rcReadError ();
    int myscanf ();

    if ((fp = fopen (rcFile, "r")) == NULL) {

	if (home = getenv ("HOME")) {
	    NEW (fn, strlen (home) + strlen (rcFile) + 2, char);
	    if (fn) {
		sprintf (fn, "%s/%s", home, rcFile);
		fp = fopen (fn, "r");
	    }
	}

	if (fp == NULL && projKey) {
	    if (fn = (char *)dmGetMetaDesignData (PROCPATH, projKey, rcFile))
		fp = fopen (fn, "r");
	}
    }
    else
	fn = rcFile;

    if (!fp) {
	return;
    }

    while (fscanf (fp, "%s", buf) > 0) {
	
	if (buf[0] == '#') {        
	    /* comment */
	}
	else if (strcmp (buf, "SLS:") == 0) {
	    if (myscanf (fp, buf) > 0) {
		NEW (slsCommand, strlen (buf) + 1, char);
		strcpy (slsCommand, buf);
	    }
	    else {
		rcReadError (fn, "SLS:");
	    }
	}
	else if (strcmp (buf, "SPICE:") == 0) {
	    if (myscanf (fp, buf) > 0) {
		NEW (spiceCommand, strlen (buf) + 1, char);
		strcpy (spiceCommand, buf);
	    }
	    else {
		rcReadError (fn, "SPICE:");
	    }
	}
	else if (strcmp (buf, "PRINT:") == 0) {
	    if (myscanf (fp, buf) > 0) {
		NEW (printCommand, strlen (buf) + 1, char);
		strcpy (printCommand, buf);
	    }
	    else {
		rcReadError (fn, "PRINT:");
	    }
	}
	else if (strcmp (buf, "PRINT_LABEL:") == 0) {
	    if (myscanf (fp, buf) > 0) {
		NEW (printLabel, strlen (buf) + 1, char);
		strcpy (printLabel, buf);
	    }
	    else {
		rcReadError (fn, "PRINT_LABEL:");
	    }
	}
	else if (strcmp (buf, "SLS_LOGIC_LEVEL:") == 0) {
	    if (fscanf (fp, "%d", &slsLogicLevel) > 0) {
		if (slsLogicLevel < 1) slsLogicLevel = 1;
		else if (slsLogicLevel > 2) slsLogicLevel = 2;
	    }
	    else {
		rcReadError (fn, "SLS_LOGIC_LEVEL:");
	    }
	}
	else if (strcmp (buf, "SLS_LOGIC_SIGNAL:") == 0) {
	    if (fscanf (fp, "%s", buf) > 0) {
		if (buf[0] == 'D') slslogtype = 'D';
		else if (buf[0] == 'A') slslogtype = 'A';
	    }
	    else {
		rcReadError (fn, "SLS_LOGIC_SIGNAL:");
	    }
	}
	else if (strcmp (buf, "SLS_TIMING_SIGNAL:") == 0) {
	    if (fscanf (fp, "%s", buf) > 0) {
		if (buf[0] == 'D') slstimtype = 'D';
		else if (buf[0] == 'A') slstimtype = 'A';
	    }
	    else {
		rcReadError (fn, "SLS_TIMING_SIGNAL:");
	    }
	}
	else if (strcmp (buf, "XDUMP_FILE:") == 0) {
	    if (fscanf (fp, "%s", buf) > 0) {
		NEW (xdumpFile, strlen (buf) + 1, char);
		strcpy (xdumpFile, buf);
	    }
	    else {
		rcReadError (fn, "XDUMP_FILE:");
	    }
	}
	else if (strcmp (buf, "SETTINGS_FILE:") == 0) {
	    if (myscanf (fp, buf) > 0) {
		NEW (settingsFile, strlen (buf) + 1, char);
		strcpy (settingsFile, buf);
	    }
	    else {
		rcReadError (fn, "SETTINGS_FILE:");
	    }
	}
	else if (strcmp (buf, "DETAIL_ZOOM_ON") == 0) {
	    doDetailZoom = 1;
	}
	else if (strcmp (buf, "TRY_NON_CAPITAL_ON") == 0) {
	    tryNonCapital = 1;
	}
	else {
	    rcReadError (fn, buf);
	}

	while ((c = getc (fp)) != '\n' && c != EOF); 
	if (c == EOF) break;

	/* skip everything until end of line */
    }

    fclose (fp);
}

int myscanf (fp, s)
FILE *fp;
char *s;
{
    int i;
    int nonspace;
    char c;

    while ((c = getc (fp)) == ' ' || c == '\t');
  
    i = 0;
    nonspace = -1;
    if (c != EOF && c != '\n') {
	while (c != EOF && c != '\n') {
	    s[i] = c;
	    if (c != ' ' && c != '\t')
		nonspace = i;
	    c = getc (fp);
	    i++;
	}
    }

    s[nonspace + 1] = '\0';

    ungetc (c, fp);

    if (i > 0)
	return (1);
    else if (c == EOF)
	return (-1);
    else
	return (0);
}

void rcReadError (fn, s)
char *fn;
char *s;
{
    fprintf (stderr, "Error in file '%s' for '%s'\n", fn, s);
    die (1);
}


double slstof (s)
char *s;
{
    char c;
    char buf[256];
    double val = -1;
    int len;
    double atof ();

    strcpy (buf, s);
    len = strlen (buf);

    c = buf[len-1];
    if (isdigit(c))
	val = atof (buf);
    else {
	buf[len-1] = '\0';
	switch (c) {
	    case 'G': val = 1.0e9 * atof (buf);
		      break;
	    case 'M': val = 1.0e6 * atof (buf);
		      break;
	    case 'k': val = 1.0e3 * atof (buf);
		      break;
	    case 'm': val = 1.0e-3 * atof (buf);
		      break;
	    case 'u': val = 1.0e-6 * atof (buf);
		      break;
	    case 'n': val = 1.0e-9 * atof (buf);
		      break;
	    case 'p': val = 1.0e-12 * atof (buf);
		      break;
	    case 'f': val = 1.0e-15 * atof (buf);
		      break;
	}
    }

    return (val);
}

char *parseCommand (s)
char *s;
{
    char *t;
    char *p;
    char help[128];
    FILE *fp;
    char c;
    int cell_cnt = 0;
    static char buf[256];

    p = buf;
    while (*s != '\0') {
	if (*s == '$' && *(s+1) == 'c' 
	    && *(s+2) == 'e' && *(s+3) == 'l' && *(s+4) == 'l') {

	    cell_cnt++;

	    t = inputname;
	    if (usedNonCapital && cell_cnt == 2)
		*p++ = (*t++) - ('A' - 'a');  /* decapitalize first char. */
	    while (*t) {
		*p++ = *t++;
	    }
	    s = s + 5;
	}
	else if (*s == '$' && *(s+1) == 'd'
	    && *(s+2) == 'a' && *(s+3) == 't' && *(s+4) == 'e') {

	    sprintf (help, "date '+%%d %%h %%y' > %s.cxx", inputname);
	    if (system (help) == 0) {
		sprintf (help, "%s.cxx", inputname);
		if (fp = fopen (help, "r")) {
		    while ((c = fgetc (fp)) != EOF && c != '\n') {
			*p++ = c;
		    }
		    fclose (fp);
		}
	    }
	    s = s + 5;
	}
	else if (*s == '$' && *(s+1) == 't'
	    && *(s+2) == 'i' && *(s+3) == 'm' && *(s+4) == 'e') {

	    sprintf (help, "date '+%%T' > %s.cxx", inputname);
	    if (system (help) == 0) {
		sprintf (help, "%s.cxx", inputname);
		if (fp = fopen (help, "r")) {
		    while ((c = fgetc (fp)) != EOF && c != '\n') {
			*p++ = c;
		    }
		    fclose (fp);
		}
	    }
	    s = s + 5;
	}
	else {
	    *p++ = *s++;
	}
    }
    *p = '\0';

    return (buf);
}

char *modNameOf (s)
char *s;
{
    static char buf[40];
    char *tmp_p;

    strcpy (buf, s);
    if ((tmp_p = strchr (buf, ' ')) != NULL) {
        /* ' ' character in name. */
        *tmp_p = '\0';
    }
    if ((tmp_p = strchr (buf, '#')) != NULL) {
        /* '#' character in name. */
        *tmp_p = '\0';
    }

    return (buf);
}

/*
** Return codes of fork
*/
#define CHILD 0
#define PARENT 1:default
#define ERROR -1

static int pgid = 0;
static int childpid = 0;
static int childRunning = 0;
static int toolReadyStatus;

int runTool (s, outFile, monitorSig)
char *s;
char *outFile;
int monitorSig;
/*              monitorSig = 0 : draw final result
/*                           1 : draw intermediate and final result
/*                          -1 : do not draw result
*/
{
    int v;
    int argno = 0;
    char *argv[16];
    char *path = NULL;
    char buf[132];
    char *p;
    int readSigMes;
    XEvent event;
    XEvent leaveEvent;
    int left;
    XEvent *ev;
    int probe_time = 3;   /* at every 'probe_time' seconds new 
			     simulation results are displayed */
    int mon_cnt;
    Bool checkEvent ();
    int int_hdl ();
    int errorInFile ();

    strcpy (buf, s);
    p = &buf[0];

    while (*p != '\0') {
	if (!path) 
	    path = p;

	if (argno < 16)
	    argv[argno++] = p;
	else
	    break;

	while (*p != ' ' && *p != '\0') p++;
	if (*p == ' ') *(p++) = '\0';
	while (*p == ' ') p++;
    }
    argv[argno] = NULL;

    v = vfork ();

    switch (v) {
        case PARENT:
	    pgid = getpgrp (0);
	    childpid = v;
	    childRunning = 1;
	    toolReadyStatus = 1;
	    signal (SIGCHLD, int_hdl);
	    readSigMes = 2;
	    left = 0;
	    mon_cnt = 0;
	    while (childRunning) {

		/* This loop may be exited in three ways:
		   1. The child has finished and childRunning has become 0 
		      (due to a SIGCHLD interrupt).
		   2. An event occurred for which checkEvent returned
		      True, e.g. '^C' was typed.
		   3. A fatal IO error occurred (destroyHandler was called
		      when XSync was executed) because the window of simeye
		      has been destroyed.
		*/

		sleep (1);

		/* test on window existance, if window does no longer exists
		   a jump to the destroyHandler will automatically be done */

		XSync (display, False);

		while (XEventsQueued (display, QueuedAfterFlush) > 0) {
		    if (left)
			ev = &event;
		    else
			ev = &leaveEvent;
		    XNextEvent (display, ev);
		    if (ev -> type == Expose) {
			XtDispatchEvent (ev);   /* for redrawing menu buttons */
		    }
		    if (ev -> type == ConfigureNotify) {
			XtDispatchEvent (ev);   /* for resizing widgets */
		    }
		    if (ev -> type == LeaveNotify && !left) { 
			left = 1;
		    }
		    if (checkEvent (display, ev, NULL) == True) {

			/* the tool is stopped by an interrupt from simeye */
		    
			/* kill all processes of the process group, except
			   simeye itself */

			signal (SIGTERM, SIG_IGN);
			kill (-pgid, SIGTERM); 
			signal (SIGTERM, int_hdl);

			toolReadyStatus = -1;
			break;
		    }
		}

		mon_cnt++;
		if (monitorSig == 1 && childRunning && mon_cnt == probe_time) {
		    if (readSignals (0, readSigMes)) {
			readSigMes = 1;
		    }
		    mon_cnt = 0;
		}
	    }
	    if (left > 0) {
		XPutBackEvent (display, &leaveEvent);  
					   /* for updating RUN button */
	    }
	    if (monitorSig != -1 && errorInFile (outFile)) 
		toolReadyStatus = 1;
	    else if (monitorSig == 1 && readSigMes == 1)
		readSignals (0, -1);  /* end intermediate reading */
	    else if (monitorSig != -1)
		readSignals (0, 0);   /* normal (single) read */
            break;
        case CHILD:
	    /* attach stdout and stderr to "outFile" */
	    freopen (outFile, "w", stdout);
	    freopen (outFile, "w", stderr);
            execvp (path, argv);
            _exit (1);
            break;
        case ERROR:
            return (1);
            break;
    }

    return (toolReadyStatus);
}

int errorInFile (fn)
char *fn;
{
     FILE *fp;
     char buf[256];
     int simulation = 0;

     if (fp = fopen (fn, "r")) {
	 while (fscanf (fp, "%s", buf) > 0) {
	     if (simulation && strcmp (buf, "aborted") == 0) {
		 fclose (fp);
		 return (1);
	     }
	     if (strcmp (buf, "simulation") == 0) simulation = 1;
	     else simulation = 0;
	 }
	 fclose (fp);
	 return (0);   /* OK */
     }

     return (1);    
}

Bool checkEvent (display, event, arg)
Display *display;
XEvent *event;
char *arg;
{
    char buf[32];
    int bufnr = 32;
    KeySym keysym;
    XComposeStatus status;

    if (event -> type == KeyPress) {
	buf[0] = '\0';
	XLookupString (event, buf, bufnr, &keysym, &status);

        if (buf[0] == '\003'  /* ^C */
	|| (buf[0] == 'c' && (event -> xkey.state & ControlMask))) 
	    return (True);
    }

    return (False);
}

initIntrup ()
{
    int int_hdl ();

    if (signal (SIGINT, SIG_IGN) != SIG_IGN)   
        signal (SIGINT, int_hdl);
        /* only when value was not SIG_IGN, a jump must be done to int_hdl */
    if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
        signal (SIGQUIT, int_hdl);
        /* only when value was not SIG_IGN, a jump must be done to int_hdl */
    signal (SIGTERM, int_hdl);
    signal (SIGILL, int_hdl);
    signal (SIGFPE, int_hdl);
#ifdef SIGBUS
    signal (SIGBUS, int_hdl);
#endif
    signal (SIGSEGV, int_hdl);
#ifdef __linux /* for some unknown reason, we receive unexpected SIGALRMs on linux ... */
    signal (SIGALRM, int_hdl);
#endif
}

int_hdl (sig)   /* interrupt handler */
int sig;
{
    int status;

    switch (sig) {
        case SIGILL :
            fprintf (stderr, "Illegal instruction\n");
            break;
        case SIGFPE :
            fprintf (stderr, "Floating point exception\n");
            break;
#ifdef SIGBUS
        case SIGBUS :
            fprintf (stderr, "Bus error\n");
            break;
#endif
        case SIGSEGV :
            fprintf (stderr, "Segmentation violation\n");
            break;
	case SIGCHLD :
	    signal (SIGCHLD, SIG_DFL);
	    if (childRunning) {
		(void) wait (&status);
		if (toolReadyStatus != -1)
		    toolReadyStatus = (status? 1: 0);  
		/* else it was 'stopped' from simeye */
		childRunning = 0;
	    }
	    break;
#ifdef __linux
        case SIGALRM:
            signal (SIGALRM, int_hdl);
            return 0; /* just ignore this alarm signal (where does it come from ????) */
#endif
        default :
	    if (childRunning > 0) {
		childRunning = 0;
		/* kill all processes with the same process group id */
		kill (-pgid, SIGTERM);  
	    }
            break;
    }

    if (sig != SIGCHLD)
	die (1);
}

void die (status)
int status;
{
    if (status == 0 && projKey)
	dmCloseProject (projKey, COMPLETE);
    dmQuit();
    exit (status);
}
