static char *SccsId = "@(#)edit.c 4.12 (TU-Delft) 01/13/93";
/**********************************************************

Name/Version      : simeye/4.12

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 <dmincl.h>
#include <sys/types.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"

extern Widget commands;
extern Widget canvasbd;
extern Widget total;
extern Widget toplevel;
extern Widget zoomoutw;

extern Widget clickedCommandw;
extern int commandType;

extern char inputname[];

extern DM_CELL *input_stimuli_key;

extern long curr_time;
extern int simperiod;

int editing = 0;
struct signal *storedSig = NULL;
long storedT1;
long storedT2;
struct sig_value *storedVals = NULL;

int somethingChanged;

Widget editcommands;
Widget unitw;
Widget newsigw;
Widget delsigw;
Widget clearallw;
Widget copysigw;
Widget changew;
Widget yankw;
Widget putbufw;
Widget speedw;
Widget t_endw;
Widget returnw;

#define NR_BUTTON  11

void enableEditing ()
{
    int n;
    Grid butWidth;
    Grid butHeight;
    Grid butSep;
    Grid butBD;
    Grid butDist;
    Grid butRest;
    Grid editWidth;
    Grid editHeight;
    Grid editVertDist;

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

    void Unit ();
    void Newsig ();
    void Delsig ();
    void Clearall ();
    void Copysig ();
    void Change ();
    void Yank ();
    void Speed ();
    void T_end ();
    void Put ();
    void Return ();

    if (editing)
        return;

    editing = 1;
    somethingChanged = 0;

    n = 0;
    XtSetArg (args[n], XtNwidth, 0), n++;
    XtSetArg (args[n], XtNheight, 0), n++;
    XtSetArg (args[n], XtNy, 0), n++;
    XtSetArg (args[n], XtNborderWidth, 0), n++;
    XtGetValues (zoomoutw, args, n);

    butHeight = args[1].value;
    butSep = args[2].value;
    butBD = args[3].value;

    n = 0;
    XtSetArg (args[n], XtNwidth, 0), n++;
    XtSetArg (args[n], XtNheight, 0), n++;
    XtSetArg (args[n], XtNvertDistance, 0), n++;
    XtSetArg (args[n], XtNborderWidth, 0), n++;
    XtGetValues (canvasbd, args, n);

    editWidth = args[0].value;
    editHeight = butHeight + 2 * butSep + 2 * butBD;
    editVertDist = args[2].value;

    XtResizeWidget (canvasbd, 
                args[0].value, 
	        args[1].value - editHeight - args[2].value - 2 * args[3].value, 
                args[3].value);

    callbacks[1].callback = NULL;

    n = 0;
    XtSetArg (args[n], XtNfromVert, canvasbd), n++;
    XtSetArg (args[n], XtNvertDistance, editVertDist), n++;
    XtSetArg (args[n], XtNwidth, editWidth), n++;
    XtSetArg (args[n], XtNheight, editHeight), n++;
    XtSetArg (args[n], XtNdefaultDistance, butSep), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    editcommands = XtCreateManagedWidget ("commands", formWidgetClass, total, 
				          args, n);

    butWidth = (editWidth - (NR_BUTTON + 1) * butSep - NR_BUTTON * 2 * butBD) 
								   / NR_BUTTON;
    butDist = butSep;
    butRest = (editWidth - 2 * butSep - NR_BUTTON * (butWidth + 2 * butBD)) 
              - butDist * (NR_BUTTON - 1);

    callbacks[0].callback = Unit;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    unitw = XtCreateManagedWidget ("grid", commandWidgetClass, 
				   editcommands, args, n);

    if (butRest == 10) butDist++;

    callbacks[0].callback = Newsig;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, unitw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    newsigw = XtCreateManagedWidget ("new", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 9) butDist++;

    callbacks[0].callback = Delsig;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, newsigw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    delsigw = XtCreateManagedWidget ("delete", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 8) butDist++;

    callbacks[0].callback = Clearall;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, delsigw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    clearallw = XtCreateManagedWidget ("clear", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 7) butDist++;

    callbacks[0].callback = Copysig;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, clearallw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    copysigw = XtCreateManagedWidget ("copy", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 6) butDist++;

    callbacks[0].callback = Change;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, copysigw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    changew = XtCreateManagedWidget ("edit", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 5) butDist++;

    callbacks[0].callback = Yank;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, changew), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    yankw = XtCreateManagedWidget ("yank", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 4) butDist++;

    callbacks[0].callback = Put;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, yankw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    putbufw = XtCreateManagedWidget ("put", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 3) butDist++;

    callbacks[0].callback = Speed;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, putbufw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    speedw = XtCreateManagedWidget ("speed", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 2) butDist++;

    callbacks[0].callback = T_end;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, speedw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    t_endw = XtCreateManagedWidget ("t_end", commandWidgetClass, 
				     editcommands, args, n);

    if (butRest == 1) butDist++;

    callbacks[0].callback = Return;
    n = 0;
    XtSetArg (args[n], XtNcallback, callbacks), n++;
    XtSetArg (args[n], XtNwidth, butWidth), n++;
    XtSetArg (args[n], XtNheight, butHeight), n++;
    XtSetArg (args[n], XtNfromHoriz, t_endw), n++;
    XtSetArg (args[n], XtNhorizDistance, butDist), n++;
    XtSetArg (args[n], XtNborderWidth, butBD), n++;
    returnw = XtCreateManagedWidget ("ready", commandWidgetClass, 
				     editcommands, args, n);

    XtRealizeWidget (editcommands);
}

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

    commandType = UNIT;
    beginCommand (w);
}

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

    if (Timescaling <= 0) {
	windowMessage ("enter grid first", -1);
	return;
    }

    commandType = NEWSIG;
    beginCommand (w);
}

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

    commandType = DELSIG;
    beginCommand (w);
}

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

    if (Begin_signal) {
	commandType = CLEARALL;
	beginCommand (w);
    }
}

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

    commandType = COPYSIG;
    beginCommand (w);
}

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

    commandType = CHANGE;
    beginCommand (w);
}

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

    commandType = YANK;
    beginCommand (w);
}

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

    if (storedVals == NULL) {
	windowMessage ("empty buffer", -1);
    }
    else {
	commandType = PUT;
	beginCommand (w);
    }
}

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

    commandType = SPEED;
    beginCommand (w);
}

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

    commandType = TEND;
    beginCommand (w);
}

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

    commandType = WRITE;
    beginCommand (w);
}

void disableEditing ()
{
    int n;
    Grid sum;
    Arg args[15];

    if (storedVals) {
        delSigval (storedVals);
	storedVals = NULL;
    }
    storedSig = NULL;

    n = 0;
    XtSetArg (args[n], XtNheight, 0), n++;
    XtGetValues (total, args, n);

    sum = args[0].value;

    n = 0;
    XtSetArg (args[n], XtNvertDistance, 0), n++;
    XtSetArg (args[n], XtNheight, 0), n++;
    XtSetArg (args[n], XtNborderWidth, 0), n++;
    XtGetValues (commands, args, n);

    sum = sum - args[0].value - args[1].value - 2 * args[2].value;

    XtUnmanageChild (editcommands);
    XtDestroyWidget (editcommands);

    n = 0;
    XtSetArg (args[n], XtNwidth, 0), n++;
    XtSetArg (args[n], XtNheight, 0), n++;
    XtSetArg (args[n], XtNvertDistance, 0), n++;
    XtSetArg (args[n], XtNborderWidth, 0), n++;
    XtGetValues (canvasbd, args, n);

    XtResizeWidget (canvasbd, 
                    args[0].value, 
                    sum - 2 * (args[2].value + args[3].value), 
                    args[3].value);

    editing = 0;
}

struct sig_value * changeSignal (sig, t1, t2, s, prev)
struct signal * sig;
long t1, t2;
int s;
struct sig_value * prev;   /* previous sig_value (if known !) */
{
    int after2value;
    struct sig_value * sval;
    struct sig_value * tmp;
    struct sig_value * new1;
    struct sig_value * new2;
    struct sig_value * before1;
    struct sig_value * before2;
    struct sig_value * prev_ret;
    long help;
    void delSigexpr ();

    if (t1 == t2)
        return (prev);

    if (sig -> expr) {

        /* the periodicity of the signal is destroyed */

	delSigexpr (sig -> expr);   
	sig -> expr = NULL;
	sig -> endless = 0;
    }

    somethingChanged = 1;

    if (t2 < t1) {
        help = t1;
        t1 = t2;
        t2 = help;
    }

    if (sig == storedSig 
    && ((t1 > storedT1 && t1 < storedT2) || (t2 > storedT1 && t2 < storedT2))) {

	storedSig = NULL;  /* since it is changed the signal is no longer
			      a representative for the contents of the buffer */
    }

    before1 = NULL;

    if (prev)
	sval = prev;      /* use prev to speed up searching process ! */
    else
        sval = sig -> begin_value;

    prev_ret = prev;

    while (sval && sval -> time < t1) {
        before1 = sval;
	prev_ret = sval;
        sval = sval -> next;
    }

    /* if (before1 && sval) then: before1 -> next == sval */

    if (!before1 || before1 -> value != s) {

        NEW (new1, 1, struct sig_value);
        if (!sig -> begin_value)
           new1 -> time = 0;
        else
           new1 -> time = t1;
        new1 -> value = s;
        new1 -> next = sval;
        if (sval)
            sval -> prev = new1;
        new1 -> prev = before1;

        if (!before1) {
            if (!sig -> begin_value) {
                sig -> begin_value = new1;
                sig -> end_value = new1;
            }
            else {
                sig -> begin_value = new1;
            }
            after2value = s;
        }
        else {
            before1 -> next = new1;
            after2value = before1 -> value;
        }
        before2 = new1;
    }
    else {
        /* else a previous sval already has a value 's': */
        /*  before1 && before1 -> value == s             */

        before2 = before1;
        after2value = s;
    }

    while (sval && sval -> time <= t2) {

        /* delete everything with t1 <= time <= t2 */

        after2value = sval -> value;
        tmp = sval;
        sval = sval -> next;

        if (tmp -> next)
            tmp -> next -> prev = tmp -> prev;
        else
            sig -> end_value = tmp -> prev;

        if (tmp -> prev)
            tmp -> prev -> next = tmp -> next;
        else
            sig -> begin_value = tmp -> next;

        DELETE (tmp);
    }

    if (sval && sval -> value == s && after2value == s)
        return (prev_ret);                  

    if (before2 && before2 -> prev 
    && before2 -> value == before2 -> prev -> value) {

        before2 -> time = t2;
    }
    else {

        NEW (new2, 1, struct sig_value);
        new2 -> time = t2;
        if (sval)
            new2 -> value = after2value;
        else
            new2 -> value = s;

        new2 -> next = sval;
        if (sval)
            sval -> prev = new2;
        else
            sig -> end_value = new2;
        new2 -> prev = before2;
        if (before2)
            before2 -> next = new2;
    }

    if (t2 > Endtime)
        Endtime = t2;
    if (t2 > SimEndtime)
	SimEndtime = t2;

    return (prev_ret);
}

void copySignal (sig1, sig2)
struct signal *sig1;
struct signal *sig2;
{
    struct sig_value *sval1;
    struct sig_value *sval2;
    struct sig_value *newval;
    SIGNALELEMENT *sigel;
    SIGNALELEMENT *last_sigel;
    SIGNALELEMENT *new_sigel;
    char flag;

    if (sig1 == sig2)
        return;

    somethingChanged = 1;

    delSigval (sig2 -> begin_value);
    sig2 -> begin_value = NULL;
    sig2 -> end_value = NULL;

    delSigexpr (sig2 -> expr);
    sig2 -> expr = NULL;

    sval2 = NULL;
    sval1 = sig1 -> begin_value;
    while (sval1) {

        NEW (newval, 1, struct sig_value);
        newval -> time = sval1 -> time;
        newval -> value = sval1 -> value;
        newval -> next = NULL;
        newval -> prev = sval2;

        if (sval2)
            sval2 -> next = newval;
        else
            sig2 -> begin_value = newval;

        sval2 = newval;

        sval1 = sval1 -> next;
    }
    sig2 -> end_value = sval2;

    sigel = sig1 -> expr;
    while (sigel) {
        NEW (new_sigel, 1, SIGNALELEMENT);
	new_sigel -> val = sigel -> val;
	new_sigel -> len = sigel -> len;
	if (sig2 -> expr) {
	    if (flag == 'c')
		last_sigel -> child = new_sigel;
	    else
		last_sigel -> sibling = new_sigel;
	}
	else
	    sig2 -> expr = new_sigel;
	last_sigel = new_sigel;

        if (sigel -> child) {
	    flag = 'c';
	    sigel = sigel -> child;
	}
	else {
	    flag = 's';
	    sigel = sigel -> sibling;
	}
    }

    sig2 -> endless = sig1 -> endless;
}

void storeSignalPart (sig, t1, t2)
struct signal *sig;
long t1;
long t2;
{
    long help;
    struct sig_value *sval;
    struct sig_value *newval;
    struct sig_value *lastval;

    if (t1 == t2) {
	return;
    }

    if (t1 > t2) {
	help = t2;
	t2 = t1;
	t1 = help;
    }

    if (storedVals) {
        delSigval (storedVals);
	storedVals = NULL;
    }

    sval = sig -> begin_value;
    while (sval && sval -> time <= t1) {
	sval = sval -> next;
    }

    if (sval) sval = sval -> prev;

    while (sval && sval -> time < t2) {
	NEW (newval, 1, struct sig_value);
	newval -> time = Max (t1, sval -> time);
	newval -> value = sval -> value;
	newval -> next = NULL;
	if (storedVals == NULL) {
	    storedVals = newval;
	    lastval = newval;
	}
	else {
	    lastval -> next = newval;
	    lastval = newval;
	}
	sval = sval -> next;
    }

    storedSig = sig;
    storedT1 = t1;
    storedT2 = t2;
}

void addStoredSignalPart (sig, t, factor)
struct signal *sig;
long t;
int factor;
{
    int i;
    struct sig_value *sval;
    struct sig_value *help;  
             /* help is used to assure a linear complexity of this function */
    SIGNALELEMENT *new_sig_el;
    SIGNALELEMENT *last_sig_el;
    SIGNALELEMENT *new_part;
    long t1;
    long t2;
    int sval2eval ();
    struct sig_value *changeSignal ();
    void delSigexpr ();

    if (!storedVals)
	return;     /* empty buffer */

    if (factor < 0) {    /* an endless part is added: use 'sig -> expr' 
					    to store the periodical part */

	if (sig == storedSig && t < storedT2) {

	    storedSig = NULL;  /* since it is changed the signal is no longer
				  a representative for the contents of the 
				  buffer */
	}

	/* delete old expr */

	delSigexpr (sig -> expr);

	NEW (sig -> expr, 1, SIGNALELEMENT);
	sig -> expr -> child = NULL;
	sig -> expr -> sibling = NULL;
	sig -> expr -> len = -1;
	sig -> endless = 1;

	last_sig_el = sig -> expr;

	/* create expr until t */

	sval = sig -> begin_value;
	t1 = 0;
	while (sval && t1 < t) {
	    if (sval -> time > t1) {
		NEW (new_sig_el, 1, SIGNALELEMENT);
		new_sig_el -> child = NULL;
		new_sig_el -> sibling = NULL;
		new_sig_el -> val = sval2eval (sval -> prev -> value);
		if (sval -> time < t)
		    new_sig_el -> len = sval -> time - t1;
		else
		    new_sig_el -> len = t - t1;

		last_sig_el -> sibling = new_sig_el;
		last_sig_el = new_sig_el;

		t1 = sval -> time;
	    }
	    sval = sval -> next;
	}

	/* add contents of buffer to expr */

	NEW (new_part, 1, SIGNALELEMENT);
	new_part -> sibling = NULL;
	new_part -> len = -1;

	NEW (new_part -> child, 1, SIGNALELEMENT);
	new_part -> child -> child = NULL;
	new_part -> child -> sibling = NULL;
	new_part -> child -> len = storedT2 - storedT1;

	last_sig_el -> sibling = new_part;

	last_sig_el = new_part -> child;

	sval = storedVals;
	while (sval) {
	    t1 = sval -> time - storedT1 + t;
	    if (sval -> next)
		t2 = sval -> next -> time - storedT1 + t;
	    else
		t2 = storedT2 - storedT1 + t;
	    NEW (new_sig_el, 1, SIGNALELEMENT);
	    new_sig_el -> child = NULL;
	    new_sig_el -> sibling = NULL;
	    new_sig_el -> val = sval2eval (sval -> value);
	    new_sig_el -> len = t2 - t1;

	    last_sig_el -> sibling = new_sig_el;
	    last_sig_el = new_sig_el;

	    sval = sval -> next;
	}
   
	sig -> expr -> val =
        new_part -> val = 
	new_part -> child -> val = last_sig_el -> val;

        /* update sig values */

	delSigval (sig -> begin_value);
	sig -> begin_value = NULL;
	sig -> end_value = NULL;
	curr_time = 0;
	simperiod = SimEndtime;
	addSgnPart (sig, sig -> expr, 1);

	adjustSgnPart (sig);

	somethingChanged = 1;

	return;
    }

    help = NULL;

    i = 0;
    while (i < factor) {
	sval = storedVals;
	while (sval) {
	    t1 = sval -> time - storedT1 + t;
	    if (sval -> next)
		t2 = sval -> next -> time - storedT1 + t;
	    else
		t2 = storedT2 - storedT1 + t;
	    t1 = t1 + i * (storedT2 - storedT1);
	    t2 = t2 + i * (storedT2 - storedT1);
	    help = changeSignal (sig, t1, t2, sval -> value, help);
	    sval = sval -> next;
	}
	i++;
    }
}

int sval2eval (v)
int v;
{
    switch (v) {
	case 0:
	    return (L_state);
	case 1:
	    return (X_state);
	case 2:
	    return (H_state);
	case -1:
	    return (Free_state);
    }

    return (X_state);
}

int writeSet (filename)
char *filename;
{
    char buf[128];
    char tmpfilename[128];
    char help[128];
    char outbuf[128];
    FILE *fp1;
    FILE *fp2;
    char *w;
    int cnt;
    char state;
    char prevstate;
    long duration;
    struct signal *sig;
    struct sig_value *sval;
    int sigunitPre, sigunitNow, sigunitDone;
    int simperiodPre, simperiodNow, simperiodDone;
    int goOn;
    int backslash;
    int copycommand;
    long firstcharpos;
    char c;
    struct signal *sigfollow;
    struct signalelement *sigel;
    int getStringFromUser ();
    DM_STREAM *dsp_cmd;
    char *getword ();
    int compareWord ();
    char eval2cmdval ();
    struct signal *existSignal ();

    sigfollow = Begin_signal;
    while (sigfollow != NULL) {
	if (sigfollow -> begin_value == NULL) {
	    windowMessage ("description has unspecified signal(s)", -1);
	    return (0);
	}
	sigfollow = sigfollow -> next;
    }

    sprintf (tmpfilename, "%d.cxx", getpid ());

    if (use_io_views) {
	dsp_cmd = dmOpenStream (input_stimuli_key, "cmd", "r"); 
	fp1 = dsp_cmd -> dmfp;
    }
    else
	fp1 = fopen (filename, "r");
    
    if ((fp2 = fopen (tmpfilename, "w")) == NULL) {
	sprintf (help, "Cannot open %s", tmpfilename);
	windowMessage (help, -1);
	return (0);
    }

    /* first copy fp1 to fp2 but 
       without 'editable' set commands
       and options sigunit and simperiod changed to their correct value */

    sigunitDone = 0;
    simperiodDone = 0;

    if (fp1) {

	while ((c = getc (fp1)) != EOF) {

	    /* read command by command */

            ungetc (c, fp1);

	    firstcharpos = ftell (fp1);

	    while ((c = getc (fp1)) == ' ' || c == '\t');

            copycommand = 0;

	    if (c == 's' && getc (fp1) == 'e' && getc (fp1) == 't' 
		&& ((c = getc (fp1)) == ' ' || c == '\t' || c == '\\')) {

		while ((c = getc (fp1)) != '=') {
		    if (c == 'n') {
		        if ((c = getc (fp1)) == 'o' 
		            && (c = getc (fp1)) == '_' 
		            && (c = getc (fp1)) == 'e' 
		            && (c = getc (fp1)) == 'd' 
		            && (c = getc (fp1)) == 'i' 
		            && (c = getc (fp1)) == 't') {

			    /* It is a set command with 'no_edit',
			       copy only if (1) the command is disabled,
			       or (2) the signal still exists in the program
			       as 'non-editable'
			    */

			    while ((c = getc (fp1)) == ' ');
			    if (c == '*' && (c = getc (fp1)) == '#') {
				copycommand = 1;            /* case (1) */
			    }
			    else {
				fscanf (fp1, "%s", buf);
				sig = existSignal (buf);
				if (sig && sig -> no_edit)
				    copycommand = 1;         /* case (2) */
			    }

			    break;    
			}
			else {
			    ungetc (c, fp1);
			}
		    }
		}
	    }
	    else {
		copycommand = 1;    /* it is no set command */
	    }

	    fseek (fp1, firstcharpos, 0);

	    sigunitPre = 0, sigunitNow = 0;
	    simperiodPre = 0, simperiodNow = 0;

	    backslash = 0;
	    goOn = 1;
	    while (goOn) {

		w = getword (fp1);

		if (sigunitNow && w[0] != '\\') {
		    fprintf (fp2, "%le ", Timescaling);
		    sigunitNow = 0;
		    sigunitDone = 1;
		}
		else if (simperiodNow && w[0] != '\\') {
		    fprintf (fp2, "%ld ", SimEndtime);
		    simperiodNow = 0;
		    simperiodDone = 1;
		}
		else if (copycommand && w[0] != EOF) {
		    fprintf (fp2, "%s", w);
		}

                if (sigunitPre) {
		    if (w[0] == '=') {
		        sigunitNow = 1;
		        sigunitPre = 0;
		    }
		    else if (w[0] != '\\')
		        sigunitPre = 0;
		}
                if (simperiodPre) {
		    if (w[0] == '=') {
		        simperiodNow = 1;
		        simperiodPre = 0;
		    }
		    else if (w[0] != '\\')
		        simperiodPre = 0;
		}

		if (compareWord (w, "sigunit"))
		    sigunitPre = 1;
		if (compareWord (w, "simperiod"))
		    simperiodPre = 1;
		    
		if ((w[0] == '\n' && !backslash) || w[0] == EOF)
		    goOn = 0;

		if (w[0] == '\\') 
		    backslash = 1;
		else if (w[0] != ' ' && w[0] != '\t' 
				     && !(w[0] == '\n' && backslash))
		    backslash = 0;
	    }
	}
	if (use_io_views)
	    dmCloseStream (dsp_cmd, COMPLETE);
	else
	    fclose (fp1);
    }

    if (!sigunitDone)
        fprintf (fp2, "option sigunit = %le\n", Timescaling);
    if (!simperiodDone)
        fprintf (fp2, "option simperiod = %ld\n", SimEndtime);

    /* then write new set commands to fp2 */

    sig = Begin_signal;
    while (sig != NULL) {

        if (sig -> no_edit) {
	    sig = sig -> next;
	    continue;
	}

        sprintf (outbuf, "set %s = ", sig -> name);

        cnt = strlen (outbuf);
        fprintf (fp2, outbuf);

        if (sig -> endless) {
	    sigel = sig -> expr;
	    if (sigel)
		sigel = sigel -> sibling;
	    while (sigel && sigel -> sibling) {
		state = eval2cmdval (sigel -> val);
		sprintf (outbuf, "%c*%ld ", state, sigel -> len);

		if (cnt + strlen (outbuf) > 80 - 2) {
		    fprintf (fp2, " \\\n     ");
		    cnt = 5;
		}
		cnt = cnt + strlen (outbuf);
		fprintf (fp2, outbuf);

		sigel = sigel -> sibling;
	    }
	    if (sigel && sigel -> child && sigel -> child -> sibling) {
		sigel = sigel -> child -> sibling;

		if (cnt + 1 > 80 - 2) {
		    fprintf (fp2, " \\\n     ");
		    cnt = 5;
		}
		fprintf (fp2, "(");

		while (sigel) {
		    state = eval2cmdval (sigel -> val);
		    sprintf (outbuf, "%c*%ld ", state, sigel -> len);

		    if (cnt + strlen (outbuf) > 80 - 2) {
			fprintf (fp2, " \\\n     ");
			cnt = 5;
		    }
		    cnt = cnt + strlen (outbuf);
		    fprintf (fp2, outbuf);

		    sigel = sigel -> sibling;
		}

		if (cnt + 3 > 80) {
		    fprintf (fp2, " \\\n     ");
		    cnt = 5;
		}
		fprintf (fp2, ")*~");
	    }
	    fprintf (fp2, "\n");

	    sig = sig -> next;
	    continue;
	}

        sval = sig -> begin_value;
        while (sval != NULL) {

            if (sval -> value == 0)
                state = 'l';
            else if (sval -> value == 1)
                state = 'x';
            else if (sval -> value == 2)
                state = 'h';
            else if (sval -> value == -1)
                state = 'f';

            if (sval -> next) {
                duration = sval -> next -> time - sval -> time;
                if (duration == 0)
                    outbuf[0] = '\0';
                else
                    sprintf (outbuf, "%c*%ld ", state, duration);
            }
            else {
                if (prevstate == state)
                    outbuf[0] = '\0';
                else
                    sprintf (outbuf, "%c", state);
            }

            if ((sval -> next && cnt + strlen (outbuf) > 80 - 2)
                || (!sval -> next && cnt + strlen (outbuf) > 80)) {
                fprintf (fp2, " \\\n     ");
                cnt = 5;
            }
            cnt = cnt + strlen (outbuf);
            fprintf (fp2, outbuf);

            prevstate = state;

            sval = sval -> next;
        }

        fprintf (fp2, "\n");

        sig = sig -> next;
    }

    fclose (fp2);
    
    /* finally move tmpfile to file */

    if (use_io_views) {
#if NCF_RELEASE >= 400
	dmMoveFileToStream (input_stimuli_key, tmpfilename, "cmd");
#endif
	dmCheckIn (input_stimuli_key, COMPLETE);
	input_stimuli_key = NULL;
    }
    else
	sprintf (help, "mv %s %s", tmpfilename, filename);

    system (help);

    sprintf (buf, "\"%s\" ready", filename);
    windowMessage (buf, -1);

    return (1);
}

char *getword (fp)
FILE *fp;
{
    static char buf[256];
    int i;
    char c;

    /* a word is 
       1. the character '\n' 
       2. the string "/ *", "* /" (space = nil) "#*" or "*#", possibly 
	  preceded by one of the characters '\\' or '=', or by an 
	  identifier string containing none of the characters '\\', '\n' 
	  or '=' or the strings "/ *", "* /", "#*" or "*#".
       3. a string of blanks (' ' or '\t'), possibly preceded by one 
	  of the characters '\\' or '=', or by an identifier string 
	  containing none of the characters '\\', '\n' or '='
	  or the strings "/ *" or "* /", "#*" or "*#".
    */

    c = getc (fp);
    if (c == '\n' || c == EOF) {
	buf[0] = c;
	buf[1] = '\0';
	return (buf);
    }
    i = 0;
    if (c != ' ' && c != '\t') {
	buf[i++] = c;
	if (c != '\\' && c != '\n' && c != '=' && c != EOF) {
	    c = getc (fp);
	    while (c != ' ' && c != '\t'
		   && !((c == '/' || c == '#') && buf[i-1] == '*')
		   && !(c == '*' && (buf[i-1] == '/' || buf[i-1] == '#'))
		   && c != '\\' && c != '\n' && c != '=' && c != EOF
		   && i < 256) {
		buf[i++] = c;
		c = getc (fp);
	    }
	}
	else {
	    c = getc (fp);
	}
    }

    if (((c == '/' || c == '#') && buf[i-1] == '*') 
      || (c == '*' && (buf[i-1] == '/' || buf[i-1] == '#'))) {

	buf[i++] = c;
    }
    else {

	while ((c == ' ' || c == '\t') && i < 256) {
	    buf[i++] = c;
	    c = getc (fp);
	}

	if (c != EOF)
	    ungetc (c, fp);
    }

    buf[i] = '\0';

    return (buf);
}

int compareWord (w1, w2)
char *w1;
char *w2;
{
    int i = 0;

    while (w1[i] == w2[i] && w2[i] != '\0') {
	i++;
    }

    if (w2[i] == '\0' 
	&& (w2[i] == '\0' || w2[i] == ' ' || w2[i] == '\t')) {
	return (1);    /* match */
    }
    else {
	return (0);    /* no match */
    }
}

char eval2cmdval (v)
int v;
{
    switch (v) {
	case L_state:
	    return ('l');
	case X_state:
	    return ('x');
	case H_state:
	    return ('h');
	case Free_state:
	    return ('f');
    }

    return ('x');
}
