[comp.windows.x] xsplot - a SPICE plotting program for X V10.4

bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)

xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE 
output.  It will drive an HP-GL plotter for hardcopy.  It can be used to look
at non-SPICE data, also.  Why, it could be the Neatest Thing Ever.  Probably
not, though.

Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and
4.3, and on random Vaxen under Ultrix 1.2 and 2.0)

  --John Bradley  -  University of Pennsylvania  -  bradley@cis.upenn.edu

Part 1 of 4
------------------------cut here-----------------------------------------
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -d ./xsplot`
then
  mkdir ./xsplot
  echo "mkdir ./xsplot"
fi
if `test ! -s ./xsplot/xsplotio.c`
then
echo "writing ./xsplot/xsplotio.c"
cat > ./xsplot/xsplotio.c << '\Rogue\Monster\'
/************************************************************************/
/* SPLOTIO.C								*/
/*----------------------------------------------------------------------*/
/* Library of routines to handle file i/o, spice parsing.		*/
/*----------------------------------------------------------------------*/
/* int   OpenFiles   (fname);						*/
/* int   OpenSpice   ();						*/
/* int   LoadNewAnal (anum);						*/
/* int	 LoadAnal    (anum);						*/
/* int   expfname    (name);						*/
/* int   killtmps    ();						*/
/* char* FixName     (name);						*/
/************************************************************************/


#include "xsplot.h"
#include <pwd.h>

static char *homedir;
char *getenv();

static char outfname[128];
static FILE *outfile;

static int NOPAGE;	/* whether or not the NOPAGE option has been set */

static char pst[256];	/* used for printf's */

/************************************************************************/
char *FixName(name)
        char *name;
{
    /* returns file name (strips off directory names)
       (ie:  "/usr/fish/beebo/crap" returns "crap") */
 
    char *sp;
     
    sp = rindex(name,'/');
    if (sp) return sp+1;   
       else return name;
}

/************************************************************************/
static char *tfname(buf,i)
char *buf;
int i;
{
    sprintf(buf,"/tmp/S%ld.%s.t%d",pid,FixName(outfname),i);
    return(buf);
}


/************************************************************************/
killtmps()
{
    /* kills all '.tn' files created by this process.  Called when quitting */

    extern int errno;

    sprintf(pst,"rm -f /tmp/S%ld.*",pid);
    system(pst);  /* yeah, I'm pretty embarrassed about it, too... */
}


/************************************************************************/
int OpenFiles()
{
    homedir = getenv("HOME");  if (homedir == NULL) homedir = ".";

    if (OpenSpice()) Quit();
    LoadNewAnal(0);
}


/************************************************************************/
int OpenSpice()
{   
    int i,err;

    strcpy(outfname,basfname);

    if (expfname(outfname)) {
        sprintf(pst,"ERROR: unable to open '%s'",outfname);
        ErrBox(pst,3);
        return 1;
        }

/*  strcat(outfname,".out"); */

    NOPAGE=0;
    outfile = fopen(outfname,"r");
    if (outfile==0) {
        sprintf(pst,"ERROR: unable to open '%s'",outfname);
        ErrBox(pst,3);
        return 1;
        }

    err=MakeTmpFiles();
    fclose(outfile);
    return(err);
}
	

/************************************************************************/
static int MakeTmpFiles()
    /* parses .OUT file into files (one file per analysis) */
    /* also loads up the anals array with stuff */

{
    int i,j,k,done,err;
    FILE *tmpfile;
    char linebuf[255], tmpfname[80];
    float tdat[MYPERANAL+1];
    Anal *ap;

    if (FindAnals())    return 1;
    if (Anals2Labs())   return 1;
    ConvertAnals();

    if (NOPARSE) return 0;

    sprintf(pst,"Parsing file '%s'.  Please wait.",outfname);
    ErrBox(pst,1);
    rewind(outfile);

    for (i=0; i<numanals; i++) {        /* for each analysis... */
        ap = &anals[i];

        tfname(tmpfname,i);
        sprintf(pst,"Writing tmp file '%s':  ",tmpfname);
        ErrBox(pst,1);

        if ( (tmpfile=fopen(tmpfname,"w"))==0) {
            sprintf(pst,"ERROR: Unable to create '%s'",tmpfname);
            ErrBox(pst,3);
            return 1;
            }

        if (FindDStart(ap->type)) {     /* go to beginning of data */
            fclose(tmpfile);
            return 1;
            }

        numpts = done = 0;
        putw(numpts,tmpfile);           /* write a dummy value for numpts */

        while (!done) {                 /* write the data to the tmp file */
            /* read a line of data */
            for (j=0; j<ap->numys+1; j++) {
                done = done || (fscanf(outfile,"%s",linebuf)==-1);
                tdat[j]=atof(linebuf);
                if (tdat[j]==0.0) {
                    if (linebuf[0]!='0') done=1;   /* read a non-numeric */
                    else if (strcmp(linebuf,"0.")==0) 
                        /* some Fortran comps print '0.0' as '0.   e00',
                           which fools scanf, hence the second fscanf */
                        fscanf(outfile,"%*s");
                    }
                }

            if (!done) {
                numpts++;
                if (numpts % 20==0) {
                    sprintf(pst,"Writing tmp file '%s':  %4d points",
                            tmpfname,numpts);
                    ErrBox(pst,0);
                    }
                fwrite(tdat,sizeof(float),ap->numys+1,tmpfile);
                }
            }

        rewind(tmpfile);                /* fill in the right val for numpts */
        putw(numpts,tmpfile);
        fclose(tmpfile);

        sprintf(pst,"Writing tmp file '%s':  %4d points",tmpfname,numpts);
        ErrBox(pst,0);
        ap->numpts = numpts;

        } /* repeat for each tmpfile/analysis */

    return 0;
}


/************************************************************************/
static int FindAnals()
/* reads the input listing.  copies lines starting with .PRINT to 
   analtitle fields in anals array.  Also notes whether the NOPAGE
   option has been set */
{
    char linebuf[256],*err;
    char a[5][20];
    int  i;


    rewind(outfile);
    numanals=0;

    while (fgets(linebuf,256,outfile)==linebuf) {
        a[0][0]='\0';
        sscanf(linebuf,"%s %s %s %s %s",a[0],a[1],a[2],a[3],a[4]);
        for (i=0; i<5; i++) a[i][19]='\0';

        if (strncmp(a[0],".OPT",4)==0) {
            for (i=1; i<5; i++) 
                if (strcmp("NOPAGE",a[i])==0) NOPAGE=1;
            }

        else if (strcmp(a[0],".PRINT")==0) {
            /* clear out previous title (yes, it's necessary) */
            for (i=0; i<80; i++) anals[numanals].title[i]=' ';
            strncpy(anals[numanals].title,linebuf,80);
            numanals++;
            if (numanals==MAXANAL) numanals--;
            }

        else if (strcmp(a[0],".END")==0) break;
        }
    return 0;
}


/************************************************************************/
static int Anals2Labs()
    /* takes anals array and gets the labels from the titles */
    /* labs[0] is filled in automatically by ConvertAnals */
{
    int i,j,c,done;
    Anal *ap;

    if (!numanals) {
        sprintf(pst,"Unable to find any analyses in this spice file.  Loading aborted");
        ErrBox(pst,4);
        return 1;
        }
	
   for (i=0; i<numanals; i++) {
       ap = &anals[i];  /* pointer to cut down on indirection calcs */

       /* clear old labels */
       for (j=1; j<=MYPERANAL; j++) ap->labels[j][0]='\0';

       /* split the ".PRINT" line into args, tossing first two */
       sscanf(ap->title,"%*s %*s %s %s %s %s %s %s %s %s\n",
              ap->labels[1], ap->labels[2], ap->labels[3], ap->labels[4], 
              ap->labels[5], ap->labels[6], ap->labels[7], ap->labels[8]);

       /* numys = (count arguments) */
       for (j=1; j<=MYPERANAL; j++) {
           c = ap->labels[j][0];
           if (!isalpha(c)) break;
           }
       ap->numys=j-1;
       }
    return 0;
}


/************************************************************************/
static ConvertAnals()
/* take anals array and convert the titles to something approaching english */
{
    int i;
    char atype[80];

    for (i=0; i<numanals; i++) {
        sscanf(anals[i].title,"%*s %s",atype);  /* atype=analysis type */

        if      (strcmp(atype,"AC")==0) {
                    strcpy(anals[i].title,"AC Analysis");
                    strcpy(anals[i].labels[0],"FREQ");
                    anals[i].type=AC;
                    }

        else if (strcmp(atype,"DC")==0) {
                    strcpy(anals[i].title,"DC Analysis");
                    strcpy(anals[i].labels[0],"VIN");
                    anals[i].type=DC;
                    }

        else if (strcmp(atype,"TRAN")==0) {
                    strcpy(anals[i].title,"Transient Analysis");
                    strcpy(anals[i].labels[0],"TIME");
                    anals[i].type=TRANS;
                    }
        else { 
            sprintf(pst,"ERROR: Unrecognized analysis '%s'",anals[i].title);
            ErrBox(pst,3);
            }
        }
}


/************************************************************************/
static int FindDStart(type)
int type;
/* searches outfile for header, leaving fp pointing at first data line */
{
    int i,j,numpts,done;
    char linebuf[256],*err,word1[80],word2[80],title[256];

    /* remove up to and including title line */

    while (1) {
        if ( (err=fgets(linebuf,256,outfile)) != linebuf) break;
        if (linebuf[1]=='*' && linebuf[5]==' ') {    /* likely to be a title */
            sscanf(linebuf,"%*s %s %s",word1,word2);
            sprintf(title,"%s %s",word1,word2);
            if (strcmp(title,SpTitle[type])==0) break;
            }
        }

    if (err!=linebuf) {         /* error occurred */
        sprintf(pst,"ERROR: Unable to find '%s'.\n",SpTitle[type]);
        ErrBox(pst,4);
        return 1;
        }

    if (NOPAGE==1) SkipLines(5);   /* skip from title to beginning of data */
              else SkipLines(8);
    return 0;
}
	


/************************************************************************/
LoadNewAnal(anum)
int anum;
/* loads an analysis, setting the 'Choose Curves' info to likely values  */
{
    int   i;

    numy   = min(anals[anum].numys,4);
    for (i=0; i<4; i++) ind[i]=i;
    LoadAnal(anum);
    curanal=anum;
}


/************************************************************************/
int LoadAnal(anum)
int anum;
/* loads an analysis, using current 'Choose Curves' info */
{
    int   i,j;
    FILE  *tmpfile;
    char  linebuf[80],tmpfname[80];
    float tmp[MYPERANAL];

    tfname(tmpfname,anum);

    sprintf(pst,"Reading tmp file '%s'",tmpfname);
    ErrBox(pst,1);

    if ( (tmpfile=fopen(tmpfname,"r"))==0) {
        sprintf(pst,"ERROR: Unable to open %s\n",tmpfname);
        ErrBox(pst,4);
        return 1;
        }

    theAnal = &anals[anum];
    numpts = theAnal->numpts = getw(tmpfile);

    if (numpts>MAXPTS) numpts=MAXPTS;

    for (i=0; i<numpts; i++) {
        fread(xlist.dat+i,sizeof(float),1,tmpfile);

        /* read a line from the file */
        fread(tmp,sizeof(float),theAnal->numys,tmpfile);
        for (j=0; j<numy; j++) ylist[j].dat[i]=tmp[ind[j]];
        }

    fclose(tmpfile);

    /* copy the labels from the anal to the dlists */
    strcpy(xlist.label,theAnal->labels[0]);
    for (i=0; i<numy; i++) {
       strcpy(ylist[i].label,theAnal->labels[ind[i]+1]);
       }

    /* figure out what the units should be */
    switch (theAnal->type) {
        case DC:    units[0]="V";  break;
        case AC:    units[0]="Hz"; break;
        case TRANS: units[0]="S";  break;
        }

    for (i=0; i<numy; i++) {
        char *st;

        /* force label to ALL CAPS */
        for (st=ylist[i].label; toupper(*st)!='\0'; st++);
        st=ylist[i].label;

        if (strncmp(st,"VDB",3)==0) {               /* dB's */
                units[i+1]="dB";
                }
        else if (strncmp(st,"VP",2)==0) {           /* Degrees */
                units[i+1]=DEGSTR;
                }
        else if (*st == 'V') {                      /* Volts */
                units[i+1]="V";
                }
        else if (*st == 'I') {                      /* Amps */
                units[i+1]="A";
                }
        else units[i+1]="";
        }
    ErrBox("",0);
    return 0;
}


/***************************************************************************/
static int SkipLines(i)
int i;
/* reads (and ignores) 'i' lines from outfile */
{
    char linebuf[255];
    for (; i>0; i--) fgets(linebuf,255,outfile);
}


/**************************************************************************/
int expfname(fname)
       char *fname;
{
    /* expands ~s in file names.  Returns the name in 'name', returns 0 if
       okay, 1 if error occurred (user name not found) */

    struct passwd *entry;
    char *cp, *sp, *up, uname[64], tmp[256];

    if (*fname != '~') return 0; /* doesn't start with a tilde, don't expand */

    /* look for the first '/' after the tilde */
    sp = index(fname,'/');
    if (sp == 0) return 1;       /* no '/' after the tilde.  Invalid fname */

    /* uname equals the string between the ~ and the / */
    for (cp=fname+1,up=uname; cp<sp; *up++ = *cp++);
    *up='\0';

    if (*uname=='\0') { /* no name.  substitute ~ with $HOME */
        strcpy(tmp,homedir);
        strcat(tmp,sp);
        }
    else {              /* get password entry for uname */
        entry = getpwnam(uname);
        if (entry==0) return 1;       /* name not found */
        strcpy(tmp,entry->pw_dir);
        strcat(tmp,sp);
        endpwent();
        }
    strcpy(fname,tmp);  /* return expanded file name */
    return 0;
}


\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplotio.c"
fi
if `test ! -s ./xsplot/xsplotmac.c`
then
echo "writing ./xsplot/xsplotmac.c"
cat > ./xsplot/xsplotmac.c << '\Rogue\Monster\'
/************************************************************************/
/* xsplotmac.c  -  Macintosh-like stuff, random graphic routines,	*/
/*			window/subwindow/button creation/redraw		*/
/*----------------------------------------------------------------------*/
/* InvTitleBar     ();							*/
/* DrawTitleBar    ();							*/
/* CreateMainWindow(name,geom);						*/
/* CreateSubwindows();							*/
/* CreateStuff     ();							*/
/* CreateButtons   ();							*/
/* MakeButton      (bnum,win,x,y,w,h,st)				*/
/* MakeCB          (bnum,win,x,y);					*/
/* MapButtons      ();							*/
/* RedrawIcon      ();							*/
/* RedrawBut       (bnum);						*/
/* RedrawCB        (bnum);						*/
/* RedrawPanel     (w,wwidth,str);					*/
/* RedrawOffPan    ();							*/
/* InvertBut       (bnum);						*/
/* DrawArrs        ();							*/
/* DashLine        (window,x1,y1,x2,y2,color,pattern);			*/
/* SetVertex       (vert,x,y,flags);					*/
/* MakeRect        (x1,y1,x2,y2);					*/
/* Frame           (win,x1,y1,x2,y2,width,color,func);			*/
/************************************************************************/


#include "xsplot.h"

#include "cursor"         /* nnw arrow cursor */
#include "cursor.mask"    /*    and mask      */
#include "cursx"          /* small x-shaped   */
#include "cursx.mask"     /* cursor and mask  */
#include "icon"           /* program icon     */
#include "titlebar.bm"    /* titlebar bitmap  */
#include "arrows.h"       /* bitmaps for trace location arrows */

/* checkerboard used in mono mode */
static short stip_bits[] = {
   0x5555, 0xaaaa, 0x5555, 0xaaaa,
   0x5555, 0xaaaa, 0x5555, 0xaaaa,
   0x5555, 0xaaaa, 0x5555, 0xaaaa,
   0x5555, 0xaaaa, 0x5555, 0xaaaa};

/* cross-weave bitmap */
static short chek_bits[] = {
   0x5555, 0x8888, 0x5555, 0x2222,
   0x5555, 0x8888, 0x5555, 0x2222,
   0x5555, 0x8888, 0x5555, 0x2222,
   0x5555, 0x8888, 0x5555, 0x2222};

/* 75% gray */
static short dkgray_bits[] = {
   0xaaaa, 0xffff, 0xaaaa, 0xffff,
   0xaaaa, 0xffff, 0xaaaa, 0xffff,
   0xaaaa, 0xffff, 0xaaaa, 0xffff,
   0xaaaa, 0xffff, 0xaaaa, 0xffff};


/***********************************/
InvTitleBar()
{
    tbInvert = !tbInvert;

    if (tbInvert) {
        if (mono) XChangeBackground(titleW,gridBpix);
             else XChangeBackground(titleW,mainBpix);
        }
    else XChangeBackground(titleW,mainFpix);

    XClear(titleW);
    DrawTitleBar();
}

/***********************************/
DrawTitleBar()
{
    int i, cfore, cback;

    if (tbInvert) 
        XPixmapPut(titleW,0,0,(WIDTH-titlebar_width)/2,0,titlebar_width, 
                   titlebar_height, titlePixInv, GXcopy, AllPlanes);
    else
        XPixmapPut(titleW,0,0,(WIDTH-titlebar_width)/2,0,titlebar_width, 
                   titlebar_height, titlePix, GXcopy, AllPlanes);
}


/***********************************/
CreateMainWindow(name,geom)
           char *name,*geom;
{
    char default_geom[20];
    OpaqueFrame frame;
    
    sprintf (default_geom, "%dx%d+%d+%d",WIDTH,HEIGHT,
               (DisplayWidth()-WIDTH)/2,(DisplayHeight()-HEIGHT)/2);

    frame.bdrwidth   = 2;
    frame.border     = mainFpix;
    frame.background = mainBpix;

    mainW = XCreate("xSplot",name,geom,default_geom,&frame,WIDTH,HEIGHT);

    if (!mainW) FatalError("Can't open main window");

}

/***********************************/
CreateSubwindows()
{
   iconW =XCreateWindow(RootWindow,0,0,icon_width,icon_height,0,0,mainBpix);
   titleW=XCreateWindow(mainW,-1,-1,WIDTH,20,1,mainFpix,mainFpix);
   gridW =XCreateWindow(mainW,15-5,50-5,GSIZE+3,GSIZE+3,3,mainFpix,gridBpix);

   presetW = XCreateWindow(mainW,PREX,PREY,PREW,PREH,1,panFpix, panBpix);
   traceW  = XCreateWindow(mainW,TRAX,TRAY,TRAW,TRAH,1,panFpix, panBpix);
   scaleW  = XCreateWindow(mainW,SCAX,SCAY,SCAW,SCAH,1,panFpix, panBpix);
   measureW= XCreateWindow(mainW,MSRX,MSRY,MSRW,MSRH,1,panFpix, panBpix);
   offsetW = XCreateWindow(mainW,OFFX,OFFY,OFFW,OFFH,1,panFpix, panBpix);
   commandW= XCreateWindow(mainW,OFFX,OFFY,OFFW,OFFH,1,panFpix, panBpix);
   modifyW = XCreateWindow(mainW,MODX,MODY,MODW,MODH,1,panFpix, panBpix);
   miscW   = XCreateWindow(mainW,MISX,MISY,MISW,MISH,1,panFpix, panBpix);

   errW    = XCreateWindow(mainW,10,HEIGHT-23,WIDTH-20,13,1,errFpix,errBpix);
   diversW = XCreateWindow(mainW,115-4,100-4,200,300,3,dlgFpix,dlgBpix);

   LoadDlog=  XCreateWindow(mainW,25-3, 150,380,100,3,dlgFpix,dlgBpix);
   SwitchDlog=XCreateWindow(mainW,115-3,150,200,100,3,dlgFpix,dlgBpix);
   CurvDlog=  XCreateWindow(mainW,115-3,100,200,300,3,dlgFpix,dlgBpix);
   PlotDlog=  XCreateWindow(mainW,25-3, 175,380,70, 3,dlgFpix,dlgBpix);
   PlotNDlog= XCreateWindow(mainW,25-3, 160,380,100,3,dlgFpix,dlgBpix);
   HelpDlog=  XCreateWindow(mainW,25-3, 125,380,200,3,dlgFpix,dlgBpix);
   AboutDlog =XCreateWindow(mainW,15-4,50-4,GSIZE,GSIZE,3,mainFpix,gridBpix);

   XSelectInput(iconW, ExposeWindow);
   XSelectInput(titleW,ExposeWindow|ButtonPressed);
   XSelectInput(gridW, ExposeWindow|ButtonPressed|ButtonReleased);

   XSelectInput(presetW,  ExposeWindow);
   XSelectInput(traceW,   ExposeWindow);
   XSelectInput(scaleW,   ExposeWindow);
   XSelectInput(measureW, ExposeWindow);
   XSelectInput(offsetW,  ExposeWindow);
   XSelectInput(modifyW,  ExposeWindow);
   XSelectInput(miscW,    ExposeWindow);
   XSelectInput(commandW, ExposeWindow);
   XSelectInput(errW,     ExposeWindow);
   XSelectInput(diversW,  ExposeWindow);

   XSelectInput(LoadDlog,  ExposeWindow|ButtonPressed);
   XSelectInput(SwitchDlog,ExposeWindow|ButtonPressed);
   XSelectInput(CurvDlog,  ExposeWindow|ButtonPressed);
   XSelectInput(PlotDlog,  ExposeWindow|ButtonPressed);
   XSelectInput(PlotNDlog, ExposeWindow|ButtonPressed);
   XSelectInput(HelpDlog,  ExposeWindow|ButtonPressed);
   XSelectInput(AboutDlog, ExposeWindow|ButtonPressed);
}


/***********************************/
CreateStuff()
{
    Bitmap tmpBits;
    int i;

    tmpBits     = XStoreBitmap(titlebar_width,titlebar_height,titlebar_bits);
    titlePix    = XMakePixmap (tmpBits,mainFcol,mainBcol);
    titlePixInv = XMakePixmap (tmpBits,mainBcol,mainFcol);
    XFreeBitmap(tmpBits);

    if (mono) {  /* panels and main background are stippled in mono mode */
        tmpBits     = XStoreBitmap(16,16,stip_bits);
        panBpix     = XMakePixmap(tmpBits,ForeColor,BackColor);
        XFreeBitmap(tmpBits);
    
        tmpBits     = XStoreBitmap(16,16,chek_bits);
        mainBpix    = XMakePixmap(tmpBits,ForeColor,BackColor);
        XFreeBitmap(tmpBits);
        }

    else {       /* but solid color in color mode */
        panBpix = XMakeTile(panBcol);
        mainBpix= XMakeTile(mainBcol);
        }
        
    gridFpix = XMakeTile(gridFcol);
    gridBpix = XMakeTile(gridBcol);
    panFpix  = XMakeTile(panFcol);
    butFpix  = XMakeTile(butFcol);
    butBpix  = XMakeTile(butBcol);
    mainFpix = XMakeTile(mainFcol);
    dlgFpix  = XMakeTile(dlgFcol);
    dlgBpix  = XMakeTile(dlgBcol);
    errFpix  = XMakeTile(errFcol);
    errBpix  = XMakeTile(errBcol);
    for (i=0; i<4; i++)
        trpix[i] = XMakeTile(trcol[i]);

    leftmask    = XStoreBitmap(arr_width,arr_height,arrl_mask_bits);
    rightmask   = XStoreBitmap(arr_width,arr_height,arrr_mask_bits);
    upmask      = XStoreBitmap(arr_width,arr_height,arru_mask_bits);
    downmask    = XStoreBitmap(arr_width,arr_height,arrd_mask_bits);

    if (mono) {
        linepats[0]=XMakePattern(0xffff,16,1);    
        linepats[1]=XMakePattern(0xaaaa,16,1);    
        linepats[2]=XMakePattern(0xcccc,16,1);    
        linepats[3]=XMakePattern(0xbbbb,16,1);
        }

    RBoxPat[0]=XMakePattern(0xc0,8,2);
    RBoxPat[1]=XMakePattern(0x30,8,2);
    RBoxPat[2]=XMakePattern(0x0c,8,2);
    RBoxPat[3]=XMakePattern(0x03,8,2);

    GridPat2=XMakePattern(PAT2,16,1);
    GridPat4=XMakePattern(PAT4,16,1);

    arrow=XCreateCursor(cursor_width,cursor_height,cursor_bits,
        cursor_mask_bits,cursor_x_hot,cursor_y_hot,mainFcol,mainBcol,GXcopy);

    cursx=XCreateCursor(cursx_width,cursx_height,cursx_bits,
        cursx_mask_bits,cursx_x_hot,cursx_y_hot,mainFcol,mainBcol,GXcopy);
}


/***********************************/
CreateButtons()
{
#define BH 19

    int i;

    MakeButton(&butts[ 0],scaleW,24,16,     68,BH,"linear",butfinfo);
    MakeButton(&butts[ 1],scaleW,24,16+BUTH,68,BH,"linear",butfinfo);

    for (i=0; i<5; i++) {
        MakeButton(&butts[i*2+2],offsetW,60,   16+BUTH*i,65,BH,"",butfinfo);
        MakeButton(&butts[i*2+3],offsetW,60+70,16+BUTH*i,65,BH,"",butfinfo);
        }
	
    MakeButton(&butts[12],modifyW,5, 16,       87,BH,"Reset",butfinfo);
    MakeButton(&butts[13],modifyW,5, 16+BUTH,  41,BH,"<-",   butfinfo);
    MakeButton(&butts[14],modifyW,51,16+BUTH,  41,BH,"->",   butfinfo);
    MakeButton(&butts[15],modifyW,5, 16+BUTH*2,41,BH,"<<-",  butfinfo);
    MakeButton(&butts[16],modifyW,51,16+BUTH*2,41,BH,"->>",  butfinfo);
    MakeButton(&butts[17],modifyW,5, 16+BUTH*3,41,BH,"<<<-", butfinfo);
    MakeButton(&butts[18],modifyW,51,16+BUTH*3,41,BH,"->>>", butfinfo);

    MakeButton(&butts[22],miscW,5,16,       87,BH,"Commands",butfinfo);
    MakeButton(&butts[21],miscW,5,16+BUTH,  87,BH,"Y-Lock",  butfinfo);
    MakeButton(&butts[20],miscW,5,16+BUTH*2,87,BH,"Undo",    butfinfo);
    MakeButton(&butts[19],miscW,5,16+BUTH*3,87,BH,"Redraw",  butfinfo);

    MakeButton(&butts[25],commandW,5,   16,       190,BH,"Load Data File", butfinfo);
    MakeButton(&butts[24],commandW,5,   16+BUTH,  190,BH,"Switch Analysis",butfinfo);
    MakeButton(&butts[26],commandW,5,   16+BUTH*2,92, BH,"Curves",         butfinfo);
    MakeButton(&butts[23],commandW,5+98,16+BUTH*2,92, BH,"Big Picture",    butfinfo);
    MakeButton(&butts[38],commandW,5,   16+BUTH*3,92, BH,"Plot",           butfinfo);
    MakeButton(&butts[39],commandW,5+98,16+BUTH*3,92, BH,"Help",           butfinfo);
    MakeButton(&butts[27],commandW,5,   16+BUTH*4,92, BH,"Digital",        butfinfo);
    MakeButton(&butts[37],commandW,5+98,16+BUTH*4,92, BH,"Quit",           butfinfo);

    MakeButton(&butts[28],presetW,5,    16,15,BH,"1",  butfinfo);
    MakeButton(&butts[29],presetW,5+20, 16,15,BH,"2",  butfinfo);
    MakeButton(&butts[30],presetW,5+40, 16,15,BH,"3",  butfinfo);
    MakeButton(&butts[31],presetW,5+60, 16,15,BH,"4",  butfinfo);
    MakeButton(&butts[32],presetW,5+80, 16,15,BH,"5",  butfinfo);
    MakeButton(&butts[33],presetW,5+100,16,15,BH,"6",  butfinfo);
    MakeButton(&butts[34],presetW,5+120,16,15,BH,"7",  butfinfo);
    MakeButton(&butts[35],presetW,5+140,16,15,BH,"8",  butfinfo);
    MakeButton(&butts[36],presetW,5+160,16,30,BH,"Set",butfinfo);

    MakeCB(0,measureW,5,      16);
    MakeCB(1,measureW,5+CBW+5,16);
    MakeCB(2,measureW,5,      16+CBH+5);
    MakeCB(3,measureW,5+CBW+5,16+CBH+5);
}

/********************/
MakeButton(bp,win,x,y,w,h,st,bfinf)
       Button   *bp;
       Window   win;
       short    x,y,w,h;
       char     *st;
       FontInfo *bfinf;
/********************/
{   
    bp->win = XCreateWindow(win,x,y,w-4,h-4,2,butFpix,butBpix);
    bp->x   = x+2;
    bp->y   = y+2;
    bp->w   = w-4;
    bp->h   = h-4;
    bp->st  = st;
    bp->invert=0;
    bp->finfo = bfinf;
    XSelectInput(bp->win,ExposeWindow|ButtonPressed|ButtonReleased);
}

/********************/
MakeCB(bnum,win,x,y)
       int    bnum;
       Window win;
       short  x,y;
/********************/
{
    if (mono) 
        CButts[bnum].win = XCreateWindow(win,x,y,CBW-4,CBH-4,2,butFpix,butBpix);
    else
        CButts[bnum].win = XCreateWindow(win,x,y,CBW-4,CBH-4,2,
            butFpix,trpix[bnum]);

    XSelectInput(CButts[bnum].win,ExposeWindow|ButtonPressed);
}

/********************/
MapButtons()
{
    int i;

    for (i=0; i<MAXBUT; i++)
        XMapWindow(butts[i].win);

    for (i=0; i<4; i++)
        XMapWindow(CButts[i].win);
}


/********************/
RedrawIcon()
{
    XBitmapBitsPut(iconW,0,0,icon_width,icon_height,icon_bits,
                     mainFcol,mainBcol,0,GXcopy, AllPlanes);
}


/********************/
RedrawBut(bp)
      Button *bp;
{
    int width, textc, backc;

    width = XStringWidth(bp->st,bp->finfo,0,0);
    
    if (bp->invert) { textc=butBcol;  backc=butFcol; }
               else { textc=butFcol;  backc=butBcol; }

    XClear(bp->win);
    XText(bp->win,(bp->w-width)/2,(bp->h - bp->finfo->height)/2,
          bp->st, strlen(bp->st), bp->finfo->id, textc, backc);
}


/********************/
RedrawCB(bnum)
      int bnum;
{
    int width, textc, backc;
    Window w;

    w = CButts[bnum].win;

    XClear(w);

    if (mono) DashLine(w,1,(CBH-4)/2,CBW-5,(CBH-4)/2,ForeColor,linepats[bnum]);

    if (bnum==selCB) Frame(w,0,0,CBW-5,CBH-5,2,butFcol,GXcopy);

}


/********************/
RedrawPanel(w,wwidth,str)
     Window w;
     int   wwidth;
     char  *str;
{
    static char *gridlab[2]={"X:","Y:"};

    int swidth,i,y;

    swidth = XStringWidth(str,butfinfo,0,0);

    XPixSet(w,0,0,wwidth,11,panFcol);
    XText(w,(wwidth-swidth)/2,0,str,strlen(str),butfont,panBcol,panFcol);

    if      (w==traceW) DrawArrs();
    else if (w==scaleW) {
        for (i=0; i<2; i++) {    /* labels */
            y=16+i*24;
            if (mono) {
                XPixSet(scaleW,5,y,14,19,BackColor);
                XLine  (scaleW,5,y,   18,y,   1,1,ForeColor,GXcopy,AllPlanes);
                XLine  (scaleW,5,y+18,18,y+18,1,1,ForeColor,GXcopy,AllPlanes);
                }

            XTextMask(scaleW,5,y+4,gridlab[i],strlen(gridlab[i]),
                butfont,panFcol);
            }
        }
}


/********************/
RedrawOffPan()
{
#define S1 "Offset"
#define S2 "Range"

    int swidth,i,y;

    XPixSet(offsetW,0,0,OFFW,11,panFcol);
    
    swidth = XStringWidth(S1,butfinfo,0,0);
    XText(offsetW,60+(65-swidth)/2,0,S1,strlen(S1),butfont,panBcol,panFcol);

    swidth = XStringWidth(S2,butfinfo,0,0);
    XText(offsetW,60+70+(65-swidth)/2,0,S2,strlen(S2),butfont,panBcol,panFcol);

    for (i=0; i<=numy; i++) {    /* labels */
        char *st;

        y=16+i*24;
        if (mono) {
            XPixSet(offsetW,5,y,50,19,BackColor);
            XLine(offsetW,5,y,   54,y,   1,1,ForeColor,GXcopy,AllPlanes);
            XLine(offsetW,5,y+18,54,y+18,1,1,ForeColor,GXcopy,AllPlanes);
            }

        if (i) st = ylist[i-1].label;
        else   st = xlist.label;

        if (i) XTextMask(offsetW,5,y+4,st,strlen(st),butfont,trcol[i-1]);
          else XTextMask(offsetW,5,y+4,st,strlen(st),butfont,panFcol);

        if (mono && i) {
            DashLine(offsetW, 6, y+2,  53, y+2,  ForeColor,linepats[i-1]);
            DashLine(offsetW, 6, y+16, 53, y+16, ForeColor,linepats[i-1]);
            }
        }   
}


/********************/
InvertBut(bp)
  Button *bp;
{

    bp->invert = ~(bp->invert);
    
    if (bp->invert) XChangeBackground(bp->win,butFpix); 
               else XChangeBackground(bp->win,butBpix);

    XClear(bp->win);
    RedrawBut(bp);
    XFlush();
}


/*********************/
DrawArrs()
{
    int fc, bc;

    fc=trcol[selCB];  bc=gridBcol;

    if (LeftArr) 
        XBitmapBitsPut(traceW,15,16,arr_width,arr_height,arrl_bits,
                       fc,fc,leftmask,GXcopy,AllPlanes);
    else 
        XBitmapBitsPut(traceW,15,16,arr_width,arr_height,arrl_bits,
                       bc,fc,leftmask,GXcopy,AllPlanes);


    if (RightArr)
        XBitmapBitsPut(traceW,65,16,arr_width,arr_height,arrr_bits,
                       fc,fc,rightmask,GXcopy,AllPlanes);
    else 
        XBitmapBitsPut(traceW,65,16,arr_width,arr_height,arrr_bits,
                       bc,fc,rightmask,GXcopy,AllPlanes);


    if (UpArr[selCB])
        XBitmapBitsPut(traceW,115,16,arr_width,arr_height,arru_bits,
                       fc,fc,upmask,GXcopy,AllPlanes);
    else 
        XBitmapBitsPut(traceW,115,16,arr_width,arr_height,arru_bits,
                       bc,fc,upmask,GXcopy,AllPlanes);


    if (DownArr[selCB])
        XBitmapBitsPut(traceW,165,16,arr_width,arr_height,arrd_bits,
                       fc,fc,downmask,GXcopy,AllPlanes);
    else
        XBitmapBitsPut(traceW,165,16,arr_width,arr_height,arrd_bits,
                       bc,fc,downmask,GXcopy,AllPlanes);

}

/***************************/
DashLine(w,x1,y1,x2,y2,color,pattern)   /* draws a Dashed line in window w */
   Window w;
   short x1,y1,x2,y2;
   int color;
   Pattern pattern;
{
    Vertex verts[2];

    SetVertex(&verts[0],x1,y1,0);
    SetVertex(&verts[1],x2,y2,0);

    XDrawDashed(w,verts,2,1,1,color,pattern,GXcopy,AllPlanes);
}

/****************************/
SetVertex(vert,x,y,flags)
   Vertex *vert;
   short x,y;
   unsigned short flags;
{
    vert->x=x;
    vert->y=y;
    vert->flags=flags;
}


/****************************/
MakeRect(x1,y1,x2,y2)
     int x1,y1,x2,y2;
{
    /* stores the four lines that make the rectangle in the first five
       elements of 'curve', for use with XDraw */

    SetVertex(curve,  x1,y1,0);
    SetVertex(curve+1,x1,y2,0);
    SetVertex(curve+2,x2,y2,0);
    SetVertex(curve+3,x2,y1,0);
    SetVertex(curve+4,x1,y1,0);
}


/****************************/
Frame(win,x1,y1,x2,y2,w,color,func)   /* draws a rectangle of thickness 'w' */
   Window win;                        /* from x1,y1 to x2,y2 */
   short  x1,y1,x2,y2;
   int    color,w,func;
{
    short tmp,wide,high;
    int planes;

    if (func==GXinvert) {
        if (mono) planes=1;
        else planes=selCB+4;
        }
    else planes=AllPlanes;

    /* get x1,y1 to be top left, and x2,y2 to be bot right */
    if (x2<x1) swap(x1,x2,tmp);
    if (y2<y1) swap(y1,y2,tmp);

    if (w==1) {  /* special case for one-pixel thick frames */
        MakeRect(x1,y1,x2,y2);
        XDraw(win,curve,5,1,1,color,func,planes);
        return;
        }

    wide = x2-x1-w+1;
    high = y2-y1-w+1;

    if (wide<1 || high<1) return;   /* can't draw it, don't bother trying */

    /* that done, draw the four rectangles.  note that they must not
       overlap, so that GXinvert can be used */

    XPixFill(win,x1,     y1,     wide,w,   color,0,func,planes); /*top   */
    XPixFill(win,x1+wide,y1,     w,   high,color,0,func,planes); /*right */
    XPixFill(win,x1+w,   y1+high,wide,w,   color,0,func,planes); /*bottom*/
    XPixFill(win,x1,     y1+w,   w,   high,color,0,func,planes); /*left  */
}



\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplotmac.c"
fi
if `test ! -d ./splotter`
then
  mkdir ./splotter
  echo "mkdir ./splotter"
fi
if `test ! -s ./splotter/color.h`
then
echo "writing ./splotter/color.h"
cat > ./splotter/color.h << '\Rogue\Monster\'
/* Color definitions.				*/

#define		NONE		0
#define		RED		1
#define		GREEN		2
#define		BLUE		3
#define		BLACK		4
#define		BROWN		5
#define		ORANGE		6
#define		VIOLET		7
#define		FT_BLACK	8

/* Defined trace color order, a la SPLOT.	*/
#define		FIRST_C		GREEN
#define		SECOND_C	RED
#define		THIRD_C		BLUE
#define		FOURTH_C	ORANGE
\Rogue\Monster\
else
  echo "will not over write ./splotter/color.h"
fi
if `test ! -s ./splotter/lines.h`
then
echo "writing ./splotter/lines.h"
cat > ./splotter/lines.h << '\Rogue\Monster\'
/* Line type data and definitions.		*/

#define		TYPE_MASK	0xffff0000
#define		VAL_MASK	0x0000ffff

#define		SOLID		0x00010000
#define		THICK		0x00020000
#define		DOT_2		0x00040000
#define		DOT_4		0x00080000

int y_divs[] = { 0, SOLID| 40, SOLID| 80, SOLID|120, SOLID|160, THICK|200,
		    SOLID|240, SOLID|280, SOLID|320, SOLID|360, 0 };

int x_divs[7][51] = {
	{	0, SOLID| 40, SOLID| 80, SOLID|120, SOLID|160, THICK|200,
		   SOLID|240, SOLID|280, SOLID|320, SOLID|360, 0 },

	{	0, SOLID|120, SOLID|191, SOLID|241, SOLID|280, SOLID|311,
		   SOLID|338, SOLID|361, SOLID|382, 0			},

	{	0, SOLID| 40, SOLID| 64, SOLID| 80, SOLID| 93, SOLID|104,
		              SOLID|113, SOLID|120, SOLID|127, THICK|133, 
		   SOLID|173, SOLID|197, SOLID|214, SOLID|227, SOLID|237,
		              SOLID|246, SOLID|254, SOLID|261, THICK|267,
		   SOLID|307, SOLID|330, SOLID|347, SOLID|360, SOLID|370,
		              SOLID|379, SOLID|387, SOLID|394, 0 }, 

	{     0,SOLID|19,    SOLID|28,    SOLID|34,    SOLID|38,    THICK|40,
		SOLID|40 +19,SOLID|40 +28,SOLID|40 +34,SOLID|40 +38,THICK|80,
		SOLID|80 +19,SOLID|80 +28,SOLID|80 +34,SOLID|80 +38,THICK|120,
		SOLID|120+19,SOLID|120+28,SOLID|120+34,SOLID|120+38,THICK|160,
		SOLID|160+19,SOLID|160+28,SOLID|160+34,SOLID|160+38,THICK|200,
		SOLID|200+19,SOLID|200+28,SOLID|200+34,SOLID|200+38,THICK|240,
		SOLID|240+19,SOLID|240+28,SOLID|240+34,SOLID|240+38,THICK|280,
		SOLID|280+19,SOLID|280+28,SOLID|280+34,SOLID|280+38,THICK|320,
		SOLID|320+19,SOLID|320+28,SOLID|320+34,SOLID|320+38,THICK|360,
		SOLID|360+19,SOLID|360+28,SOLID|360+34,SOLID|360+38,0},

	{	0, SOLID|120, SOLID|191, SOLID|241, SOLID|280, SOLID|311,
		   SOLID|338, SOLID|361, SOLID|382, 0			},

	{	0, SOLID| 40, SOLID| 64, SOLID| 80, SOLID| 93, SOLID|104,
		              SOLID|113, SOLID|120, SOLID|127, THICK|133, 
		   SOLID|173, SOLID|197, SOLID|214, SOLID|227, SOLID|237,
		              SOLID|246, SOLID|254, SOLID|261, THICK|267,
		   SOLID|307, SOLID|330, SOLID|347, SOLID|360, SOLID|370,
		              SOLID|379, SOLID|387, SOLID|394, 0 }, 

	{     0,SOLID|19,    SOLID|28,    SOLID|34,    SOLID|38,    THICK|40,
		SOLID|40 +19,SOLID|40 +28,SOLID|40 +34,SOLID|40 +38,THICK|80,
		SOLID|80 +19,SOLID|80 +28,SOLID|80 +34,SOLID|80 +38,THICK|120,
		SOLID|120+19,SOLID|120+28,SOLID|120+34,SOLID|120+38,THICK|160,
		SOLID|160+19,SOLID|160+28,SOLID|160+34,SOLID|160+38,THICK|200,
		SOLID|200+19,SOLID|200+28,SOLID|200+34,SOLID|200+38,THICK|240,
		SOLID|240+19,SOLID|240+28,SOLID|240+34,SOLID|240+38,THICK|280,
		SOLID|280+19,SOLID|280+28,SOLID|280+34,SOLID|280+38,THICK|320,
		SOLID|320+19,SOLID|320+28,SOLID|320+34,SOLID|320+38,THICK|360,
		SOLID|360+19,SOLID|360+28,SOLID|360+34,SOLID|360+38,0}
};


\Rogue\Monster\
else
  echo "will not over write ./splotter/lines.h"
fi
if `test ! -s ./splotter/makefile`
then
echo "writing ./splotter/makefile"
cat > ./splotter/makefile << '\Rogue\Monster\'
CFLAGS = -g

splotter: splotter.o
	cc ${CFLAGS} -o splotter splotter.o


splotter.o: scaling.h lines.h plot.h color.h

\Rogue\Monster\
else
  echo "will not over write ./splotter/makefile"
fi
if `test ! -s ./splotter/plot.h`
then
echo "writing ./splotter/plot.h"
cat > ./splotter/plot.h << '\Rogue\Monster\'
#define		pen_up()	fprintf(out, "PU")
#define		pen_down()	fprintf(out, "PD")
#define		plot_to(x, y)	fprintf(out, "PA%d,%d;", x, y)
#define		rplot_to(x, y)	fprintf(out, "PR%d,%d;", x, y)
#define		fplot_to(x, y)	fprintf(out, "PA%f,%f;", x, y)
#define		select_pen(x)	if(pc != x) {fprintf(out, "SP%d;", x); pc = x;}
#define		def_line()	fprintf(out, "LT;")
#define		line_type(x,y)	fprintf(out, "LT%d,%d;", x, y)
#define		clip_set()	fprintf(out, "IW%d,%d,%d,%d;", 0, 0, (int)RBOX_SIZE,\
					(int)RBOX_SIZE)
#define		clip_clear()	fprintf(out, "IW;")
#define		set_slow()	fprintf(out, "VS5;")
#define		set_fast()	fprintf(out, "VS30;")
#define		low_acc()	fprintf(out, "AS1;")
#define		high_acc()	fprintf(out, "AS;")

/* Label functions.					*/
#define		label(l)	fprintf(out, "LB%s\003", l)	
#define		flabel(l)	fprintf(out, "LB%f\003", l)
#define		label_2(m, e)	fprintf(out, "LB%de2^%d\003", m, e)
#define		label_10(m, e)	fprintf(out, "LB%de10^%d\003", m, e)
#define		label_size(s)	fprintf(out, "SR%f,%f;", s, s)
#define		label_origin(s)	fprintf(out, "LO%d;", s)
#define		horiz_label()	fprintf(out, "DI;")
#define		vert_label()	fprintf(out, "DI0,-1;")
\Rogue\Monster\
else
  echo "will not over write ./splotter/plot.h"
fi
if `test ! -s ./splotter/scaling.h`
then
echo "writing ./splotter/scaling.h"
cat > ./splotter/scaling.h << '\Rogue\Monster\'
/* These definitions are for defining paper scaling.
 */

/* Paper space definitions.			*/
#define		BORDER		500.0
#define		RBOX_SIZE	400.0
#define		ADJUST		250.0

/* Tick mark constants.				*/
#define		MINOR_TICK	3
#define		NUM_TICKS	50
#define		TICK_MOD	5
#define		TICK_DIST	(int)(RBOX_SIZE/NUM_TICKS)


/* Misc. scaling definitions.			*/
#define		X_RANGE		(MAXX - MINX)
#define		Y_RANGE		(MAXY - MINY)
#define		BOX_SIZE	(Y_RANGE - 2.0 * BORDER)
#define		G_R		(RBOX_SIZE/BOX_SIZE)
#define		BO_x		( (X_RANGE - BOX_SIZE) / 2.0 + MINX)
#define		BO_y		( (Y_RANGE - BOX_SIZE) / 2.0 + MINY)

/* Scaled P1 and P2 values.			*/
#define		P1Rx		(MINX - BO_x + (asize?0:ADJUST))
#define		P2Rx		(MAXX - BO_x + (asize?0:ADJUST))
#define		P1Ry		(MINY - BO_y - (asize?ADJUST:0))
#define		P2Ry		(MAXY - BO_y - (asize?ADJUST:0))

/* Header labeling constants.			*/
#define		H_LABEL_SIZE	2.0
#define		FNAME_Y		430
#define		ANNAME_Y	415
#define		H_O_TYPE	5

/* Axis labeling constants.			*/
#define		A_LABEL_SIZE	.5
#define		A_O_TYPE	5
#define		CLOSE_OFF	50
#define		FAR_OFF		100
#define		X_OFF		-40
\Rogue\Monster\
else
  echo "will not over write ./splotter/scaling.h"
fi
if `test ! -s ./splotter/splotter.c`
then
echo "writing ./splotter/splotter.c"
cat > ./splotter/splotter.c << '\Rogue\Monster\'
#include	<stdio.h>
#include	"scaling.h"
#include	"plot.h"
#include	"lines.h"
#include	"color.h"

#define		DISPLAY_FILE	"/usr/vlsi/berk/lib/displays"

/* Misc. definitions.				*/
#define		MAX_TRACES	4
#define		MAX_POINTS	900
#define		BUF_SIZE	256

/* Paper size defintions, a la P1 and P2.	*/
/* For A size paper defaults.			*/
float MINY = 320.0;
float MAXY = 7520.0;
float MINX = 80.0;
float MAXX = 10080.0;

int asize = 1;

typedef union f_i{
	float f;
	int i;
} F_I;


typedef struct axis_des {
	F_I offset, range;
} AXIS_DES;


AXIS_DES x_axis_des;

AXIS_DES y_axis_des[MAX_TRACES];

/* Pen color.	*/
int pc;

char * plotter = "plot1";
char f_name[BUF_SIZE];
char an_name[BUF_SIZE];

int grid_type;
int num_traces;

int * traces;
int * x_trace;

int num_read;

FILE * out;
int is_tty;

main(argc, argv)
/* Process command line arguments.
 * Allocate data, open files,
 * call routines.
 */
int argc;
char ** argv;
{
	char * get_display();
	char * in_fname = NULL, * out_fname = NULL;
	char * arg_ptr;		/* Pointer to command args.	*/

	/* Process command line arguments.	*/
	for(argv++; *argv != NULL; argv++)
	    if( *(arg_ptr = *argv) == '-')
		while(*++arg_ptr != '\0')
		    switch(*arg_ptr){
			case 'i':	in_fname = *++argv;
					break;
			case 'o':	out_fname = *++argv;
					break;
			case 'a':	MINX = 80.0;
					MAXX = 10080.0;
					MINY = 320.0;
					MAXY = 7520.0;
					asize = 1;
					break;
			case 'b':	MINX = 620.0;
					MAXX = 15820.0;
					MINY = 80;
					MAXY = 10080;
					asize = 0;
					break;
			case 'p':	plotter = *++argv;
					break;
		    }

	if(in_fname == NULL)
		in_fname = get_display();
	if(strcmp(in_fname, "-"))
			if( freopen(in_fname, "r", stdin) == NULL)
				error("can't open %s\n", in_fname);
	read_data();
#ifdef PDEBUG
	print_data();
#endif
	if(out_fname == NULL){
		char command[BUF_SIZE];

		sprintf(command, "lpr -P%s -J \"%s\" -T \"%s\"",
			plotter, f_name, an_name);
		if((out = popen(command, "w")) == NULL)
			error("pipe error to printer - help\n");
	}
	else	if(strcmp(out_fname, "-")){
			if( (out = fopen(out_fname, "w")) == NULL)
				error("can't open %s\n", out_fname);
		}
	else	out = stdout;
	is_tty = isatty(out->_file);
	if(is_tty)
		init_plot();
	startup();
	set_grid();
	plot_grid();
	label_grid();
	plot_traces();
	label_it();
	select_pen(NONE);
	closeup();
}



char * get_display(str)
{
	char line[BUF_SIZE];
	FILE * f;
	char text_d[BUF_SIZE], disp_d[BUF_SIZE];
	char * ttyname();
	char * tty;

	if((f = fopen(DISPLAY_FILE, "r")) == NULL)
		error("can't open display file %s\n", DISPLAY_FILE);
	if( (tty = ttyname(0)) == NULL )
		error("can't find my ttyname\n");
	while(fgets(line, BUF_SIZE, f) != NULL){
		if(sscanf(line, "%s %s", text_d, disp_d) != 2)
			error("display file format error\n");
		if(!strcmp(text_d, tty)){
			if((tty = (char *)malloc(strlen(disp_d + 1))) == NULL)
				error("memory error\n");
			strcpy(tty, disp_d);
			return(tty);
		}
	}
	error("can't find text %s in display file\n", tty);
}



init_plot()
{
	fprintf(out, "\33.J\33.@1024;2:\33.P1:");
	fprintf(out, "\33.N;19:\33.I300;;17:\33.M;;;10:");
}


startup()
{
		/* Set plotter up.	*/
	fprintf(out, "\33.(RO;DFIP;AP5;");
}


closeup()
{
		/* Close plotter up.	*/
	fprintf(out, "DFPG1;\33.)");
}


set_grid()
{
	fprintf(out, "IP%d,%d,%d,%d;", (int)MINX, (int)MINY,
					(int)MAXX, (int)MAXY);
	fprintf(out, "SC%.2f,%.2f,%.2f,%.2f;", P1Rx*G_R,P2Rx*G_R,P1Ry*G_R,P2Ry*G_R);
}



read_data()
{
	int i;
	int j;
	int * x_ptr, * t_ptr;

	if(gets(f_name) == NULL)
		error("error reading file name\n", 0);
	if(gets(an_name) == NULL)
		error("error reading analysis name\n", 0);
	if(scanf("%d ", &grid_type) != 1)
		error("error reading grid type\n", 0);
	if(scanf("%d ", &num_traces) != 1)
		error("error reading number of traces\n", 0);
	switch(grid_type){
		case 0:	if(scanf("%f %f ", &x_axis_des.offset.f,
					&x_axis_des.range.f) != 2)
				error("error reading x-axis\n");
			break;
		case 1:
		case 2:
		case 3:	if(scanf("10^%d %d ", &x_axis_des.offset.i,
					&x_axis_des.range.i) != 2)
				error("error reading x-axis\n");
			break;
		case 4:
		case 5:
		case 6:	if(scanf("2^%d %d ", &x_axis_des.offset.i,
					&x_axis_des.range.i) != 2)
				error("error reading x-axis\n");
			break;
		default:	error("internal error - help\n");
			break;
		}
	for(i = 0; i < num_traces; i++)
		if( scanf("%f %f ", &y_axis_des[i].offset.f,
			&y_axis_des[i].range.f) != 2)
		error("error reading y-axis\n");
	if( (x_trace = (int *)calloc(MAX_POINTS, sizeof(int))) == NULL)
		error("memory error - help\n", 0);
	if((traces = (int *)calloc(MAX_POINTS*num_traces,sizeof(int))) == NULL)
		error("memory error - help\n", 0);
	for(x_ptr = x_trace, t_ptr = traces, i = 0, num_read = 0;
			i < MAX_POINTS; i++, num_read++, x_ptr++){
		if(scanf("%d ", x_ptr) != 1)
			break;
		for(j = 0; j < num_traces; j++, t_ptr++)
			if(scanf("%d ", t_ptr) != 1)
				error("format error last line\n");
	}
}
 


#ifdef PDEBUG

print_data()
{
	int i;
	int j;

	fprintf(stderr, "%s\n%s\n%d\n%d\n", f_name, an_name, grid_type, num_traces);
	switch(grid_type){
		case 0:	fprintf(stderr, "%f %f\n", x_axis_des.offset.f,
				x_axis_des.range.f);
			break;
		case 1:
		case 2:
		case 3:	fprintf(stderr, "10^%d %d\n", x_axis_des.offset.i,
				x_axis_des.range.i);
			break;
		case 4:
		case 5:
		case 6:	fprintf(stderr, "2^%d %d\n", x_axis_des.offset.i,
				x_axis_des.range.i);
			break;
		default:	error("debug error - help\n");
			break;
		}
	for(i = 0; i < num_traces; i++)
		fprintf(stderr, "%f %f\n", y_axis_des[i].offset.f,
					y_axis_des[i].range.f);
	for(i = 0; i < num_read; i++){
		fprintf(stderr, "%d ", x_trace[i]);
		for(j = 0; j < num_traces; j++)
			fprintf(stderr, "%d ", traces[j][i]);
		fprintf(stderr, "\n");
	}
}

#endif



plot_grid()
{
	int i;
	int coord;
	float f_coord;
	int l_type;
	int sw = 0;
	int *l_ptr;

	set_fast();
	low_acc();

	/* Draw Box.	*/
	select_pen(BLACK);
	plot_to(0,0);
	draw_rbox((int)RBOX_SIZE);
	fplot_to(-.5, -.5);
	draw_rbox((int)RBOX_SIZE + 1);
	plot_to(-1,-1);
	draw_rbox((int)RBOX_SIZE+2);
	
	/* Draw Y grid.	*/
 	for(l_ptr = &y_divs[1]; *l_ptr; l_ptr++){
		coord = VAL_MASK & *l_ptr;
		f_coord = (float)coord;
		l_type = TYPE_MASK & *l_ptr;
		if(!sw){
			plot_to(0, coord);
			fline_to(0.0, f_coord, RBOX_SIZE, f_coord, l_type);
		}
		else{
			plot_to((int)RBOX_SIZE, coord);
			fline_to(RBOX_SIZE, f_coord, 0.0, f_coord, l_type);
		}
		sw = !sw;

	}		
	/* Draw X grid.	*/
	for(l_ptr = &x_divs[grid_type][1]; *l_ptr; l_ptr++){
		coord = VAL_MASK & *l_ptr;
		f_coord = (float)coord;
		l_type = TYPE_MASK & *l_ptr;
		if(!sw){
			plot_to(coord, 0);
			fline_to(f_coord, 0.0, f_coord, RBOX_SIZE, l_type);
		}
		else{
			plot_to(coord, (int)RBOX_SIZE);
			fline_to(f_coord, RBOX_SIZE, f_coord, 0.0, l_type);
		}
		sw = !sw;
	}		

	if(!grid_type){	/* Must do tick marks for linear grid.	*/
		def_line();
		select_pen(BLACK);
		set_slow();
		for(i = 1; i < NUM_TICKS; i++)
			if(i%TICK_MOD){
				plot_to(i*TICK_DIST,
					(int)RBOX_SIZE/2-MINOR_TICK);
				pen_down();
				plot_to(i*TICK_DIST,
					(int)RBOX_SIZE/2+MINOR_TICK);
				pen_up();
			}
			else{  /* don't plot major tick marks */
			}

		for(i = 1; i < NUM_TICKS; i++)
			if(i%TICK_MOD){
				plot_to((int)RBOX_SIZE/2-MINOR_TICK,
					i*TICK_DIST);
				pen_down();
				plot_to((int)RBOX_SIZE/2+MINOR_TICK,
					i*TICK_DIST);
				pen_up();
			}
			else{ /* don't plot major tick marks */
			}
	}
	set_fast();
	high_acc();
}


label_grid()
{
	int i, j;
	int * l_ptr;
	float label_acc, label_inc;
	int m, e;
	int label_loc = X_OFF;

	label_origin(A_O_TYPE);
	label_size(A_LABEL_SIZE);
	vert_label();
	select_pen(BLACK);
	l_ptr = &x_divs[grid_type][1];
	switch(grid_type){
		case 0:	label_inc = x_axis_des.range.f;
			label_acc = x_axis_des.offset.f - 4 * label_inc;
			for(i = 0; i < 9; i++, l_ptr++){
				plot_to(VAL_MASK & *l_ptr, label_loc);
				flabel(label_acc);
				label_acc += label_inc;
			}
			break;
		case 1:	e = x_axis_des.offset.i;
			for(i = 2; i < 10; i++, l_ptr++){
				plot_to(VAL_MASK & *l_ptr, label_loc);
				label_10(i, e);
			}
			break;
		case 2:	e = x_axis_des.offset.i;
			for(i = 0; i < 3; i++, e++)
				for(j = (i?1:2); j < 10; j++, l_ptr++){
					plot_to(VAL_MASK & *l_ptr, label_loc);
					label_10(j, e);
				}
			break;
		case 3: e = x_axis_des.offset.i + 1;
			for(i = 1; i < 10; i++, e++, l_ptr++){
				l_ptr += 4;
				plot_to(VAL_MASK & *l_ptr, label_loc);
				label_10(1, e);
			}
			break;
		case 4:	e = x_axis_des.offset.i;
			for(i = 2; i < 10; i++, l_ptr++){
				plot_to(VAL_MASK & *l_ptr, label_loc);
				label_2(i, e);
			}
			break;
		case 5:	e = x_axis_des.offset.i;
			for(i = 0; i < 3; i++, e++)
				for(j = (i?2:1); j < 10; j++, l_ptr++){
					plot_to(VAL_MASK & *l_ptr, label_loc);
					label_2(j, e);
				}
			break;
		case 6: e = x_axis_des.offset.i + 1;
			for(i = 1; i < 10; i++, e++, l_ptr++){
				l_ptr += 4;
				plot_to(VAL_MASK & *l_ptr, label_loc);
				label_2(1, e);
			}
			break;
	}
}



plot_traces()
{
	int i, j;
	int * t_ptr, * x_ptr, * l_ptr;
	float label_acc, label_inc;
	int label_loc;

	low_acc();
	set_slow();
	label_size(A_LABEL_SIZE);
	label_origin(A_O_TYPE);
	horiz_label();
	for(i = 0; i < num_traces; i++){
		switch(i){
			case 0:	select_pen(FIRST_C);
				break;
			case 1:	select_pen(SECOND_C);
				break;
			case 2:	select_pen(THIRD_C);
				break;
			case 3:	select_pen(FOURTH_C);
				break;
			default:	select_pen(RED);
				break;
		}
		x_ptr = x_trace;
		t_ptr = traces + i;
		plot_to(*x_ptr, *t_ptr);
		pen_down();
		clip_set();
		for(j = 1; j < num_read; j++){
			x_ptr++;
			t_ptr += num_traces;
			plot_to(*x_ptr, *t_ptr);
		}
		for(j -= 2; j >= 0; j--){
			x_ptr--;
			t_ptr -= num_traces;
			plot_to(*x_ptr, *t_ptr);
		}
		clip_clear();
		pen_up();
		switch(i){
			case 0:	label_loc = -CLOSE_OFF;
				break;
			case 1:	label_loc = (int)RBOX_SIZE + CLOSE_OFF;
				break;
			case 2: label_loc = -FAR_OFF;
				break;
			case 3:	label_loc = (int)RBOX_SIZE + FAR_OFF;
				break;
		}
		label_inc = y_axis_des[i].range.f;
		label_acc = y_axis_des[i].offset.f - 4 * label_inc;
		for(l_ptr = &y_divs[1]; *l_ptr; l_ptr++){
			plot_to(label_loc, VAL_MASK & *l_ptr);
			flabel(label_acc);
			label_acc += label_inc;
		}
	}
	high_acc();
	set_fast();
}

 
label_it()
{
	label_size(H_LABEL_SIZE);
	label_origin(H_O_TYPE);
	select_pen(VIOLET);
	plot_to((int)(RBOX_SIZE/2.0), FNAME_Y);
	label(f_name);
	plot_to((int)(RBOX_SIZE/2.0), ANNAME_Y);
	label(an_name);
}


 
draw_rbox(size)
int size;
{
	pen_down();
	rplot_to(size, 0);
	rplot_to(0, size);
	rplot_to(-size, 0);
	rplot_to(0, -size);
	pen_up();
}


line_to(x, y, type)
int x, y, type;
{
	int tpc;
	int slow = 1;
		
	if(type != -1)
		switch(type){
			case DOT_2:	line_type(-2, 1);
					set_slow();
					break;
			case DOT_4:	tpc = pc;
					select_pen(FT_BLACK);
					line_type(-1, 1);
					set_slow();
					break;
			case SOLID:
			default:	def_line();
					slow = 0;
					break;
		}
	pen_down();
	plot_to(x, y);
	pen_up();
	if(type == DOT_4)
		select_pen(tpc);
	if(slow)
		set_fast();
}

fline_to(xf, yf, xt, yt, type)
float xf, yf, xt, yt;
int type;
{
	int tpc;
	int slow = 1;
	
	if(type != -1)
		switch(type){
			case DOT_2:	line_type(-2, 1);
					set_slow();
					break;
			case DOT_4:	tpc = pc;
					select_pen(FT_BLACK);
					line_type(-1, 1);
					set_slow();
					break;
			case SOLID:
			case THICK:
			default:	def_line();
					slow = 0;
					break;
		}
	pen_down();
	if(type == THICK)
		if(xf == xt){	/* Verticla line.	*/
			fplot_to(xf - (float).5, yt);
			fplot_to(xt - (float).5, yt);
			fplot_to(xt, yt);
			fplot_to(xf, yf);
			fplot_to(xf + (float).5, yf);
			fplot_to(xt + (float).5, yt);
		}
		else{	/* Horizontal line.	*/
			fplot_to(xf, yf - (float).5);
			fplot_to(xt, yt - (float).5);
			fplot_to(xt, yt);
			fplot_to(xf, yf);
			fplot_to(xf, yf + (float).5);
			fplot_to(xt, yt + (float).5);
		}
	else	fplot_to(xt, yt);
	pen_up();
	if(type == DOT_4)
		select_pen(tpc);
	if(slow)
		set_fast();
}


error(str, num)
char * str;
int num;
{
	fprintf(stderr, str, num);
	exit(1);
}
\Rogue\Monster\
else
  echo "will not over write ./splotter/splotter.c"
fi
if `test ! -s ./splotter/splotter.l`
then
echo "writing ./splotter/splotter.l"
cat > ./splotter/splotter.l << '\Rogue\Monster\'
.TH SPLOTTER local
.UC 4
.SH NAME
splotter \- plot spif format file (from splot) on HPGL plotters
.SH SYNTAX
.B splotter
[
.B -ioabcr
] [ arguments... ]
.br
.SH DESCRIPTION
.PP
.I Splotter
takes as input a file in
.B spif
format.
.B Spif
is a specialized intermediate file format for plotting
.B SPICE
output.
.B Spif was developed at the
.B Digital
.B Systems
.B Laboratory,
.B University
.B of
.B Pennsylvania.
.B Spif
files are generated by 
.I splot,
a program distributed by the
.B DSL.
.PP
The simplest usage of
.I splotter
is described in this paragraph, and the following paragraphs describe
more advanced features.
To generate
.B spif
files, one must use the
.I plot
command in
.I splot.
For simple operation, select the serial line option from the
.I plot
command.  This will send the
.B spif
file to the text terminal associated with the graphics display that
.I splot
is running on.  So, from the text terminal, type the command
.I 'splotter'.
Then from within
.I splot,
plot to the serial line.  Whatever was on the
.I splot
display window will magically appear at the plotter.  That's all there is
to it.  Please note that this trick only works with text-display pairs that
are hardwired and specified in the file ~cad/lib/displays.
.PP
There are several options to
.I splotter
as follows:
.TP
.B -i
The folowing argument is taken as the input
.B spif
file.  The default is the graphics display specified in ~cad/lib/displays.
.TP
.B -o
The following argument is taken as the output file.  The default is
to spool to the plotter.  The defualt plotter is called 
.I 'plot1'.
.TP
.B -a
.I Splotter
will assume 'A' size paper.  This is the default.
.TP
.B -h
Print a banner page.  If not asserted, the users name - as specified in the
.I gcos
field of the password entry - and time are printed on the plot.  The default
is to not print the banner page.
.TP
.B -b
.I Splotter
will assume 'B' size paper.
.B -a
is the default.
.TP
.B -p
The following argument is taken as the name of the plotter to spool to,
if the
.B -o
option is not used.  The default is
.I 'plot1'.
.TP
.B -c
Do not clip the traces to the grid window.  This option is for plotters
which do not clip properly.  If the plot comes out without the traces,
try this option.  The default is to clip.
.TP
.B -r
The following argument specifies the number of times the traces are drawn.
Each time a trace is drawn, it is drawn forwards and backwards.  The default
is one.
.TP
.B -u
The filename specified by the -i option is unlinked after it is printed.
.PP
.I Splotter
supports a number of environment settings for tailoring it to the user's likes.
The environment variable is called
.I 'SPLOTOPTS'.
It has the form 'option=value,option=value,....'.  Do not use any extra spaces
in the specification.  The following environment options are available:
.TP 10
.B slow
Sets the slow plotter speed for drawing traces.  The acceptable range is
5 to 80 cm/s.  The default is 5.
.TP 10
.B fast
Sets the fast speed for the plotter.  The range is 5 to 80 cm/s.  The default
is 30.
.TP 10
.B penX
Sets the pen color of trace number X.  Legal pens are pen1, pen2, pen3, pen4.
See below for color values. The respective defaults are green, red, blue,
and orange.
.TP 10
.B gridc
Sets the pen color for drawing the grid.  See below for color values.
The default is black.
.TP 10
.B gridl
Sets the pen color for labeling the x-axis of the grid.  See below for color
values.
The default is black.
.TP 10
.B namec
Sets the pen color for drawing the users name and time if the
.B -h
option is not specified.  See below for color values.  The
default is brown.
.TP 10
.B headc
Sets the pen color for drawing the header strings.
These are the name of the file, and the analysis type.
See below for color values.
The default is violet.
.TP 10
.B size
Set the expected paper size.
If 'a' is specified, 'A' size paper is expected.  Otherwise 'B' size paper
is expected.
The default is 'a'.
.PP
The following colors are available: red, green, blue, black, brown, orange, 
and violet.  These pens reside in pen carriage locations 1 to 7, respectively,
for the 
.I HP75xx
plotters.  Two other colors are available.  The color 'none' specifies that no
pen is to be used.  The color 'eight' specifies the pen in carriage position
8.  This color is unspecified.
.PP
As an example, suppose the user does not want a banner page or his name printed
on the plot.  To accomplish this, set
.I SPLOTOPTS
to "namec=none".
.SH FILES
/usr/local/splotter
.br
/usr/local/warmup		pen exerciser
.br
/usr/cad/lib/displays		text-graphic display link file
.SH BUGS AND CAVEATS
.PP
.I Splotter
.B cannot
guarantee the quality of pen traces that come out of the plotter.  To help
warm up the plotter pens, run the program 'warmup' to exercise the pens.
However, 
.B DO
.B NOT
attempt to clean the pens by hand.  If you do, you may be ejected from
the
.B DSL.
Report any bugs to a 
.B DSL
staff member.
.SH SEE ALSO
hplot(local)
.SH AUTHOR
David P. Feldman
.br
Digital Systems Laboratory
.br
University of Pennsylvania
\Rogue\Monster\
else
  echo "will not over write ./splotter/splotter.l"
fi
if `test ! -s ./splotter/README`
then
echo "writing ./splotter/README"
cat > ./splotter/README << '\Rogue\Monster\'
Notes on splotter:

  Splotter is the program that takes data generated by xsplot and plots it.
It will (in theory) drive any HP-GL plotter, though we only have a HP 7550A,
so who knows...  Anyhow, splotter takes the data from xsplot, converts it
to HP-GL commands, and execs 'lpr' to print it on 'plot1'.  This has several
nice features.  One is that queueing is automatically dealt with.  Another is
that lpr allows you to print on remote machines.  For example, on my RT 
workstation, I have the following entry in my /etc/printcap file:

#plotter 'plot1' on dsl
plot1:\
	:lp=:rm=dsl.cis.upenn.edu:rp=plot1:sd=/usr/spool/plot1d

and on 'dsl.cis.upenn.edu' (the VAX that the plotter is hooked to) I've got
the following:

plot1|7550a|hp7550a:\
        :lp=/dev/plot1:sd=/usr/spool/plot1:lf=/usr/adm/plot-log:br#9600:\
        :fs#0x200003:fc#0dffffc:af=/usr/adm/plot.acct:mc#1:sf:sh:\
        :if=/etc/plotif:of=/usr/lib/lpf:

Needless to say, it works.  Your mileage may vary.


Anyhow, regarding the splotter man page, it contains a lot of information
that you won't need to know if you're running xsplot.  (We have versions of
splot running on PCs (EGA and PGA), and they have to go through some extra
steps to get the data up to the host machine.)  If you're running xsplot, and
have splotter installed, you probably will never have to actually run splotter
by hand, as xsplot will do that for you.  However, if you have splotter and
xsplot running on different machines (for whatever reason), all you have to 
know to run it is "splotter -i spiffile".

John Bradley  -  University of Pennsylvania  -  bradley@cis.upenn.edu

P.S.  You may wish to refer any plotter-related questions to the author.
  (David Feldman  -  david@dsl.cis.upenn.edu)  I don't *do* hardware.
\Rogue\Monster\
else
  echo "will not over write ./splotter/README"
fi
echo "Finished archive 1 of 4"
exit

bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)

xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE 
output.  It will drive an HP-GL plotter for hardcopy.  It can be used to look
at non-SPICE data, also.  Why, it could be the Neatest Thing Ever.  Probably
not, though.

Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and
4.3, and on random Vaxen under Ultrix 1.2 and 2.0)

  --John Bradley  -  University of Pennsylvania  -  bradley@cis.upenn.edu

Part 2 of 4
-------------------------cut here----------------------
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -d ./xsplot`
then
  mkdir ./xsplot
  echo "mkdir ./xsplot"
fi
if `test ! -s ./xsplot/xsplotctl.c`
then
echo "writing ./xsplot/xsplotctl.c"
cat > ./xsplot/xsplotctl.c << '\Rogue\Monster\'
/************************************************************************/
/* XSPLOTCTL.C								*/
/*----------------------------------------------------------------------*/
/* Library of routines to handle controls (push buttons)		*/
/*----------------------------------------------------------------------*/
/* void  R2Str	 	 (num);						*/
/* void  O2Str		 (num);						*/
/* void  ModifyBut	 (bnum,ctrl);					*/
/* void  SetXButs        ();						*/
/* void  DrawXButs       ();						*/
/* void  FpToEng         (str,num);					*/
/************************************************************************/


#include "xsplot.h"



/************************************************************************/
R2Str(num)
int num;

/* takes the power and multiplier values and fills in the str and val fields */

{
    Range *rp = &ranges[num];

    strcpy(rp->str,multstr[rp->multiplier]);
    strcat(rp->str,prefix[rp->power]);
    strcat(rp->str,units[num]);

    rp->val=mult[rp->multiplier] * pow(10.0,(double) ((rp->power-4)*3) );
}

	
/************************************************************************/
O2Str(num)
int num;

/* takes the val field and fills in the str field */

{   Offset *op = &offsets[num];
    char tmp[20];
    int i,e;

    FpToEng(tmp,op->val);   /* tmp = 'x.xxxExx' */

    /* find the 'E' part, truncate tmp at that point, and set 'e' = the
       exponent */

    for (i=4; (tmp[i]!='E') && tmp[i]; i++);

    if (!tmp[i]) e=0;   /* was no 'E' */
    else {
        tmp[i]='\0';
        e=atoi(tmp+i+1);
        }

    /* do a quick range check */
    if (e<-12) 
        { op->val=0.0;  strcpy(tmp,"0.000"); e=0; }

    if (e>12 && op->val>0.0)
        { op->val=  999.9e12;  strcpy(tmp,"999.9"); e=12; }

    if (e>12 && op->val<0.0)
        { op->val= -999.9e12;  strcpy(tmp,"-999.9"); e=12; }
    
    /* tack units onto end of string */
    strcat(tmp,prefix[(e/3)+4]);
    strcat(tmp,units[num]);
    strcpy(op->str,tmp);
}

	
/************************************************************************/
ModifyBut(bnum,ctrl)
int bnum;
{
	if      (ctrl==12) Norm(bnum);
	else if (ctrl==13) Neg(bnum,1);
	else if (ctrl==14) Pos(bnum,1);
	else if (ctrl==15) Neg(bnum,2);
	else if (ctrl==16) Pos(bnum,2);
	else if (ctrl==17) Neg(bnum,3);
	else if (ctrl==18) Pos(bnum,3);
}


/************************************************************************/
static Neg(bnum,amount)
int bnum,amount;
{
    int    rnum,i;
    Range  *rp;
    Offset *op;

    /* if it's one of the X controls, and we're non-linear, then deal */
    if ((bnum==2 || bnum==3) && xscal!=LINEAR) ModXCtrl(bnum,-1*amount);


    /* see if it's one of the range controls */
    else if ((bnum==3) || (bnum==5) || (bnum==7) || (bnum==9) || (bnum==11)) {
        rnum=(bnum-3)/2;  rp= &ranges[rnum];
        switch (amount) {
            case 1:  rp->multiplier--;  break;
            case 2:  rp->multiplier-=3; break;
            case 3:  rp->power--;       break;
            }

        /* adjust things */
        if (rp->multiplier<0) {
            rp->multiplier+=9;
            rp->power--;
            }

        if (rp->power<0) {
            rp->power = rp->multiplier = 0;
            }

        R2Str(rnum);
        butts[bnum].st = rp->str;
        RedrawBut(&butts[bnum]);
        }


    /* see if it's one of the offset controls */
    else if ((bnum==2) || (bnum==4) || (bnum==6) || (bnum==8) || (bnum==10)) {
        if (ylock && bnum!=2) {
            for (i=1; i<=numy; i++) ModOffset(i,-1*amount);
            }
        else {
            rnum=(bnum-2)/2;
            ModOffset(rnum,-1*amount);
            }
        }

    /* see if it's the X Grid Control */
    else if (bnum==0) {
        xscal=(xscal+2) % 3;
        butts[bnum].st=scals[xscal];
        RedrawBut(&butts[bnum]);
        DrawXButs();
        }


}


/************************************************************************/
static Pos(bnum,amount)
int bnum,amount;
{
    int    rnum,i;
    Range  *rp;
    Offset *op;

    /* if it's one of the X controls, and we're non-linear, then deal */
    if ((bnum==2 || bnum==3) && xscal!=LINEAR) ModXCtrl(bnum,amount);


    /* see if it's one of the range controls */
    else if ((bnum==3) || (bnum==5) || (bnum==7) || (bnum==9) || (bnum==11)) {
        rnum=(bnum-3)/2;  rp= &ranges[rnum];
        switch (amount) {
            case 1:  rp->multiplier++;  break;
            case 2:  rp->multiplier+=3; break;
            case 3:  rp->power++;       break;
            }

        /* adjust things */
        if (rp->multiplier>8) {
            rp->multiplier-=9;
            rp->power++;
            }

        if (rp->power>8) {
            rp->power = rp->multiplier = 8;
            }

        R2Str(rnum);
        butts[bnum].st = rp->str;
        RedrawBut(&butts[bnum]);
        }


    /* see if it's one of the offset controls */
    else if ((bnum==2) || (bnum==4) || (bnum==6) || (bnum==8) || (bnum==10)) {
        if (ylock && bnum!=2) {
            for (i=1; i<=numy; i++) ModOffset(i,amount);
            }
        else {
            rnum=(bnum-2)/2;
            ModOffset(rnum,amount);
            }
        }

    /* see if it's the X Grid Control */
    else if (bnum==0) {
        xscal=(xscal+1) % 3;
        butts[bnum].st=scals[xscal];
        RedrawBut(&butts[bnum]);
        DrawXButs();
        }


}


/************************************************************************/
static Norm(bnum)
int bnum;
{
    int    rnum,i;
    Range  *rp;
    Offset *op;

    if ((bnum==2 || bnum==3) && xscal!=LINEAR) ModXCtrl(bnum,0);

    else if ((bnum==3) || (bnum==5) || (bnum==7) || (bnum==9) || (bnum==11)) {
        rnum=(bnum-3)/2;
        rp = &ranges[rnum];
        rp->power =4;
        rp->multiplier=0;
        rp->val=1.0;
        R2Str(rnum);
        butts[bnum].st=rp->str;
        RedrawBut(&butts[bnum]);
        }

    else if ((bnum==2) || (bnum==4) || (bnum==6) || (bnum==8) || (bnum==10)) {
        if (ylock && bnum!=2) {
            for (i=1; i<=numy; i++) {
                offsets[i].val=0.0;
                O2Str(i);
                butts[2+i*2].st=offsets[i].str;
                RedrawBut(&butts[2+i*2]);
                }
            }
        else {
            rnum=(bnum-2)/2;
            offsets[rnum].val=0.0;
            O2Str(rnum);
            butts[bnum].st=offsets[rnum].str;
            RedrawBut(&butts[bnum]);
            }
        }

    else if (bnum==0) {
        xscal=LINEAR;
        butts[bnum].st=scals[xscal];
        RedrawBut(&butts[bnum]);
        DrawXButs();
        }
}


/************************************************************************/
static ModOffset(num,amt)
int num,amt;
{
    double rng;
    int i,bnum;

    bnum = num*2+2;
    rng  = ranges[num].val;

    if      (amt==  3) offsets[num].val += (rng*10.0);
    else if (amt==  2) offsets[num].val += (rng);
    else if (amt==  1) offsets[num].val += (rng/10.0);
    else if (amt== -1) offsets[num].val -= (rng/10.0);
    else if (amt== -2) offsets[num].val -= (rng);
    else if (amt== -3) offsets[num].val -= (rng*10.0);

    O2Str(num);
    butts[bnum].st=offsets[num].str;
    RedrawBut(&butts[bnum]);
	
}


/************************************************************************/
static ModXCtrl(bnum,amt)
int bnum,amt;
{	
    int *offs, *rang;

    if (xscal==LOG10) { offs = &L10Offset;  rang = &L10Range;}
                 else { offs = &OctOffset;  rang = &OctRange;}


    if (bnum==2) {    /* offset */
        if (amt) {
            *offs += amt;
            if (*offs<-19) *offs = -19;
            if (*offs>19)  *offs =  19;
            }
        else 
            *offs=0;

        SetXButs();
        RedrawBut(&butts[bnum]);
        }
    
    else {            /* range */
        if      (amt>0) { *rang+=1;  *rang%=3; }
        else if (amt<0) { *rang+=2;  *rang%=3; }
        else            *rang=0;

	SetXButs();
	RedrawBut(&butts[bnum]);
	}
}


/************************************************************************/
SetXButs()
    /* sets top two buttons (2,3) to appropriate strings */
{
    static char oStr[20];
    static char rStrs[3][8]={"1 div","3 divs","10 divs"};

    switch (xscal) {
        case LINEAR:
            butts[2].st=offsets[0].str;
            butts[3].st=ranges[0].str;
            break;
        case LOG10:
            sprintf(oStr,"1E%d %s",L10Offset,units[0]);
            butts[2].st=oStr;
            butts[3].st=rStrs[L10Range];
            break;
        case OCTAVE:
            sprintf(oStr,"2^%d %s",OctOffset,units[0]);
            butts[2].st=oStr;
            butts[3].st=rStrs[OctRange];
            break;
        }
    if (butts[0].st != scals[xscal]) {
        butts[0].st = scals[xscal];
        }
}


/************************************************************************/
DrawXButs()
    /* sets top two buttons (2,3) to appropriate strings and draws them */
{
	SetXButs();
	RedrawBut(&butts[2]);
	RedrawBut(&butts[3]);
}


/******************/           
FpToEng(st,aval)
char *st;
double aval;
/*
 * converts a floating point number to a string in the form 'x.xxx Exx',
 * where the Exx is divisible by 3.  (engineering notation)
 */

{
    int e,ei,i,j;
    char tmp[20];
         
    sprintf(st,"%e",fabs(aval));  /* generate the 'std' E-notation */
    *(st+5)='\0';                 /* take the first five chars */
                                  /* 'x.xxx' */
     
    for (i=6; *(st+i)!='e'; i++); /* find the beginning of the 'E' part */
    i++;
        
    e=atoi(st+i);   /* exponent value (an integer) */
    i=(e+99) % 3;   /* number of places to shift dec. point (0-2) */
    ei = e-i;       /* new/improved exp. value (divisible by 3) */  
     
    for (j=1; j<=i; j++)    /* shift the decimal point right 0-2 times */
        *(st+j) = *(st+j+1);

    *(st+i+1) = '.';         
 
    if (aval<0.0) {         /* if negative, add a '-' sign at the front */
        for (i=4; i>0; i--) *(st+i) = *(st+i-1);
        *st = '-';
        }
         
    if (ei) {               /* tack on the exponent part */
        sprintf(tmp,"E%-3d",ei);
        strcat(st,tmp);
        }
}
            
\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplotctl.c"
fi
if `test ! -s ./xsplot/xsplotdiv.c`
then
echo "writing ./xsplot/xsplotdiv.c"
cat > ./xsplot/xsplotdiv.c << '\Rogue\Monster\'
/************************************************************************/
/* XSPLOTDIV.C  -  routines for manipulating the 'diversion'		*/
/*----------------------------------------------------------------------*/
/* InitDivers();	- called once at start of program to init it	*/
/* OpenDivers();	- open up the diversion and execute it		*/
/* RedrawDivers();	- called by 'HandleEvent' to redraw the thing	*/
/************************************************************************/

#include "xsplot.h"

/* size of interesting part of diversion window */
#define DW 200
#define DH 290

#define BRWIDE 16
#define BRHIGH 8
#define BRWIDE2 8
#define BRHIGH2 4
#define BX(j) (20*j + 10)
#define BY(i) (14*i + 24)

static int invplanes,score,fast,small,grace,ballnum,numbricks;
static short bx,by,bdx,bdy,px,py;
static int pwidth, bwidth=6, pwidth2, bwidth2;
static Cursor noncurs;

static short brick[6][10];  /* hint, hint */
static short bscore[6] = {5,5,3,3,1,1};

/************************************************************************/
InitDivers()
{
    static short non_bits[8] = {0,0,0,0,0,0,0,0};  /* an inviso-cursor */

    invplanes = dlgFcol ^ dlgBcol;
    px = -1;  /* a very unlikely number */
    py = 272;
    bwidth2 = bwidth/2;

    NewGame();
    noncurs = XCreateCursor(8,8,non_bits,non_bits,0,0,1,0,GXcopy);
    XDefineCursor(diversW,noncurs);
}


/************************************************************************/
static NewGame()
{
    score = ballnum = 0;
    NewBall();
    NewBricks();
}

/************************************************************************/
static NewBall()
{
    char *tmp  = "Game Over";
    char *tmp1 = "Click mouse to continue";
    XEvent event;

    ballnum++;
    if (ballnum==4) { /* game over */
        XText(diversW,(DW-XStringWidth(tmp,butfinfo,0,0))/2,
              150,tmp,strlen(tmp),butfont,dlgFcol,dlgBcol);
        XText(diversW,(DW-XStringWidth(tmp1,butfinfo,0,0))/2,
              162,tmp1,strlen(tmp1),butfont,dlgFcol,dlgBcol);
        }

    bx = (abs(rand())%20)*10 + 5;  by = 141;
    bdx = (abs(rand())%21)-10;  bdy = 6;
    InvertPad();
    pwidth=32;  pwidth2 = pwidth/2;
    InvertPad();
    fast=small=0;  grace=40;
}


/************************************************************************/
static NewBricks()
{
    int i,j;

    numbricks=60;

    for (i=0; i<6; i++)
        for (j=0; j<10; j++) brick[i][j]=1;
}


/************************************************************************/
OpenDivers()
{
    XEvent event;
    Window subw;
    int mx,my,ox,oy,gameover;
    int i,w,h,sc;

    sc=selCB;  selCB=3;  /* to force the inverted frame to be color '3' */
    for (i=1; i<=201; i+=8) {
        Frame(gridW,i-10,i-15,i+10,i+15,1,dlgFcol,GXinvert);
        XFlush();
        Timer(15000L);
        }

    for (i=1; i<201; i+=8) {
        Frame(gridW,i-10,i-15,i+10,i+15,1,dlgFcol,GXinvert);
        XFlush();
        Timer(15000L);
        }
 
    selCB=sc;

    for (w=20,h=30; w<200; w+=10,h+=15) {  /* Zoom! */
        int x,y;
        x=201-w/2;  y=201-h/2;
        Frame(gridW,x,y,x+w,y+h,1,dlgFcol,GXcopy);
        XFlush();
        Timer(25000L);
        }

    XMapWindow(diversW);

    gameover=0;  grace=40;

    /* handle events until the next mouse event */   
    while (1) {
        Timer(30000L);

        if (XPending()) {
            XNextEvent(&event);
            if (event.type != ButtonPressed) HandleEvent(&event);
            else if (event.type == ButtonPressed && gameover) {
                gameover=0;
                NewGame();
                RedrawDivers();
                }
            else break;
            }

        if (gameover) continue;

        /* advance diversion by one frame */
        XQueryMouse(diversW,&mx,&my,&subw);
        if (mx>DW) mx=DW;
        if (mx<0)  mx=0;

        if (mx != px) { /* move player thing */
            InvertPad();
            px = mx;
            InvertPad();
            }

        if (grace) {  /* give the player a grace period before moving ball */
            grace--;
            continue;
            }


        /* move non-player thing */
        ox = bx;  oy = by;
        bx += bdx;  by += bdy;
        if ( (bx-bwidth2 < 0) || (bx+bwidth2 > DW) ) {  /* hit left or right */
            bdx = -bdx;
            bx += 2*bdx;
            }

        if (by-bwidth2 < 0) {  /* hit back */
            bdy = - bdy;
            by += 2*bdy;
            if (!small) { /* make paddle smaller */
                small=1;
                InvertPad();
                pwidth=18;  pwidth2=pwidth/2;
                InvertPad();
                }
            }

        else if (by+bwidth > DH) {  /* hit bottom */
            XFeep(0);
            NewBall();
            if (ballnum==4) {  /* game over */
                gameover=1;  continue;
                }
            else DrawBC();
            }

        else if ( (by+bwidth2) >= py 
             && (by-bwidth2) <= (py+8)
             && (bx+bwidth2) > (px-pwidth2) 
             && (bx-bwidth2) < (px+pwidth2) ) {   /* hit paddle */
            bdy = -bdy;
            bdx = (bx-px)/2;
            if (small)  bdx=2*bdx;  /* more english on smaller paddle */
            }

        else {  /* check to see if it hit a brick */
            int i,j,k;
            for (i=0; i<6; i++) {  /* find row */
                k=BY(i);
                if ( (k-BRHIGH2) < (by+bwidth2)
                  && (k+BRHIGH2) > (by-bwidth2) ) break;
                }

            if (i<6)  {  /* it's on a row, now check individual bricks */
                for (j=0; j<10; j++) {
                    k=BX(j);
                    if ( brick[i][j]
                      && (k-BRWIDE2) < (bx+bwidth2)
                      && (k+BRWIDE2) > (bx-bwidth2) ) break;
                    }

                if (j<10) { /* hit brick[i][j] */
                    brick[i][j]=0;  numbricks--;
                    InvBrick(i,j);
                    bdy = -bdy;
                    score += bscore[i];
                    DrawScore();

                    if (!fast && i<2) {  /* hit a rear brick.  speedup */
                        fast=1;
                        bdy = bdy * 2;
                        }

                    if (!numbricks) {  /* completed the thing.  Wowzo! */
                        XText(diversW,
                              (DW-XStringWidth("Wowzo!",dlogfinfo,0,0))/2,
                              150,"Wowzo!",6,dlogfont,dlgFcol,dlgBcol);
                        score+=200;  DrawScore();
                        XFeep(0);  XFeep(0);  XFeep(0);  XFlush();
                        Timer(2000000L);  ballnum--;
                        NewBall();  NewBricks();  RedrawDivers();
                        ox=bx;  oy=by;
                        }
                    }
                }
            }
                    
        InvertBall(ox,oy);  InvertBall(bx,by);
        }

    XUnmapWindow(diversW);
}


/************************************************************************/
static InvertBall(x,y)
              int x,y;
{
    XPixFill(diversW,x-bwidth2,y-bwidth2,bwidth,bwidth,1,0,GXinvert,invplanes);
}


/************************************************************************/
static InvBrick(i,j)
            int i,j;
{
    XPixFill(diversW,BX(j)-BRWIDE2,BY(i)-BRHIGH2,BRWIDE,BRHIGH,
             1,0,GXinvert,invplanes);
}


/************************************************************************/
static InvertPad()
{
    XPixFill(diversW,px-pwidth2,py,pwidth,8,1,0,GXinvert,invplanes);
}


/************************************************************************/
static DrawBC()
{
    char tmp[24];

    sprintf(tmp,"Ball %d",ballnum);
    XText(diversW,20,DH+1,tmp,strlen(tmp),butfont,dlgBcol,dlgFcol);
}


/************************************************************************/
static DrawScore()
{
    char tmp[24];

    sprintf(tmp,"Score=%d",score);
    XText(diversW,DW-20-XStringWidth(tmp,butfinfo,0,0),
          DH+1,tmp,strlen(tmp),butfont,dlgBcol,dlgFcol);
}


/************************************************************************/
RedrawDivers()
{
    int i,j;

    XClear(diversW);
    InvertPad();
    InvertBall(bx,by);

    for (i=0; i<6; i++)
        for (j=0; j<10; j++)
            if (brick[i][j]) InvBrick(i,j);

    XPixSet(diversW,0,DH,DW,10,dlgFcol);
    DrawBC();
    DrawScore();
}
             
\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplotdiv.c"
fi
if `test ! -s ./xsplot/xsplotdlg.c`
then
echo "writing ./xsplot/xsplotdlg.c"
cat > ./xsplot/xsplotdlg.c << '\Rogue\Monster\'
/************************************************************************/
/* XSPLOTDLG.C  -  routines for manipulating dialog boxes		*/
/*----------------------------------------------------------------------*/
/* OpenDlog(w);		- open a dialog window				*/
/* CloseDlog();		- close the current dialog window		*/
/* RedrawDlog();	- got an 'ExposeWindow'.  Redraw the dlog	*/
/* DlogKey(st,len);	- got a 'KeyPress' during dialog.  Deal with it */
/* ClickDlog(x,y);	- got a mouse click at x,y.  Do something.	*/
/************************************************************************/


#include "xsplot.h"

static int selanal;

/**********************/
OpenDlog(w)
Window w;
{
    int i;

    dlogW = w;

    if (dlogW == LoadDlog)    {  /* 380x100 */
        MakeButton(&dbutts[0],dlogW,30, 60,80,30,"Ok",dlogfinfo);
/*      MakeButton(&dbutts[1],dlogW,150,60,80,30,"No Parse",dlogfinfo); */
        MakeButton(&dbutts[1],dlogW,270,60,80,30,"Cancel",dlogfinfo);

        for (i=0; i<2; i++) XSelectInput(dbutts[i].win,ExposeWindow);

        XMapSubwindows(dlogW);
        dlogstr[0]='\0';  dlscnt=0;
        }

    else if (dlogW == SwitchDlog)  {
        XChangeWindow(dlogW,200,40+20*numanals);
        selanal = curanal;
        }

    else if (dlogW == CurvDlog)    {  /* 200x300 */
        MakeButton(&curvbutts[0],dlogW,10, 50, 80,40,theAnal->labels[1],dlogfinfo);
        MakeButton(&curvbutts[1],dlogW,110,50, 80,40,theAnal->labels[2],dlogfinfo);
        MakeButton(&curvbutts[2],dlogW,10, 100,80,40,theAnal->labels[3],dlogfinfo);
        MakeButton(&curvbutts[3],dlogW,110,100,80,40,theAnal->labels[4],dlogfinfo);
        MakeButton(&curvbutts[4],dlogW,10, 150,80,40,theAnal->labels[5],dlogfinfo);
        MakeButton(&curvbutts[5],dlogW,110,150,80,40,theAnal->labels[6],dlogfinfo);
        MakeButton(&curvbutts[6],dlogW,10, 200,80,40,theAnal->labels[7],dlogfinfo);
        MakeButton(&curvbutts[7],dlogW,110,200,80,40,theAnal->labels[8],dlogfinfo);

        MakeButton(&dbutts[0],dlogW,10, 265,80,25,"Ok",dlogfinfo);
        MakeButton(&dbutts[1],dlogW,110,265,80,25,"Cancel",dlogfinfo);

        for (i=0; i<numy; i++) InvertBut(&curvbutts[ind[i]]);

        XMapWindow(dbutts[0].win);  XSelectInput(dbutts[0].win,ExposeWindow);
        XMapWindow(dbutts[1].win);  XSelectInput(dbutts[1].win,ExposeWindow);
        for (i=0; i<theAnal->numys; i++) {
            XMapWindow(curvbutts[i].win);
            XSelectInput(curvbutts[i].win,ExposeWindow);
            }
        }

    else if (dlogW == PlotDlog)    { /* 380x70 */
        MakeButton(&dbutts[0],dlogW,30, 30,80,30,"File",   dlogfinfo);
        MakeButton(&dbutts[1],dlogW,150,30,80,30,"Plotter",dlogfinfo);
        MakeButton(&dbutts[2],dlogW,270,30,80,30,"Cancel", dlogfinfo);

        for (i=0; i<3; i++) XSelectInput(dbutts[i].win,ExposeWindow);
        XMapSubwindows(dlogW);
        }

    else if (dlogW == PlotNDlog)    {  /* 380x100 */
        MakeButton(&dbutts[0],dlogW,30, 60,80,30,"Ok",dlogfinfo);
        MakeButton(&dbutts[1],dlogW,270,60,80,30,"Cancel",dlogfinfo);
        dbutts[2].win=0;
        for (i=0; i<2; i++) XSelectInput(dbutts[i].win,ExposeWindow);
        XMapSubwindows(dlogW);
        dlogstr[0]='\0';  dlscnt=0;
        }

    else if (dlogW == HelpDlog)    {}

    XMapWindow(dlogW);
}

/**********************/
CloseDlog()
{

    int i;

    if (dlogW == LoadDlog)   { 
        InvertBut(&butts[25]);
        XDestroySubwindows(dlogW);
        }

    else if (dlogW == SwitchDlog) { InvertBut(&butts[24]); }

    else if (dlogW == CurvDlog)   {
        InvertBut(&butts[26]);
        XDestroySubwindows(dlogW);
        }

    else if (dlogW == PlotDlog)   { 
        InvertBut(&butts[38]);
        XDestroySubwindows(dlogW);
        }

    else if (dlogW == PlotNDlog)   { 
        InvertBut(&butts[38]);
        XDestroySubwindows(dlogW);
        }

    else if (dlogW == HelpDlog)   { InvertBut(&butts[39]); }

    XUnmapWindow(dlogW);

    dlogW = 0;
}

/***********************/
RedrawDlog()
{
    int i;

    if (dlogW == LoadDlog) { /* 380x100 */
        XText(dlogW,10,10, "Load data from:",15, dlogfont,dlgFcol,dlgBcol);
        Frame(dlogW,10,30, 370,50, 2, dlgFcol,GXcopy);
        XText(dlogW,14,36,dlogstr,dlscnt,butfont,dlgFcol,dlgBcol);
        XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36,         /* text cursor */
                butfinfo->width, butfinfo->height, dlgFcol);
        }

    else if (dlogW == SwitchDlog) {  /* 200x(40 + 20*numanal) */
        XText(dlogW, 10,10, "Choose an analysis:",19, 
              dlogfont,dlgFcol,dlgBcol);
        XLine(dlogW, 0,30, 200,30, 1,1,dlgFcol,GXcopy,AllPlanes);
        for (i=0; i<numanals; i++)
            XText(dlogW, 10,40+20*i+(20-dlogfinfo->height)/2, anals[i].title,
                  strlen(anals[i].title), dlogfont, dlgFcol, dlgBcol);
        XPixFill(dlogW,0,40+20*curanal,200,20,ForeColor,0,GXinvert,
                    dlgFcol ^ dlgBcol);
        }

    else if (dlogW == CurvDlog) {  /* 200x300 */
        XPixSet(dlogW,0,0,200,30,dlgBcol);
        XLine(dlogW,0,30,200,30,1,1,dlgFcol,GXcopy,AllPlanes);
        XText(dlogW,35,8, "Choose 1-4 curves",17,dlogfont,dlgFcol,dlgBcol);
        }

    else if (dlogW == HelpDlog) {  /* 380x200 */
        XText(dlogW, 40, 65, "Sorry, no on-line help available...",35,
              dlogfont,dlgFcol,dlgBcol);
        }

    else if (dlogW == PlotDlog) { /* 380x70 */
        XText(dlogW,10,10, "Send plot data to:",18,dlogfont,dlgFcol,dlgBcol);
        }

    else if (dlogW == PlotNDlog) { /* 380x100 */
        XText(dlogW,10,10, "Write plot data to:",19, dlogfont,dlgFcol,dlgBcol);
        Frame(dlogW,10,30, 370,50, 2, dlgFcol, GXcopy);
        XText(dlogW,14,36,dlogstr,dlscnt,butfont,dlgFcol,dlgBcol);
        XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36,      /* text cursor */
                butfinfo->width, butfinfo->height, dlgFcol);
        }

}

/***********************/
DlogKey(st,cnt)
char *st;
int cnt;
{
    int i;

    if (dlogW == LoadDlog || dlogW == PlotNDlog) {
        for (i=0; i<cnt; i++) {
            if (st[i]=='\010' || st[i]=='\177') {  /* backspace/del */
                XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36,
                             butfinfo->width, butfinfo->height, dlgBcol);
                if (dlscnt) dlscnt--;
                XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36,
                             butfinfo->width, butfinfo->height, dlgFcol);
                }

            else if (st[i]=='\0') {}  /* toss nulls away */

            else if (st[i]=='\n' || st[i]=='\r') {  /* return. choose default */
                if (dlscnt==0)    /* didn't enter a name.  Cancel */
                    ClickDlog(dbutts[1].x+1, dbutts[1].y+1);
                else              /* choose 'Ok' */
                    ClickDlog(dbutts[0].x+1, dbutts[0].y+1);
                }

            else { /* normal character */
                dlogstr[dlscnt]=st[i];
                XText(dlogW,14+dlscnt*butfinfo->width,36,&st[i],1,
                      butfont,dlgFcol,dlgBcol);
                if (dlscnt<MAXDSTR) dlscnt++;
                XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36,
                             butfinfo->width, butfinfo->height, dlgFcol);
                }
            }
        }
}


/***********************/
ClickDlog(x,y)
short x,y;
{
    int i;
    char tmpfname[64];

    dlogstr[dlscnt]='\0';

    if (dlogW == LoadDlog) {
        for (i=0; i<2; i++) {
            if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) &&
                y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break;
            }

        if (i<2) {
             InvertBut(&dbutts[i]);
             XFlush();
             Timer(200000L);
             }
        else return;

        if (i==0) {
            NOPARSE=0;
            strcpy(tmpfname,basfname);
            strcpy(basfname,dlogstr);
            if (OpenSpice()) {  /* couldn't load it.  or something */
                NOPARSE=1;
                if (strcmp(FixName(tmpfname),FixName(basfname))==0) {
                    /* the very odd case that the previous SPICE and the
                       asked-for SPICE have the same filename, but the 
                       asked-for SPICE was unable to be loaded.  In this
                       case, it's possible that the previous SPICE's tmp
                       files have been overwritten.  Better regenerate 
                       them, to be on the safe side... */
                    NOPARSE=0;
                    }
                strcpy(basfname,tmpfname);
                OpenSpice();
                LoadAnal(curanal);
                }
            else {
                LoadNewAnal(0);
                ChangedAnal();
                XFlush();
                RedrawSettings();
                }
            }
        CloseDlog();
        }


    else if (dlogW == SwitchDlog) {
        int tmpanal;
        tmpanal = (y/20)-2;
        if (tmpanal<0 || tmpanal>numanals) return;
        else if (tmpanal==selanal) {
            if (selanal==curanal) { CloseDlog();  return; }
            else { 
                LoadNewAnal(selanal);
                CloseDlog();
                ChangedAnal();
                XFlush();
                RedrawSettings();
                }
            }
        else {
            XPixFill(dlogW,0,40+20*selanal,200,20,ForeColor,0,GXinvert,
                     dlgFcol ^ dlgBcol);
            selanal=tmpanal;
            XPixFill(dlogW,0,40+20*selanal,200,20,ForeColor,0,GXinvert,
                     dlgFcol ^ dlgBcol);
            }
        }

    else if (dlogW == CurvDlog) {
        int j,numsel,tmpind[4];

        for (i=0; i<2; i++) {
            if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) &&
                y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break;
            }

        if (i<2) { InvertBut(&dbutts[i]);  XFlush();  Timer(200000L); }

        if (i==0) { /* Ok */
            for (j=0,numsel=0; j<theAnal->numys; j++)
                if (curvbutts[j].invert) {
                    if (numsel<4) tmpind[numsel]=j;
                    numsel++;
                    }
            if (numsel==0) {
                ErrBox("Choose at least one curve.",1);
                InvertBut(&dbutts[0]);
                }
            else if (numsel>4) {
                ErrBox("Choose no more than four curves.",1);
                InvertBut(&dbutts[0]);
                }
            else {  /* selected curves are okay, load 'em */
                for (j=0; j<numsel; j++) ind[j]=tmpind[j];
                numy=numsel;
                LoadAnal(curanal);
                ChangedCurves();
                CloseDlog(); /* note that closing dlog will redraw ALL data */
                XFlush();
                RedrawSettings();
                }
            }

        else if (i==1) {  /* Cancel */
            CloseDlog();
            }                

        else {                
            for (i=0; i<theAnal->numys; i++) {
                if (x>=curvbutts[i].x && x<=(curvbutts[i].x+curvbutts[i].w) &&
                    y>=curvbutts[i].y && y<=(curvbutts[i].y+curvbutts[i].h)) break;
                }
            if (i<theAnal->numys) InvertBut(&curvbutts[i]); 
            }
        }
        

    else if (dlogW == PlotDlog) {
        for (i=0; i<3; i++) {
            if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) &&
                y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break;
            }
        if (i<3) {
             InvertBut(&dbutts[i]);
             XFlush();
             Timer(200000L);
            }
        else return;

        if (i==0) {        /* File */
            XMapWindow(PlotNDlog);
            CloseDlog();
            InvertBut(&butts[38]);
            OpenDlog(PlotNDlog);
            }
        else if (i==1) {   /* Plotter */
            Splotter();
            CloseDlog();
            }
        else CloseDlog();  /* Cancel */
        }


    else if (dlogW == PlotNDlog) {
        for (i=0; i<2; i++) {
            if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) &&
                y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break;
            }

        if (i<2) {
             InvertBut(&dbutts[i]);
             XFlush();
             Timer(200000L);
             }
        else return;

        if (i==0) {  /* Ok */
            if (!PlotFile(dlogstr)) ErrBox("Plot file written.",-1);
            }

        CloseDlog();
        }


    else CloseDlog();
}


\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplotdlg.c"
fi
if `test ! -s ./xsplot/xsplotgr.c`
then
echo "writing ./xsplot/xsplotgr.c"
cat > ./xsplot/xsplotgr.c << '\Rogue\Monster\'
/************************************************************************/
/* XSPLOTGR.C								*/
/*----------------------------------------------------------------------*/
/* Library of routines to handle data plotting, Big Picture, etc.	*/
/*----------------------------------------------------------------------*/
/* void  DrawGwin  ();							*/
/* void  PlotData  ();							*/
/* void  ClearArrs ();							*/
/* void  DrawGrid  ();							*/
/* void  BigPicture();							*/
/* float CalcX();							*/
/* float CalcY();							*/
/* void  BestFit();							*/
/* int   CalcSRect(x,y,x1,y1);						*/
/* void  DigitalPresets();
/************************************************************************/


#include "xsplot.h"

#define SPLOTTER "/usr/local/splotter"

#define XUNIT 40
#define YUNIT 40
#define LOG2  0.69314718055994530941
#define NEGLOG -19.0         /* value returned when attempting log(-n) */

#define BPBottomFP 396.0     /* Big Picture size/position info */
#define BPHighFP   390.0     /* the Big Picture is a 390x390 rect centered */
#define BPLeftFP     6.0     /* in the 400x400 grid window */
#define BPWideFP   390.0

#define BPLeft       6
#define BPBottom   396 

static int oldxscal = -1, oldyscal = -1;

static int BPonscrn = 0;

#define log10a(x)  ((x<0.0) ? NEGLOG : log10(x))
#define log2a(x)   ((x<0.0) ? NEGLOG : log(x)/LOG2)
#define inrange(y) (y>=GTop && y<=GBottom)

static float xmin,xmax,ymin,ymax;     /* min/max values of DATA, unscaled */

static float sxmin,symin,sxmax,symax; /* min/max values of screen grid */
                                      /* note: sx/sy vals are ALWAYS linear */

static float dx,dy;                   /* xmax-xmin, ymax-ymin */
static float sdx,sdy;                 /* sxmax-sxmin, symax-symin */


/************************************************************************/
DrawGwin()  /* redraws whatever was in the grid window */
{
    if (BPonscrn) BigPicture();
             else PlotData();
}


/************************************************************************/
static float Coord2S(coord,scale)
float coord;
int scale;
{
    switch (scale) {
        case LINEAR: return(coord);
        case LOG10:  return(log10a(coord));
        default:     return(log2a(coord));
        }
}


/************************************************************************/
static int xconv(x)
float x;
{
    /* given an x value (from xlist.dat[]), convert it 
       to an integer (+-4K) suitable for plotting */

    float xtmp;
    static float divsize[3]={400.0,133.333333,40.0};  
    /* size of a division on one, three, and ten division grid, respectively */

    switch (xscal) {
        case LINEAR: xtmp = GLRmidFP+((x-offsets[0].val)/ranges[0].val)*XUNIT;
                     break;
        case LOG10:  x    = Coord2S(x,xscal);
                     xtmp = GLeftFP + (x-L10Offset)*divsize[L10Range];
                     break;

        case OCTAVE: x    = Coord2S(x,xscal);
                     xtmp = GLeftFP + (x-OctOffset)*divsize[OctRange];
                     break;
        }

    if      (xtmp<-4000.0) xtmp = -4000.0;
    else if (xtmp> 4000.0) xtmp =  4000.0;
    return( (int) xtmp);
}

/************************************************************************/
static int yconv(i,y)
int i;
float y;
{
    /* given a y value from ylist[i].dat[], convert it to an integer
       (+-4K) suitable for plotting */

    float ytmp;
	
    y = Coord2S(y,yscal);

    ytmp = GTBmidFP - ((y-offsets[i+1].val) / ranges[i+1].val) * YUNIT;

    if (ytmp> 4000.0) ytmp =  4000.0;
    if (ytmp<-4000.0) ytmp = -4000.0;
    return( (int) ytmp);
}


/************************************************************************/
PlotData()
{
    /* draws the data in the gridW using the current settings */

    int x,y,i,j,numplot;
    Vertex *vp;

    ClearArrs();
    BPonscrn = Vis159 = 0;

    DrawGrid();             /* clear and redraw the grid */
    if (numpts<2) return;   /* no points (per se) to draw */

    for (i=0; i<numy; i++) {           /* draw each curve */
        numplot=0;
        for (j=0; j<numpts; j++) {
            x = xconv(xlist.dat[j]);
            y = yconv(i,ylist[i].dat[j]);

            if (x<GLeft)   LeftArr=1;   /* set arrows according */
            if (x>GRight)  RightArr=1;
            if (y<GTop)    UpArr[i]=1;
            if (y>GBottom) DownArr[i]=1;

            /* keep track of the number of points plotted */
            if (x>=GLeft && x<=GRight && y>=GTop && y<=GBottom) numplot++;

            SetVertex(curve+j,x,y,0);            
            }

        if (mono)
            XDrawDashed(gridW,curve,numpts,1,1,ForeColor,linepats[i],GXcopy,AllPlanes);
        else 
            XDraw(gridW,curve,numpts,1,1,trcol[i],GXcopy,AllPlanes);

        /* if 30 or less points plotted, plot the actual data points, too. */
        if (numplot<31) 
            for (j=0,vp=curve; j<numpts; j++,vp++) {
                x = vp->x;
                y = vp->y;
                if (x>=GLeft && x<=GRight && y>=GTop && y<=GBottom)
                    XPixFill(gridW,x-1,y-1,3,3,trcol[i],0,GXcopy,AllPlanes);
                }
        }		
    DrawArrs();
}	


/************************************************************************/
ClearArrs()
{
    int i;

    LeftArr = RightArr = 0;
    for (i=0; i<4; i++) UpArr[i] = DownArr[i] = 0;
}


/************************************************************************/
static Calcminmax()
    /* calculates xmin,ymin,xmax,ymax,dx,dy */
{
    int i,j;

    /* find xmin, xmax, ymin, ymax */
    xmin = xmax = xlist.dat[0];
    ymin = ymax = ylist[0].dat[0];

    for (i=0; i<numpts; i++) {
        if (xlist.dat[i]<xmin) xmin=xlist.dat[i];
        if (xlist.dat[i]>xmax) xmax=xlist.dat[i];

        for (j=0; j<numy; j++) {
            if (ylist[j].dat[i]<ymin) ymin=ylist[j].dat[i];
            if (ylist[j].dat[i]>ymax) ymax=ylist[j].dat[i];
            }
        }

    dx=xmax-xmin;   dy=ymax-ymin;
}


/************************************************************************/
static CalcSdat()
{
    /* calculate sxmin, sxmax, symin, symax, sdx, sdy */

    sxmin=Coord2S(xmin,xscal);
    sxmax=Coord2S(xmax,xscal);

    symin=Coord2S(ymin,yscal);
    symax=Coord2S(ymax,yscal);

    sdx=sxmax-sxmin;
    sdy=symax-symin;
}


/************************************************************************/
static int BPxconv(x)
float x;
{
    /* converts a data x-value to it's bigpicture x-value */

    float xtmp;
	
    x=Coord2S(x,xscal);

    xtmp = BPLeftFP + ((x-sxmin) * BPWideFP) / sdx;
    return( (int) xtmp);
}


/************************************************************************/
static int BPyconv(y)
float y;
{
    /* converts a data y-value to it's bigpicture y-value */

    float ytmp;
	
    Coord2S(y,yscal);

    ytmp=BPBottomFP - ((y-symin) * BPHighFP) / sdy;
    return( (int) ytmp);
}


/************************************************************************/
BigPicture()
{
    /* erases grid, redraws the Big Picture */

    int x,y,i,j;
    char vals[100],vals1[16],vals2[16],vals3[16],vals4[16];

    BPonscrn=1;  Vis159=0;

    XClear(gridW);
    Calcminmax();
    CalcSdat();
    ClearArrs();
    DrawArrs();

    if (numpts<2) return;   /* no points (per se) to draw */

    for (i=0; i<numy; i++) {           /* draw each curve */
        for (j=0; j<numpts; j++) {
            x = BPxconv(xlist.dat[j]);
            y = BPyconv(ylist[i].dat[j]);
            SetVertex(curve+j,x,y,0);            
            }

        if (mono)
            XDrawDashed(gridW,curve,numpts,1,1,ForeColor,linepats[i],GXcopy,AllPlanes);
        else
            XDraw(gridW,curve,numpts,1,1,trcol[i],GXcopy,AllPlanes);

        }		


    for (i=0; i<numy; i++) DrawRBox(i);

    FpToEng(vals1,xmin);
    FpToEng(vals2,xmax);
    FpToEng(vals3,ymin);
    FpToEng(vals4,ymax);
    sprintf(vals,"Xmin:%-11.11s   Xmax:%-11.11s           Ymin:%-11.11s   Ymax:%-11.11s",vals1,vals2,vals3,vals4);

    ErrBox(vals,-1);
}	


/************************************************************************/
static int Rxconv(x)
float x;
{
    /* converts a data value to a BigPicture value, clipping at edge */
    /* used by DrawRBox() */

    x = BPLeftFP + ((x-sxmin) * BPWideFP) / sdx;

    if      (x>GRightFP) return(GRight);
    else if (x<GLeftFP)  return(GLeft);
    else                 return((int) x);
}

/************************************************************************/
static int Ryconv(y)
float y;
{
    /* converts a data value to a BigPicture value, clipping at edge */
    /* used by DrawRBox() */

    y = BPBottomFP - ((y-symin) * BPHighFP) / sdy;
    if      (y>GBottomFP) return(GBottom);
    else if (y<GTopFP)    return(GTop);
    else                  return((int) y);
}


/************************************************************************/
DrawRBox(rnum)
int rnum;
{
    /* draws a box on the BP, showing the part of a curve that will be 
       visible on the grid */

    int x1,y1,x2,y2;

    static int NumDiv[3]={1,3,10};

    if (xscal==LINEAR) {
        x1=Rxconv(offsets[0].val - 5*ranges[0].val);
        x2=Rxconv(offsets[0].val + 5*ranges[0].val);
        }

    else if (xscal==LOG10) {
        x1=Rxconv((float) L10Offset);
        x2=Rxconv((float) (L10Offset + NumDiv[L10Range]) );
        }

    else /* xscal==OCTAVE */ {
        x1=Rxconv((float) OctOffset);
        x2=Rxconv((float) (OctOffset + NumDiv[OctRange]) );
        }

    y1=Ryconv(offsets[rnum+1].val + 5*ranges[rnum+1].val);
    y2=Ryconv(offsets[rnum+1].val - 5*ranges[rnum+1].val);

    MakeRect(x1,y1,x2,y2);
    XDrawDashed(gridW,curve,5,1,1,trcol[rnum],RBoxPat[rnum],GXcopy,AllPlanes);
 /* XDraw(gridW,curve,5,1,1,ForeColor,GXcopy,AllPlanes); */
}



/************************************************************************/
DrawGrid()
{
    int   i,gtype,x,y;
    static int numlines[3]={10,28,51};
    static int repeat  [3]={9,9,5};
    static int xval[3][51]={{  0,120,191,241,280,311,338,361,382,400},
                            {  0, 40, 64, 80, 93,104,113,120,127,
                             133,173,197,214,227,237,246,254,261,
                             267,307,330,347,360,370,379,387,394,400},
                            {  0, 19, 28, 34, 38, 
                              40, 59, 68, 74, 78,
                              80, 99,108,114,118,
                             120,139,148,154,158,
                             160,179,188,194,198,
                             200,219,228,234,238,
                             240,259,268,274,278,
                             280,299,308,314,318,
                             320,339,348,354,358,
                             360,379,388,394,398,400}};

    XClear(gridW);

    /* draw vertical lines */
    if (xscal==LINEAR) {
        for (i=0,x=GLeft; i<11; i++,x+=40) {
            if (i==5) XLine(gridW,x,GTop,x,GBottom,1,1,gridFcol,GXcopy,AllPlanes);
            else      DashLine(gridW,x,GTop,x,GBottom+1,gridFcol,GridPat2);
            }
        }

    else {
        if (xscal==LOG10)  gtype=L10Range;
        if (xscal==OCTAVE) gtype=OctRange;

        for (i=0; i<numlines[gtype]; i++) {
            x = xval[gtype][i]+GLeft;

            if (i%repeat[gtype]) 
                DashLine(gridW,x,GTop,x,GBottom+1,gridFcol,GridPat4);
            else
                XLine(gridW,x,GTop,x,GBottom,1,1,gridFcol,GXcopy,AllPlanes);
            }
        }

    /* draw horizontal lines */
    for (i=0,y=GTop; i<11; i++,y+=40) {
        if (i==5) XLine(gridW,GLeft,y,GRight,y,1,1,gridFcol,GXcopy,AllPlanes);
        else      DashLine(gridW,GLeft,y,GRight,y,gridFcol,GridPat2);
        }

    /* draw tick marks */
    if (xscal==LINEAR) {
        for (i=1,x=GLeft+8; i<50; i++,x+=8)
            if (i%5) XLine(gridW,x,GTBmid-2,x,GTBmid+2,1,1,gridFcol,GXcopy,AllPlanes);
        for (i=1,y=GTop+8; i<50; i++,y+=8)
            if (i%5) XLine(gridW,GLRmid-2,y,GLRmid+2,y,1,1,gridFcol,GXcopy,AllPlanes);
        }
}


/********************/
static float BPx2fp(x)
int x;
{
    /* given a grid coordinate on the big picture, returns the data value
       associated with it.  Used for zooming on the BP */

    if (xscal==LINEAR) 
        return ( ((x-BPLeft)/BPWideFP) * dx + xmin);
    else if (xscal==LOG10)
        return (pow(10.0,( (x-BPLeft)/BPWideFP) * sdx + sxmin) );
    else /* (xscal==OCTAVE) */
        return (pow(2.0, ( (x-BPLeft)/BPWideFP) * sdx + sxmin) );
};

/********************/
static float BPy2fp(y)
int y;
{
    /* see BPx2fp */

    return ( ((BPBottom-y)/BPHighFP) * dy + ymin);
}

/***************/
float CalcX(x)
int x;
{
    /* calculates the value (in data coordinates) of a given x (grid) value */

    static float DivSize[3]={400.0,133.333333,40.0};

    if (BPonscrn) 
        return(BPx2fp(x));

    else if (xscal==LINEAR) 
        return(((float)(x-GLRmid)/40.0) * ranges[0].val + offsets[0].val);

    else if (xscal==LOG10) 
        return(pow(10.0,((x-GLeft)/DivSize[L10Range]) + L10Offset));

    else /* (xscal==OCTAVE) */
	return(pow(2.0, ((x-GLeft)/DivSize[OctRange] + OctOffset)));
}


/***************/
float CalcY(y,trace)
int y,trace;
{
    /* calculates the value (in data coordinates) of a given y (grid) value */

    if (BPonscrn) 
        return(BPy2fp(y));

    else
        return( ((GTBmid-y)/40.0) * ranges[trace+1].val + offsets[trace+1].val);
}


/******************/
BestFit()
{
    /* fills in the range/offset values with the 'best' values */

    double zx1,zy1,zx2,zy2,zdx,zdy,zxm,zym;
    int i,mul,exp;

    Calcminmax();
    CalcSdat();

    zx1 = xmin;
    zx2 = xmax;
    zdx = zx2 - zx1;
    zxm = zx1 + zdx/2.0;

    zy1 = ymin;
    zy2 = ymax;
    zdy = zy2 - zy1;
    zym = zy1 + zdy/2.0;

    CalcXRange(zx1,zx2,zdx,zxm);

    CalcNearRange(zdy,&mul,&exp,&zym);
    for (i=0; i<numy; i++) {
        ranges[i+1].multiplier=mul;
        ranges[i+1].power=exp;
        offsets[i+1].val=zym;
        }
}


/******************/
int CalcSRect(x1,y1,x2,y2)
short x1,y1,x2,y2;
{
    short i,tmp;
    double zx1,zy1[4],zx2,zy2[4],zdx,zdy[4],zxm,zym[4];
    int mul,powr;


    if (x1==x2 && y1==y2) { BestFit(); return(1); }

    if (x1==x2 || y1==y2) return(0);  /* empty rectangle */
    /* get x1,y1 to be bot left, and x2,y2 to be top right */
    if (x2<x1) swap(x1,x2,tmp);
    if (y1<y2) swap(y1,y2,tmp);

    for (i=0; i<8; i++) {
        InvertSBox(x1,y1,x2,y2);  XFlush();
        Timer(100000L);
        }
	

    zx1 = CalcX(x1);
    zx2 = CalcX(x2);
    zdx = zx2-zx1;
    zxm = zx1 + zdx/2.0;
    CalcXRange(zx1,zx2,zdx,zxm);

    if (BPonscrn) {
        /* zoom onto big picture */
        double zy1,zy2,zdy,zym;

        zy1 = CalcY(y1);
        zy2 = CalcY(y2);
        zdy = zy2-zy1;
        zym = zy1 + zdy/2.0;
		
        CalcNearRange(zdy,&mul,&powr,&zym);
        for (i=0; i<numy; i++) {
            ranges[i+1].multiplier=mul;
            ranges[i+1].power=powr;
            offsets[i+1].val=zym;
            }
        }

    else {
        /* zooming on grid */

        /* calculate zoomed-to y values */
        for (i=0; i<numy; i++) {
            zy1[i] = CalcY(y1,i);
            zy2[i] = CalcY(y2,i);
            zdy[i] = zy2[i] - zy1[i];
            zym[i] = zy1[i] + zdy[i]/2.0;
            CalcNearRange(zdy[i],&ranges[i+1].multiplier,&ranges[i+1].power,&zym[i]);
            offsets[i+1].val=zym[i];
            }
        }
	
    return(1);

}


/****************/
static CalcXRange(x1,x2,dx,xm)
double x1,x2,dx,xm;
{
    /* given min,max,dx,and midpt values, sets the x controls to whatever'd
       'best' (there's that word again) display the range */

    double mid;

    mid=xm;

/*    printf("CalcXRange: x1=%e  x2=%e  dx=%e  xm=%e\n",x1,x2,dx,xm); */

    if (xscal==LINEAR) {
        CalcNearRange(dx,&ranges[0].multiplier,&ranges[0].power,&mid);
        offsets[0].val=mid;
        }

    else if (xscal==LOG10) {
        double tmp;
        L10Offset=(int) floor(log10(x1));
        if (L10Offset<-20) L10Offset = -20;
        if (L10Offset> 20) L10Offset =  20;
        tmp = x2/x1;
        if      (tmp>1000.0) L10Range=2;
        else if (tmp>  10.0) L10Range=1;
        else                 L10Range=0;
        }
		
    else /* (xscal==OCTAVE) */ {
        double tmp;
        OctOffset=(int) floor(log(x1)/log(2.0));
        if (OctOffset<-20) OctOffset = -20;
        if (OctOffset> 20) OctOffset =  20;
        tmp = x2/x1;
        if      (tmp>8.0) OctRange=2;
        else if (tmp>2.0) OctRange=1;
        else              OctRange=0;
        }
}		
	

/****************/
static CalcNearRange(d,mul,exp,mid)
double d;
int *mul,*exp;
double *mid;
{
    /* given a delta, and a midpoint, returns 'best fit' mul,exp, and mid 
       values.  Only works on linear settings */

    /* takes a desired range 'd', and converts it to a valid range setting */
    /* rounding rules:  1<x<=2.0  -> x=2.0
                        2<x<=5.0  -> x=5.0
                        5<x       -> x=10.0   (where x=first digit) */

    /* also takes the center of the range (offset) and rounds it to 
       the next lower half-division (ie: if the resultant range is
       5V per division, the offset will be rounded to some multiple of
       2.5V.  In theory, at least */

    double mant,newmant,rpdiv,rpdiv2,z,md;
    int powr,m,e,e1;

    powr = (int) floor(log10(d));	/* powr(125.0) = 2 */

    mant = d/pow(10.0,(double) powr);	/* mant(125.0) = 1.25 */

    /* mant * 10^powr = d   :   1 <= mant < 10 */

    /* round up range */
    if      (mant>5.0) { newmant=1.0; m=0; powr++;}
    else if (mant>2.0) { newmant=5.0; m=2; }
    else if (mant>1.0) { newmant=2.0; m=1; }
    else               { newmant=1.0; m=0; }

    powr--;				/* divide by 10 to get range/div */

    e = (powr/3) + 4;			/* convert powr -> exp */
    if (e>8) e=8;			/* truncate at ends of valid range */
    if (e<0) e=0;
    e1=abs(powr)%3;
    if (powr<0 && e1!=0) { e--;  e1=3-e1; }

    if (e>=0) m=m+e1*3;			/* calculate mul */
    else { e=0; m=0; }

    *mul=m;  *exp=e;

    /* calculate the nice, rounded-off midpt */
    rpdiv = newmant * pow(10.0,(double) powr);	/* range per div */
    rpdiv2 = rpdiv/2;				/* range per half-div */
    md = *mid;

    /* vaguely-evil kludge.  Basically, if mid/rpdiv2 is something like
       5.99999, this hopefully pushes it above 6.0, so that floor returns 6 */
    *mid = *mid * 1.00001;

    z = floor(*mid/rpdiv2);		/* integer # of half-divs in m */
    *mid = z * rpdiv2;			/* rounded down version of m */

/*  printf("rpdiv:=%e    rpdiv2=%e\n",rpdiv,rpdiv2);
    printf("mid=%e  mid/rpdiv=%e  z=%e  z*rpdiv2=%e\n\n",md,md/rpdiv2,z,*mid);
*/
}



/************************************************************************/
/* Routines to handle data plotting.	(Hard Copy!  Wowzo!)		*/
/*----------------------------------------------------------------------*/
/*	PlotFile(fnam);	- writes data points to the named SPIF file.	*/
/*	Splotter();	- writes a tmp SPIF file, and execs splotter	*/
/************************************************************************/


/*
 * The SPIF Format:
 *   (all numbers are in ascii format (printf))
 *
 * Field 1:  The name of the spice file
 *       2:  The name of the analysis
 *	 3:  The Grid Type
 *		(0 = Linear, 10 divs per axis, with axes at center)
 *		(1 = Log10, 1 div)
 *		(2 = Log10, 3 divs)
 *		(3 = Log10, 10 divs)
 *		(4 = Log 2, 1 div)
 *		(5 = Log 2, 3 divs)
 *		(6 = Log 2, 10 divs)
 *		(consult Splot to see what grids should look like)
 *	 4:  The number of traces in the plot (1-4)
 *       5:  The names of the traces (2-5 words, each up to 8 chars long)
 *	 6:  The x-axis offset/range information
 *		(if gridtype=0, will be in the form
 *			x.xxxxexx  x.xxxxexx
 *		 where the first number is the offset at the center line,
 *		 and the second is the amount of change per division)
 *
 *		(if gridtype=1-3, will be in the form
 *			10^x  y
 *		  where 'x' will be an integer in range +/- 19.
 *		  this refers to the value at the left edge of the plot.
 *		  'y' will be an integer, either 1,3, or 10.  This is
 *		  actually redundant, but what the hell.)
 *
 *		(if gridtype=4-6, will be in the form
 *			2^x  y
 *		  where 'x' will be an integer in range +/- 19.
 *		  this refers to the value at the left edge of the plot.
 *		  'y' will be an integer, either 1,3, or 10.  This is
 *		  actually redundant, but what the hell.)
 *
 *	 7:  The y-axis offset/range information
 *		This will be 1-4 lines, each containing a pair of
 *		numbers of the format used for the x-axis when gridtype=0
 *
 *	 8:  The actual data
 *		This will be an indeterminant number of lines, each with
 *		an x coordinate and 1-4 y coordinates separated by 
 *		spaces.  The coordinates will be in the range +/- 32K.
 *		The plotting program should clip these coordinates to the
 *		range 0-400 on both axes.  0,0 refers to the bottom left
 *		corner of the grid.
 *		The end of the data will be signalled by the end of the
 *		SPIF file, so needless to say, this field HAS to be the
 *		last field in the SPIF file, should anyone get the urge
 *		to add things to the SPIF format.
 *
 */



/****************/
int PlotFile(name)
       char *name;
/****************/
{
    /* writes the named SPIF file */

    int x,y,i,j,gridtype;
    FILE *spiffile;
    char tmp[128];

    if (expfname(name)) {
        sprintf(tmp,"Unable to create file '%s'",name);
        ErrBox(tmp,3);
        return 1;
        }

    spiffile = fopen(name,"w");
    if (spiffile == 0) {
        sprintf(tmp,"Unable to create file '%s'",name);
        ErrBox(tmp,3);
        return 1;
        }

    /* write header information */
    fprintf(spiffile,"%s\n",FixName(basfname));
    fprintf(spiffile,"%s\n",theAnal->title);

    if      (xscal==LINEAR)   gridtype=0;
    else if (xscal==LOG10)    gridtype=1+L10Range;
    else /* (xscal==OCTAVE)*/ gridtype=4+OctRange;
    fprintf(spiffile,"%d\n",gridtype);

    fprintf(spiffile,"%d\n",numy);

    fprintf(spiffile,"%s",xlist.label);
    for (i=0; i<numy; i++) fprintf(spiffile,"  %s",ylist[i].label);
    fprintf(spiffile,"\n");

    if (xscal==LINEAR)
        fprintf(spiffile,"%e  %e\n",offsets[0].val,ranges[0].val);
    else if (xscal==LOG10)
        fprintf(spiffile,"10^%d  %d\n",L10Offset,L10Range);
    else /* OCTAVE */
        fprintf(spiffile,"2^%d  %d\n",OctOffset,OctRange);

    for (i=0; i<numy; i++)
        fprintf(spiffile,"%e  %e\n",offsets[i+1].val,ranges[i+1].val);

    /* write data points to file */
    for (i=0; i<numpts; i++) {
        x = xconv(xlist.dat[i]);
        fprintf(spiffile,"%d",x);
        for (j=0; j<numy; j++) {
            y = yconv(j,ylist[j].dat[i]);
            y = 400 - y;            /* reverse direction so that y=0=bottom */
            if (y>32000) y=32000;
            fprintf(spiffile,"  %d",y);
            }
        fprintf(spiffile,"\n");
        }

    fclose(spiffile);
    return 0;
}	


/***************/
int Splotter()
/***************/
{
    /* generates a unique file name (/tmp/spifXXXXXX), writes the SPIF file
       using that name, and then runs SPLOTTER to plot it (and delete it) */

    char name[32];
    int pid;

    strcpy(name,"/tmp/spifXXXXXX");
    mktemp(name);

    if (PlotFile(name)) return 1;

    pid = vfork();

    if (pid==0) {   /* we're in the child's context.  fire up splotter */
        char tmp[128];
        sprintf(tmp,"Executing %s.",SPLOTTER);
        ErrBox(tmp,-1);
        if (execl(SPLOTTER,SPLOTTER,"-i",name,"-u",0) == -1) {
            sprintf(tmp,"Couldn't execute %s.",SPLOTTER);
            ErrBox(tmp,4);
            _exit();  /* exit the child process */
            }
        }
}




/*************************************************************/
DigitalPresets()
/*************************************************************/
{
    /* sets range/offsets to 'best' values for viewing several curves that
       range from 0.0 to 5.0.  'Stacks' them, or some such nonsense. */
 
    int i,m,p;
    double zx1,zx2,zdx,zxm;

    /* do a best fit on the X-axis */
    Calcminmax();
    CalcSdat();
    zx1 = xmin;
    zx2 = xmax;
    zdx = zx2 - zx1;
    zxm = zx1 + zdx/2.0;
    CalcXRange(zx1,zx2,zdx,zxm);
    
    /* set up the y-axis values */
    switch (numy) {
        case 1: m=0;  p=4;                 /* 1V per div */
                offsets[1].val=  2.5;  break;
         
        case 2: m=1;  p=4;                 /* 2V per div */
                offsets[1].val= -2.0;
                offsets[2].val=  6.0;  break;
         
        case 3: m=1;  p=4;                 /* 2V per div */
                offsets[1].val= -4.0;
                offsets[2].val=  2.0;
                offsets[3].val=  8.0;  break;
         
        case 4: m=2;  p=4;                 /* 5V per div */
                offsets[1].val= -15.0;
                offsets[2].val=  -5.0;
                offsets[3].val=   5.0;
                offsets[4].val=  15.0;  break;
        }
     
    for (i=1; i<=numy; i++) {
        ranges[i].multiplier=m;  ranges[i].power=p;
        }
     
    xscal=LINEAR;
}    
     
\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplotgr.c"
fi
echo "Finished archive 2 of ompXB di

bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)

xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE 
output.  It will drive an HP-GL plotter for hardcopy.  It can be used to look
at non-SPICE data, also.  Why, it could be the Neatest Thing Ever.  Probably
not, though.

Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and
4.3, and on random Vaxen under Ultrix 1.2 and 2.0)

  --John Bradley  -  University of Pennsylvania  -  bradley@cis.upenn.edu

Part 3 of 4
----------------------cut here-------------------
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -d ./xsplot`
then
  mkdir ./xsplot
  echo "mkdir ./xsplot"
fi
if `test ! -s ./xsplot/xsplot.c`
then
echo "writing ./xsplot/xsplot.c"
cat > ./xsplot/xsplot.c << '\Rogue\Monster\'
/*
 * xsplot.c  -  Spice Plotting program for the X Window system
 *
 *  Author:    John Bradley, University of Pennsylvania
 *                (bradley@cis.upenn.edu)
 *
 *  Concept:   Filip Fuma, University of Pennsylvania
 *                (fuma@cis.upenn.edu)
 *
 *  Copyright Notice:  Oh, let's see...  The typical stuff, I suppose.
 *      don't be removing our names and claiming you wrote it.  Don't
 *      sell this program, as if people'd actually pay money for it.
 *      There are, of course, no warranties implied, under the "you should
 *      be happy it does anything at all" school of thought.  In short,
 *      don't be a WEASEL.  Other than that, feel free to redistribute the
 *      source, and of course, send us lots of letters telling us how much
 *      you like it, and what great guys we are for writing it.
 *
 *  Copyright 1986,1987, University of Pennsylvania
 *
 */


#define MAIN
#define PREFILE "~/.splotpre"

#include "xsplot.h"

#include <signal.h>
#include <sys/time.h>
#include <setjmp.h>

#ifndef sigmask
#define sigmask(m)      (1 << ((m)-1))
#endif

static int LastClicked = -1;
static int EditButton  = -1;
static int MadeStuff   =  0;



/***********/
crash(disp,err)
Display *disp;
XErrorEvent *err;
/***********/
{
/* a routine that crashes and dumps core.  Useful for tracking X errors*/
    char *st, *tmp="foobar";
    if (err->error_code == BadFont) return;
    st = NULL;
    fprintf(stderr,"Crashing...\n");
    fprintf(stderr,"err=%s\n",XErrDescrip(err->error_code));
    strcpy(st,tmp);
}



/*******************************************/
main(argc, argv)
    int   argc;
    char *argv[];
/*******************************************/
{
    int i, status,dpcs;
    char *strind;

    char *fc, *bc;
    char *geom    = NULL;
    char *display = NULL;
    int rvflag    = 0;      /* don't use reverse video as a default */
    int invkey    = -1;

    Color cdef;
    XEvent event;
    char *def;


    pid = getpid();


    /*********************Defaults*********************/
    fc  = XGetDefault(argv[0], "Foreground");
    bc  = XGetDefault(argv[0], "Background");



    /*********************Options*********************/

    basfname[0]='\0';
    for (i = 1; i < argc; i++) {

        if (argv[i][0] == '=') {
            geom = argv[i];
            continue;
            }

        strind = index(argv[i], ':');

        if(strind != NULL) {
            display = argv[i];
            continue;
            }

        if (argv[i][0] != '-') {   /* the file name */
            strcpy(basfname,argv[i]);
            continue;
            }

        Syntax(argv[0]);
    }

    if (basfname[0] == '\0') Syntax(argv[0]);   /* didn't get a file name */



    /*****************************************************/

    /* Open up the display. */

    if (XOpenDisplay(display) == NULL) {
        fprintf(stderr, "%s: Can't open display '%s'\n",
                argv[0], XDisplayName(display));
        exit(1);
        }

    /* load fonts */
    if ((butfinfo = XOpenFont("6x10"))==NULL)
       FatalError("couldn't open '6x10' font\n");
    butfont=butfinfo->id;

    if ((dlogfinfo = XOpenFont("8x13"))==NULL)
       FatalError("couldn't open '8x13' font\n");
    dlogfont=dlogfinfo->id;


    /* Set up colors and pixmaps. */

    /* Set normal default colors */
    if (!rvflag) { ForeColor=BlackPixel;  BackColor=WhitePixel; }
            else { ForeColor=WhitePixel;  BackColor=BlackPixel; }

    dpcs=DisplayCells();

    mono = 1;   /* default is monochrome */

    if (dpcs>2) {      /* if it's a color display, however... */
        int pixels[1],planes,b;
        Color defs[8];

        status=XGetColorCells(1,1,3,&planes,pixels);
        if (planes != 7) {
            fprintf(stderr,"XGetColorCells: planes=%d!\n",planes);
            status=0;
            }

        if (status) {
            b=pixels[0];
            for (i=0; i<8; i++) defs[i].pixel = b+i;
            /* set up default colors */
            XParseColor("green",     defs);   /* first 4 cols are trace cols */
            XParseColor("red",       defs+1);
            XParseColor("slate blue",defs+2);
            XParseColor("yellow",    defs+3);
            XParseColor("black",     defs+4);
            XParseColor("white",     defs+5);
            XParseColor("firebrick", defs+6);
            XParseColor("medium forest green", defs+7);

            XStoreColors(8,defs);             /* do it */

            /* set up color numbers */
            gridFcol=b+5;    gridBcol=b+4;    /* NOTE: gridBcol MUST be b+4 */
            panFcol =b+5;    panBcol =b+4;
            butFcol =b+5;    butBcol =b+6;
            mainFcol=b+5;    mainBcol=b+2;
            dlgFcol =b+3;    dlgBcol =b+7;
            errFcol =b+5;    errBcol =b+4;
            
            for (i=0; i<4; i++) trcol[i]=b+i;
            mono=0;
            }
        }

    if (dpcs>2&&(fc !=NULL)&&XParseColor(fc ,&cdef)&&XGetHardwareColor(&cdef))
        ForeColor=cdef.pixel;

    if (dpcs>2&&(bc !=NULL)&&XParseColor(bc ,&cdef)&&XGetHardwareColor(&cdef))
        BackColor=cdef.pixel;

    if (mono) {
        gridFcol = panFcol = butFcol = mainFcol = dlgFcol = errFcol=ForeColor;
        gridBcol = panBcol = butBcol = mainBcol = dlgBcol = errBcol=BackColor;
        for (i=0; i<4; i++) trcol[i]=ForeColor;
        }
        
    /**************** parse/load spice file *****************/
    InitVars();
    OpenFiles();

    /**************** Create/Open X Resources ***************/
    CreateStuff();
    CreateMainWindow(argv[0],geom);
    CreateSubwindows();
    CreateButtons();

    XSelectInput(mainW, ExposeWindow|ButtonReleased|ButtonPressed|KeyPressed);

    /* map all the windows, except for the command window, and the dlogs.
       Map the subwindows except for the ones in offsetW and measureW,
       as ChangedAnal does that (to avoid redraw).  Note that this
       prevents me from simply doing XMapSubwindows on mainW */

    XMapWindow    (mainW);
    XMapWindow    (titleW);
    XMapWindow    (gridW);
    XMapWindow    (presetW);
    XMapWindow    (traceW);
    XMapWindow    (scaleW);
    XMapWindow    (measureW);
    XMapWindow    (offsetW);
    XMapWindow    (modifyW);
    XMapWindow    (miscW);
    XMapWindow    (errW);

    XMapSubwindows(presetW);
    XMapSubwindows(traceW);
    XMapSubwindows(scaleW);
    XMapSubwindows(commandW);
    XMapSubwindows(modifyW);
    XMapSubwindows(miscW);

    /* map x range/offset buttons, as these are NOT mapped in ChangedAnal */
    XMapWindow(butts[2].win);
    XMapWindow(butts[3].win);

    XSetIconWindow(mainW,iconW);

    XDefineCursor (mainW,arrow);

    /********************************************/

    ChangedAnal();
    XErrorHandler(crash);
    MadeStuff=1;    /* redirect ErrBox output to errW */
    InitDivers();

    /**************** Main loop *****************/
    while (1) {
        XNextEvent(&event);
        HandleEvent(&event);
        }
}



/****************/
HandleEvent(event)
    XEvent *event;
/****************/
{
    int i;
    Window wind;

    switch (event->type) {
        case ExposeWindow: {
            XExposeWindowEvent *exp_event = (XExposeWindowEvent *) event;
            wind = exp_event->window;

            /* figure out what redraw routine to call */

            if      (wind==mainW)     DrawWindow();
            else if (wind==iconW)     RedrawIcon();
            else if (wind==titleW)    DrawTitleBar();
            else if (wind==gridW)     DrawGwin();
            else if (wind==errW)      RedrawErrBox();
            else if (wind==dlogW)     RedrawDlog();
            else if (wind==diversW)   RedrawDivers();
            else if (wind==AboutDlog) RedrawAbout();

            else if (wind==presetW)  RedrawPanel(wind,PREW,"User Presets");
            else if (wind==traceW)   RedrawPanel(wind,TRAW,"Trace Location");
            else if (wind==scaleW)   RedrawPanel(wind,SCAW,"Grid Type");
            else if (wind==measureW) RedrawPanel(wind,MSRW,"Measurement");
            else if (wind==modifyW)  RedrawPanel(wind,MODW,"Modify");
            else if (wind==miscW)    RedrawPanel(wind,MISW,"Misc.");
            else if (wind==commandW) RedrawPanel(wind,OFFW,"Alternate Commands");
            else if (wind==offsetW)  RedrawOffPan();

            else {
                if (dlogW) {
                    for (i=0; i<3; i++) 
                        if (dbutts[i].win==wind) {RedrawBut(dbutts+i); break;}
                    if (dlogW == CurvDlog) {
                        for (i=0; i<8; i++) 
                            if (curvbutts[i].win==wind) {RedrawBut(curvbutts+i); break;}
                        }
                    }
               
                for (i=0; i<MAXBUT; i++)
                    if (butts[i].win==wind) { RedrawBut(butts+i); break; }

                for (i=0; i<4; i++)
                    if (CButts[i].win==wind) { RedrawCB(i); break; }
                }
            
            }
            break;

        case ButtonPressed: {
            XButtonEvent *but_event = (XButtonEvent *) event;
            wind = but_event->window;

            /* if dlog window up, mouse events outside dlog are tossed away */
            if (dlogW) {
                /* only left button clicks do anything */
                if ((but_event->detail & 0xff) == LeftButton) {

                    if (wind==dlogW) {
                        ClickDlog(but_event->x,but_event->y);
                        }
                    }
                }

             else {
                /***************/
                /* LEFT BUTTON */
                /***************/

                if ((but_event->detail & 0xff) == LeftButton) {

                    if (wind == titleW) {
                        InvTitleBar();
                        Credits();
                        }                        
                            
                    if (wind == gridW) {
                        TrackMeasure(but_event->x,but_event->y);
                        break;
                        }
    
                    for (i=0; i<MAXBUT; i++) /* see if it's a control button */
                      if (butts[i].win==wind) {
                          InvertBut(butts+i);
                          LastClicked = i;
                          break;
                          }
    
                    if (i!=MAXBUT) break;    /* found it already */
    
                    for (i=0; i<4; i++) {    /* see if it's a color button */
                      if (CButts[i].win==wind) {
                        if (i!=selCB) {
                          int j=selCB;  selCB=i;
                          RedrawCB(j);
                          RedrawCB(i);
                          DrawArrs();
                          }
                        break;
                        }
                      }
    
                    }
    
                /***************/
                /* MID. BUTTON */
                /***************/

                else if ((but_event->detail & 0xff) == MiddleButton) {
                    if (wind == gridW) TrackSBox(but_event->x,but_event->y);
                    else BigPicture();          /* BigPicture command */
                    }
    
                /****************/
                /* RIGHT BUTTON */
                /****************/
    
                else if ((but_event->detail & 0xff) == RightButton) {
                    if (wind == titleW) OpenDivers();
                    else if (wind == gridW) Track159Box(but_event->x,but_event->y);
                    else { PlotData(); SetUndo(); }    /* redraw command */
                    }
                }
            }
            break;

        case ButtonReleased: {
            XButtonEvent *but_event = (XButtonEvent *) event;

            if ((but_event->detail & 0xff) == LeftButton) Click();
            }
            break;
                    
        case KeyPressed: {
            XKeyEvent *key_event = (XKeyEvent *) event;
            char *st;  int cnt;

            st = XLookupMapping(key_event,&cnt);
            if (dlogW) DlogKey(st,cnt);
            }
            break;

        default:
            printf("event type=%ld\n",event->type); 
            FatalError("Unexpected X_Event");

        }  /* end of switch */
}


/***********************************/
Syntax(call)
 char *call;
{
    printf ("Usage: %s filename [display] [=geometry]\n",call);
    exit(0);
}


/***********************************/
FatalError (identifier)
       char *identifier;
{
    fprintf(stderr, "xsplot: %s\n", identifier);
    exit(1);
}


/***********************************/
InitVars()
{
    tbInvert=0;
    selCB=0;
    comUp=0;
    NOPARSE =0;
    dlogW = 0;
    ylock=0;
    L10Offset = L10Range = OctOffset = OctRange = 0;
}


/***********************************/
ChangedAnal()
{
    /* loaded a different anal.  redraw the "file:  analysis" string,
       do a bestfit, redraw x control if necessary */

    int tmp;

    DrawWindow();
    /* choose xscal based on anal.type */
    if (theAnal->type==AC) xscal=LOG10;  else xscal=LINEAR;

    BestFit();
    ChangedCurves();
}


/***********************************/
ChangedCurves()
{
    /* changed curves.  since numy could now be different, map/unmap 
       numy-dependent stuff, copy strings to buttons */

    int i;

    /* map/unmap offset/range/color buttons */
    for (i=0; i<4; i++) {
        if (i<numy) {
            XMapWindow(butts[i*2+4].win);
            XMapWindow(butts[i*2+5].win);
            XMapWindow(CButts[i].win);
            }
        else {
            XUnmapWindow(butts[i*2+4].win);
            XUnmapWindow(butts[i*2+5].win);
            XUnmapWindow(CButts[i].win);
            }
        }

    if (selCB>=numy) {  /* map the selected CB to a valid CB (if nec.) */
        i=selCB;  selCB=0;  RedrawCB(i);  RedrawCB(0);
        }

    ChangedSettings();
    SetUndo();  SetUndo();   /* clear the undo buffer */
}


/***********************************/
ChangedSettings()
{
    /* changed the range/offset settings through zooming, digital, presets,
       etc.  Reset the button strings */

    int i;

    /* set range/offset button strings */
    for (i=0; i<=numy; i++) {
        R2Str(i);  butts[3+i*2].st = ranges[i].str;
        O2Str(i);  butts[2+i*2].st = offsets[i].str;
        }
    SetXButs();

}


/***********************************/
RedrawSettings()
{
    int i;
    Pixmap tmpPix;

    if (comUp) {		/* Alt Commands window up.  close it */
        Com2Ctrl();
        }
    else {			/* redraw range/offset buttons */
        tmpPix = XPixmapSave(offsetW,0,0,OFFW,OFFH);  /* save the bits */
        if (tmpPix) {
            ComZoom(offsetW);       /* only do the effect if bits saved */
            XClipDrawThrough(offsetW);
            XPixmapPut(offsetW,0,0,0,0,OFFW,OFFH,tmpPix,GXcopy,AllPlanes);
            XClipClipped(offsetW);
            XFreePixmap(tmpPix);
            }
        for (i=2; i<12; i++) RedrawBut(butts+i);
        }
    RedrawBut(&butts[0]);
}


/***********************************/
DrawWindow()
{
    char str[256];

    XClear(mainW);
    sprintf(str,"%s:  %s",FixName(basfname),theAnal->title);
    XText(mainW,215-XStringWidth(str,butfinfo,0,0)/2,30,
          str,strlen(str),butfont,mainFcol,mainBcol);
}


static int errInv=0;

/***********************************/
RedrawErrBox()
{
    if (errInv) 
         XText(errW,6,1,errstr,strlen(errstr),butfont,errBcol,errFcol);
    else
         XText(errW,6,1,errstr,strlen(errstr),butfont,errFcol,errBcol);
}


/***********************************/
ErrBox(str,delay)
char *str;
short delay;
{
    /* positive delay does 'effect', waits 'delay' seconds */
    /* 0 delay redraws ErrBox with different string */
    /* negative delay does effect, but no delay */

    int i,col;

    strcpy(errstr,str);

    if (errInv) col=errBcol;  else col=errFcol;

    if (MadeStuff) {  /* only draw stuff if window has been opened up */
        int xm,ym,w;

        if (delay) {
            if (errInv) XChangeBackground(errW,errBpix);
                   else XChangeBackground(errW,errFpix);
            errInv = !errInv;

            xm = (WIDTH-20) / 2;  ym=6;  w=WIDTH-20;
            for (i=0; i<7; i++) {  /* size=(WIDTH-20)x13 */
                XPixSet(errW,xm-(i*w/12),ym-i,i*w/6,i*2+1,col);
                XFlush();
                Timer(50000L);
                }
            }
        else {
            XClear(errW);
            }

        RedrawErrBox();
        XFlush();

        if (delay>0) Timer((long) (delay * 1000000L));  /* wait 'delay' secs */
        }
    else {            /* windows not up, just printf */       
        fprintf(stderr,"%s",errstr);
        if (delay) fprintf(stderr,"\n");
              else fprintf(stderr,"\r");
        }
}


/***********************************/
Click()

/* called when a pushbutton is released.  handles inverting of buttons, and
   if it's a command button, calls the appropriate routine. */

{
    if (LastClicked == -1) return;  /* not sure if this ever happens */

    if (LastClicked<12) {                /* clicked an edit button */
        if (EditButton>=0) InvertBut(&butts[EditButton]);
                                         /* turn off prev but */
        EditButton  = LastClicked;
        LastClicked = -1;
        }

    else { /* clicked some command button */
        switch (LastClicked) {
            case 12:  /* Modification controls */
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
                if (EditButton>=0) ModifyBut(EditButton,LastClicked);
                InvertBut(&butts[LastClicked]);
                break;
            case 19:                              /* Redraw button */
                PlotData();
                SetUndo();
                InvertBut(&butts[LastClicked]);
                break;
            case 20:                              /* Undo button */
                InvertBut(&butts[LastClicked]);
                GetUndo();
                ChangedSettings();
                PlotData();
                RedrawSettings();
                SetUndo();
                break;
            case 21:                              /* Y-Lock button */
                ylock = !ylock;
                break;
            case 22:                              /* Commands button */
                if (comUp) {
                    Com2Ctrl();
                    }
                else {
                    ComZoom(offsetW);
                    XMapWindow(commandW);
                    XUnmapWindow(offsetW);
                    comUp=1;
                    }
                break;
            case 23:                              /* Big Picture button */
                InvertBut(&butts[LastClicked]);
                BigPicture();
                Com2Ctrl();
                break;
            case 24:				  /* Switch Analysis */
                OpenDlog(SwitchDlog);
                break;
            case 25:				  /* Load Data File */
                OpenDlog(LoadDlog);
                break;
            case 26:				  /* Choose Curves */
                OpenDlog(CurvDlog);
                break;
            case 27:				  /* Digital Presets */
                InvertBut(&butts[LastClicked]);
                DigitalPresets();
                ChangedSettings();
                PlotData();
                RedrawSettings();
                SetUndo();
                break;
            case 28:                              /* user preset #1 */
            case 29:                              /*  '     '    #2 */
            case 30:                              /*  '     '    #3 */
            case 31:                              /*  '     '    #4 */
            case 32:                              /*  '     '    #5 */
            case 33:                              /*  '     '    #6 */
            case 34:                              /*  '     '    #7 */
            case 35:                              /*  '     '    #8 */
                InvertBut(&butts[LastClicked]);
                Preset(LastClicked-28);
                ChangedSettings();
                PlotData();
                RedrawSettings();
                SetUndo();
                break;
            case 36:				  /* Set user preset */
                SetPreLoop();
                break;
            case 38:				  /* Plot to 'where' */
                OpenDlog(PlotDlog);
                break;
            case 39:				  /* Help */
                OpenDlog(HelpDlog);
                break;
            case 37:                              /* Quit button */
                InvertBut(&butts[LastClicked]);
                Quit();
                break;
            }
        LastClicked = -1;
        }
}


/***********************/
SetPreLoop()
/***********************/
{
    /* loop that's called when 'Set' button is pressed.
       handles events until the next mouse event
       if mouse event is a LeftClick in one of the preset butts (28-35)
         then call SetPreset
         else turn 'set' button off, handle mouse event, and leave */

    int i,j;
    XEvent event;
    Window wind;

    while (1) {
        XNextEvent(&event);
        if (event.type != ButtonPressed) HandleEvent(&event);
        else {
            XButtonEvent *but_event = (XButtonEvent *) &event;
            wind = but_event->window;

            if ((but_event->detail & 0xff) != LeftButton) {
                InvertBut(&butts[36]);
                HandleEvent(&event);
                }
            else {  /* well, it's a leftclick... */
                for (i=28; i<37 && (wind!=butts[i].win); i++);

                if (i==36) { /* clicked the 'Set' button again */
                    InvertBut(&butts[36]);
                    }
                else if (i==37) { /* wasn't a preset button */
                    InvertBut(&butts[36]);
                    HandleEvent(&event);
                    }
                else {       /* WAS one of the preset buttons */
                    InvertBut(&butts[i]);
                    XFlush();
                    for (j=0; j<7; j++) {    /* flash the 'set' and '#' buts */
                        InvertBut(&butts[i]);
                        InvertBut(&butts[36]);
                        XFlush();
                        Timer(100000L);
                        }
                    SetPreset(i-28);
                    }
                }
            break;   /* break out of the infinite loop on ANY ButtonPress */
            }
        }
}

        

/***********************/
ComZoom(win)
Window win;
{
    /* gratuitous zoom effect for changing between AltCommands and RangeOffset
       windows */

    /* note:  the '11' is so that only the lower part of the window gets 
       zoomed.  zooming doesn't overwrite the titlebar part of the window 
       (which, coincidentally, is 11 pixels high) */

    short i,x,y,w,h;

    XClipDrawThrough(win);

    for (i=1; i<=15; i++) {
        w = OFFW*i/15;
        h = (OFFH-11)*i/15;
        x = OFFW/2 - w/2;
        y = 11 + (OFFH-11)/2 - h/2;
        XTileFill(win,x+1,y+1,w,h,panBpix,0,GXcopy,AllPlanes);
        Frame(win,x,y,x+w,y+h,1,panFcol,GXcopy);
        XFlush();
        Timer(30000L);
        }
    XClipClipped(win);
}


/******************/
Com2Ctrl()
{
    /* closes commands window, brings up range window, in amusing fashion */

    ComZoom(commandW);
    XMapWindow(offsetW);
    XUnmapWindow(commandW);
    comUp=0;
    if (butts[22].invert) InvertBut(&butts[22]);  /* turn command button off */

}


/******************/
TrackMeasure(x,y)
int x,y;
{
    /* tracks the measuring tool, and show measurments when done */

    float zx,zy,zx1,zy1,zdx,zdy,CalcX(),CalcY();
    char vals[100],vals1[16],vals2[16],vals3[16],vals4[16],vals5[16];

    short x1,y1,state;
    int i,xn,yn;
    Window subw;
    Pixmap tmpPix;

    XDefineCursor(gridW,cursx);
    /* while dragging the tool, show a different cursor */

    x1=x;  y1=y;
    InvertCross(x,y,x1,y1);

    while ( XQueryMouseButtons(gridW,&xn,&yn,&subw,&state), state&LeftMask) {
        if (xn!=x1 || yn!=y1) {  /* moved */
            InvertCross(x,y,x1,y1);
            x1=xn;  y1=yn;
            InvertCross(x,y,x1,y1);
            }
        }
    
    InvertCross(x,y,x1,y1);
    XUndefineCursor(gridW);

    /* if ended up outside the gridrect, don't do anything */

    if (x1<GLeft || x1>GRight || y1<GTop || y1>GBottom)
        sprintf(vals,"");

    else {
        zx =CalcX(x);
        zx1=CalcX(x1);
        zdx=zx1-zx;

        zy = CalcY(y,selCB);
        zy1= CalcY(y1,selCB);
        zdy=zy1-zy;

        FpToEng(vals1,zx1);
        FpToEng(vals2,zy1);
        FpToEng(vals3,zdx);
        FpToEng(vals4,zdy);
        if (zdx!=0.0) FpToEng(vals5,zdy/zdx);
        else          sprintf(vals5," infinity");

        if (zdx==0.0 && zdy==0.0) 
            sprintf(vals,"X:%-11.11s  Y:%-11.11s",vals1,vals2);
        else
            sprintf(vals,"X:%-11.11s  Y:%-11.11s    dX:%-11.11s  dY:%-11.11s    dY/dX:%-11.11s",vals1,vals2,vals3,vals4,vals5);
        }

     ErrBox(vals,-1);
}


/******************/
InvertCross(x,y,x1,y1)
int x,y,x1,y1;
{
    /* draws an L-shaped thing from x,y to x1,y1.  Only checks position 
       of x1,y1, as x,y is known to be inside the grid. */

    if (x1<GLeft || x1>GRight)  return;
    if (y1<GTop  || y1>GBottom) return;

    SetVertex(curve+0,x,y,0);
    SetVertex(curve+1,x,y1,0);
    SetVertex(curve+2,x1,y1,0);

    if (mono) XDraw(gridW,curve,3,1,1,ForeColor,GXinvert,1);
         else XDraw(gridW,curve,3,1,1,ForeColor,GXinvert,4+selCB);
}


/***********************/
Track159Box(x,y)
short x,y;
{
    /* tracks the 10-50-90% box */

    short x1,y1,state;
    int i,xn,yn;
    Window subw;

    if (Vis159) Invert159Box(R159[0],R159[1],R159[2],R159[3]);

    XDefineCursor(gridW,cursx);
    /* while dragging the box, show a different cursor */

    x1=x;  y1=y;
    InvertBox(x,y,x1,y1);

    while ( XQueryMouseButtons(gridW,&xn,&yn,&subw,&state), state&RightMask) {
        if (xn!=x1 || yn!=y1) {  /* moved */
            InvertBox(x,y,x1,y1);
            x1=xn;  y1=yn;
            InvertBox(x,y,x1,y1);
            }
        }
    
    XUndefineCursor(gridW);
    InvertBox(x,y,x1,y1);

    /* if ended up outside the gridrect */
    if (x1<GLeft || x1>GRight || y1<GTop || y1>GBottom) Vis159=0;
    else {
        Vis159=1;
        R159[0]=x;  R159[1]=y;  R159[2]=x1;  R159[3]=y1;
        Invert159Box(x,y,x1,y1);
        }
}


InvertBox(x,y,x1,y1)
short x,y,x1,y1;
{
    /* inverts a 1-pix-thick rectangle.  Note that it only checks the range
       of x1,y1, as x,y is known to be inside the grid */

    if (x1<GLeft || x1>GRight)  return;
    if (y1<GTop  || y1>GBottom) return;

    if (x==x1 || y==y1) return;

    MakeRect(x,y,x1,y1);
    Frame(gridW,x,y,x1,y1,1,ForeColor,GXinvert);
}


Invert159Box(x,y,x1,y1)
short x,y,x1,y1;
{
    /* inverts a 1-pix-rectangle and 10, 50, and 90% lines */

    short i,dy;
    int p;

    if (x==x1 || y==y1) return;

    InvertBox(x,y,x1,y1);

    if (x1<x) swap(x,x1,i);
    if (y1<y) swap(y,y1,i);

    dy=y1-y;

    if (mono) p = 1;
         else p = 4 + selCB;

    XLine(gridW,x+1,y+dy*10/100,x1-1,y+dy*10/100,1,1,ForeColor,GXinvert,p);
    XLine(gridW,x+1,y+dy*50/100,x1-1,y+dy*50/100,1,1,ForeColor,GXinvert,p);
    XLine(gridW,x+1,y+dy*90/100,x1-1,y+dy*90/100,1,1,ForeColor,GXinvert,p);
}


/***********************/
TrackSBox(x,y)
short x,y;
{
    /* tracks the scaling box, and zooms in on it when mouse is released */

    short x1,y1,state;
    int i,xn,yn;
    Window subw;

    XDefineCursor(gridW,cursx);
    /* while dragging the box, show a different cursor */

    x1=x;  y1=y;
    InvertSBox(x,y,x1,y1);

    while ( XQueryMouseButtons(gridW,&xn,&yn,&subw,&state), state&MiddleMask) {
        if (xn!=x1 || yn!=y1) {  /* moved */
            InvertSBox(x,y,x1,y1);
            x1=xn;  y1=yn;
            InvertSBox(x,y,x1,y1);
            }
        }
    
    InvertSBox(x,y,x1,y1);
    XUndefineCursor(gridW);
    /* if ended up outside the gridrect, don't zoom */
    if (x1<GLeft || x1>GRight || y1<GTop || y1>GBottom) return;

    if (CalcSRect(x,y,x1,y1)) {
        ChangedSettings();
        PlotData();
        RedrawSettings();
        SetUndo();
        }
}

InvertSBox(x,y,x1,y1)
short x,y,x1,y1;
{
    /* inverts a 2-pix-thick rectangle.  Note that it only checks the range
       of x1,y1, as x,y is known to be inside the grid */

    if (x1<GLeft || x1>GRight)  return;
    if (y1<GTop  || y1>GBottom) return;

    if (x==x1 || y==y1) { return; }

    Frame(gridW,x,y,x1,y1,2,ForeColor,GXinvert);
}

        
/***************************************************/

static int timerdone;

/*******/
onalarm()
/*******/
{
  timerdone=1;
}


/*******/
Timer(val)   /* waits for VAL microseconds */
 long val;
/*******/
{
    struct itimerval it;

    if (val==0) return;
  
    bzero(&it, sizeof(it));
    if (val>=1000000L) {  /* more than 1 second */
        it.it_value.tv_sec = val / 1000000L;
        val %= 1000000L;
        }
    it.it_value.tv_usec = val;
    timerdone=0;
    signal(SIGALRM,onalarm);
    setitimer(ITIMER_REAL, &it, (struct itimerval *)0);
    while (1) {
        sigblock(sigmask(SIGALRM));  /* note:  have to block, so that ALRM */
        if (timerdone) break;    /* doesn't occur between 'if (timerdone)' */
        else sigpause(0);        /* and calling sigpause(0) */
        }
    sigblock(0);                 /* turn ALRM blocking off */
    signal(SIGALRM,SIG_DFL);
}


/*******/
mmove(num,src,des)
  int num;
  char *src,*des;
/*******/
{
    /* copies num bytes from src to des.  Probably won't work on some
       systems, but I couldn't find a handy move routine... */

    int i;

    for (i=0; i<num; i++) *des++ = *src++;
}



/*******/
Quit()
/*******/
{
    XUnmapWindow(mainW);
    killtmps();
    exit(0);
}




/************************************************/
/* functions to deal with undo and user presets */
/************************************************/

#define INTSIZE sizeof(int)
#define DBLSIZE sizeof(double)
#define RECSIZE ( 5*(INTSIZE + INTSIZE + DBLSIZE) + 5*(INTSIZE) )
/* size of a Preset Record.
        5 * ( range.power (int), range.multiplier (int), offset.val (double) )
        + L10Offset/Range OctOffset/Range, and xscal (ints) */

static char UndoBuf[2][RECSIZE];


/*******************/
int Preset(pre)
       int pre;
/*******************/
{
    /* reads preset #pre.  Returns '1' if unable to do it, '0' otherwise */

    int i;
    FILE *fp;
    char fname[128];

    strcpy(fname,PREFILE);
    expfname(fname);

    fp = fopen(fname,"r");
    if (!fp) {
        ErrBox("Unable to open preset file.",3);
        return(1);
        }
    else {
        long offset;
        offset = pre*RECSIZE;
        fseek(fp,offset,0);
        for (i=0; i<5; i++) {   /* read mult,power,and off.val for each ctrl */
            fread(&ranges[i].multiplier,INTSIZE,1,fp);
            fread(&ranges[i].power,     INTSIZE,1,fp);
            fread(&offsets[i].val,      DBLSIZE,1,fp);
            }
        fread(&L10Offset,INTSIZE,1,fp);
        fread(&L10Range, INTSIZE,1,fp);
        fread(&OctOffset,INTSIZE,1,fp);
        fread(&OctRange, INTSIZE,1,fp);
        fread(&xscal,    INTSIZE,1,fp);

        fclose(fp);
        ErrBox("Preset loaded.",-1);
        return(0);
        }
}


/*********************/
int SetPreset(pre)
          int pre;
/*********************/
{
    /* writes preset #pre (with current control vals)  
       creates PREFILE if needed */

    int i;
    long offset;
    FILE *fp;
    char fname[128];

    strcpy(fname,PREFILE);
    expfname(fname);

    fp=fopen(fname,"r");      /* see if file exists */
    if (fp==0) {              /* create if it it doesn't */
        int i,j,mval,pval;
        double dval;
		
        mval = 0;
        pval = 4;
        dval =0.0;

        ErrBox("Creating preset file...",3);
        fp=fopen(fname,"w");
        for (i=0; i<8; i++) {
            for (j=0; j<5; j++) {  /* write mult,power,and off.val for ctrls */
                fwrite(&mval,INTSIZE,1,fp);
                fwrite(&pval,INTSIZE,1,fp);
                fwrite(&dval,DBLSIZE,1,fp);
                }
            fwrite(&mval,INTSIZE,1,fp);
            fwrite(&mval,INTSIZE,1,fp);
            fwrite(&mval,INTSIZE,1,fp);
            fwrite(&mval,INTSIZE,1,fp);
            fwrite(&mval,INTSIZE,1,fp);
            }
        }

    fclose(fp);

    /* write the preset */

    fp = fopen(fname,"a");
    offset = pre*RECSIZE;
    fseek(fp,offset,0);
    for (i=0; i<5; i++) {    /* write mult,power,and off.val for each ctrl */
        fwrite(&ranges[i].multiplier,INTSIZE,1,fp);
        fwrite(&ranges[i].power,     INTSIZE,1,fp);
        fwrite(&offsets[i].val,      DBLSIZE,1,fp);
        }
    fwrite(&L10Offset,INTSIZE,1,fp);
    fwrite(&L10Range, INTSIZE,1,fp);
    fwrite(&OctOffset,INTSIZE,1,fp);
    fwrite(&OctRange, INTSIZE,1,fp);
    fwrite(&xscal,    INTSIZE,1,fp);

    fclose(fp);

    ErrBox("Preset written.",-1);
}


/***************/
SetUndo()
/***************/
{
    /* copies UndoBuf[0] to UndoBuf[1], puts current settings in UndoBuf[0] */

    char *cp;
    int i;

    mmove(RECSIZE,UndoBuf[0],UndoBuf[1]);	/* save previous settings */

    /* put current settings into UndoBuf[0] */
    for (i=0, cp=UndoBuf[0]; i<5; i++) {
        mmove(INTSIZE,&ranges[i].multiplier,cp);  cp += INTSIZE;
        mmove(INTSIZE,&ranges[i].power,     cp);  cp += INTSIZE;
        mmove(DBLSIZE,&offsets[i].val,      cp);  cp += DBLSIZE;
        }

    mmove(INTSIZE,&L10Offset,cp);  cp+=INTSIZE;
    mmove(INTSIZE,&L10Range ,cp);  cp+=INTSIZE;
    mmove(INTSIZE,&OctOffset,cp);  cp+=INTSIZE;
    mmove(INTSIZE,&OctRange ,cp);  cp+=INTSIZE;
    mmove(INTSIZE,&xscal    ,cp);  cp+=INTSIZE;
}


/***************/
GetUndo()
/***************/
{
    /* gets current settings from UndoBuf[1] */

    char *cp;
    int i;

    for (i=0, cp=UndoBuf[1]; i<5; i++) {	/* get each roff */
        mmove(INTSIZE,cp,&ranges[i].multiplier);  cp+=INTSIZE;
        mmove(INTSIZE,cp,&ranges[i].power);       cp+=INTSIZE;
        mmove(DBLSIZE,cp,&offsets[i].val);        cp+=DBLSIZE;
        }

    mmove(INTSIZE,cp,&L10Offset);  cp+=INTSIZE;
    mmove(INTSIZE,cp,&L10Range);   cp+=INTSIZE;
    mmove(INTSIZE,cp,&OctOffset);  cp+=INTSIZE;
    mmove(INTSIZE,cp,&OctRange);   cp+=INTSIZE;
    mmove(INTSIZE,cp,&xscal);      cp+=INTSIZE;
}



FontInfo *bigfinfo;
Font bigfont;

/**********/
Credits()
/**********/
{

    int i,j,k;
    XEvent event;
    Window wind;

    bigfont=0;
    /* load BIG font */
    if ((bigfinfo = XOpenFont("nonb44"))!=NULL) {}
    else if ((bigfinfo = XOpenFont("sbdr40"))!=NULL) {}
    else if ((bigfinfo = XOpenFont("micr25"))!=NULL) {}
    else bigfinfo = dlogfinfo;
    bigfont = bigfinfo->id;
    XFlush();

    /* scroll window contents down */
    for (i = -10; i<=GSIZE; i+=10) {
        XMoveArea(gridW,0,i,0,i+10,GSIZE+10,GSIZE-i-10);
        if (mono) XPixSet(gridW,0,i,GSIZE+10,10,gridFcol);
             else XPixSet(gridW,0,i,GSIZE+10,10,gridBcol);
        XFlush();
        Timer(50000L);
        }

    /* draw window */
    if (mono) XChangeBackground(AboutDlog,gridFpix);
         else XChangeBackground(AboutDlog,gridBpix);
    XMapWindow(AboutDlog);
    

    i=j=0;
    /* handle events until the next mouse event */
    while (1) {
        if (XPending()) {
            XNextEvent(&event);
            if (event.type != ButtonPressed) HandleEvent(&event);
            else break;
            }

        /* amusing (?) animation */
        if (mono) {
            int col;
            i+=5;  if (i>GSIZE) { i=j%5;  j++;  j=j%10; }
            if (j&1) col=gridFcol; else col=gridBcol;
            XLine(AboutDlog, i,0,GSIZE,i,            1,1,col,GXcopy,AllPlanes);
            XLine(AboutDlog, GSIZE,i,GSIZE-i,GSIZE,  1,1,col,GXcopy,AllPlanes);
            XLine(AboutDlog, GSIZE-i,GSIZE,0,GSIZE-i,1,1,col,GXcopy,AllPlanes);
            XLine(AboutDlog, 0,GSIZE-i,i,0,          1,1,col,GXcopy,AllPlanes);
            }
        else {
            i+=5;  if (i>=GSIZE) { i=0;  j+=3;  j&=3; }
            XLine(AboutDlog, i,0,GSIZE,i,            1,1,trcol[j],GXcopy,AllPlanes);
            XLine(AboutDlog, GSIZE,i,GSIZE-i,GSIZE,  1,1,trcol[(j+1)&3],GXcopy,AllPlanes);
            XLine(AboutDlog, GSIZE-i,GSIZE,0,GSIZE-i,1,1,trcol[(j+2)&3],GXcopy,AllPlanes);
            XLine(AboutDlog, 0,GSIZE-i,i,0,          1,1,trcol[(j+3)&3],GXcopy,AllPlanes);
            }
            
        Timer(20000L);
        XFlush();
        }

    
    /* scroll window contents up, filling new area with mainBpix */
    for (i=GSIZE-10; i>=0; i-=10) {
        if (i) XMoveArea(AboutDlog,0,10, 0,0, GSIZE,i);
        XPixSet(AboutDlog,0,i, GSIZE,10, gridBcol);
        XFlush();
        Timer(50000L);
        }

    /* invert title bar back to normal */
    InvTitleBar(); 
    XUnmapWindow(AboutDlog);

    /* jettison bigfont if one was loaded */
    if (bigfont != dlogfont  && bigfont != 0) XFreeFont(bigfont);
}


/***********************/
RedrawAbout()
/***********************/
{
    int bcol,c1,c2,c3;

    if (mono) {
        bcol=gridFcol;  c1=c2=c3=gridBcol;
        }
    else {
        bcol=gridBcol;  c1=trcol[2];  c2=trcol[3];  c3=trcol[0];
        }

    if (bigfont)
        XText(AboutDlog, 200-(XStringWidth("xSplot",bigfinfo,0,0))/2,
              200-(bigfinfo->height/2),
              "xSplot",6, bigfont, c1,bcol);

    XText(AboutDlog, 
          200-(XStringWidth("by John Bradley and Filip Fuma",butfinfo,0,0))/2,
          200+(bigfinfo->height/2)+10,
          "by John Bradley and Filip Fuma",30, butfont, c2,bcol);

    XText(AboutDlog, 200-(XStringWidth(REVDATE,butfinfo,0,0))/2,
          200+(bigfinfo->height/2)+10+butfinfo->height+10,
          REVDATE,strlen(REVDATE), butfont, c3,bcol);
}


\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplot.c"
fi
if `test ! -s ./xsplot/xsplot.l`
then
echo "writing ./xsplot/xsplot.l"
cat > ./xsplot/xsplot.l << '\Rogue\Monster\'
.TH XSPLOT l "30 July 1987" "X Version 10.4"
.SH NAME
xsplot \- An interactive SPICE plotting program
.SH SYNOPSIS
.B xsplot
filename [host:display] [=geometry]
.SH DESCRIPTION
.I xsplot
is an interactive X program that graphically displays the output of SPICE runs
in an oscilloscope-ular fashion.  It will allow you to zoom in on interesting
sections, measure distances and slopes, and draw 10% cutoffs.  It will, with
the help of an auxilliary program, generate hardcopy to an HP-GL plotter.
Rumor has it that there's even an amusing diversion buried in the code.  Why,
it may well be the Neatest Program Ever.  Probably not, though.
.SH OPTIONS
.PP
.TP 14
.B \=geometry
The width and height shouldn't be set by the user, as the default size 
(640x480) is also the only size.  Anything smaller will be ignored, and 
anything larger won't be used.  You can feel free to set the position, though.
.PP
.TP 14
.B \fIhost\fP:\fIdisplay\fP
Normally,
.I xsplot
gets  the host and display number from the environment variable
"DISPLAY".  However, one can specify them explicitly.
The
.I host
specifies which machine to create the
.I xsplot
window on, and
the
.I display
argument specifies the display number.
.SH OPERATION
.PP
Start up 
.I xsplot
on the "diff.out" SPICE file by typing "xsplot diff.out".
With any luck at all, the program should parse the data and open up the main
window.
.PP
Note:  Unless specified otherwise, 'click' means 'clicking the left button'.
.PP
.I The Title Bar:
At the very top of the screen is the title bar.  Clicking on it with the left
button will display the credits.  Click the left button again to make them go
away.
.PP
.I The Grid:
The large grid that takes up most of the main window is where all the data is
actually displayed.  Note that the name of the file and the analysis type are
displayed above the grid.
.PP
.I The Offset/Range Box:
This specifies the values used in graphing the data.  The first pair of values
are used for the (common) x-axis.  Subsequent pairs are used for the y-axes.
In the example, (diff.out:  DC Analysis), the common x-axis is labeled "VIN".
The offset of "0.000 V" means that the center of the screen corresponds to
VIN=0.0V.  The range (50mV) is the amount the x-value changes per division.
The other two pairs of numbers work the same way for the two y-axes.  (Note 
that in the example they are the same, meaning the two curves are plotted in
the same scale.  This doesn't have to be the case, however.)
.PP
.I The Modify Box:
This houses the controls used to modify the offset/range settings and the Scale
settings.  To modify one of these values, click on the value to be modified,
and then click the modification controls.  Click on the Redraw button 
to see the results.
.PP
.I The User Presets Box:
You have the ability to save eight complete sets of control settings.  This
allows you to return to a certain "view" of your data without having to 
play around with the controls.  To save a preset, click on the 
.B Set 
button, and
then click on one of the numbered buttons.  To return to a preset, click on 
one of the numbered buttons.
.PP
.I The Measurement Box:
Up to four buttons will be shown, one for each dataset you have chosen to 
graph (2 in the example).  If you are on a color display, the colors of the
boxes will match the colors of the traces.  On a monochrome display, the 
buttons will have a line drawn in them with the same stipple pattern as the 
related trace.  The box that has the thick frame around it is the 'Active 
Dataset'.  This is the dataset that can be measured at the moment.  (See 
.B
"Cursor Madness!", 
below.)  Note that if all the traces have the same offset/range settings, then
it doesn't matter which one is the active dataset.
.PP
.I The Trace Location Box:
This shows in what directions the active dataset goes off the screen, if any.
.PP
.I The Grid Type Box:
This determines the type of grid that will be used for the x and y axes.  
Currently, the y axis is always 'linear'.  The x axis, however, can be either
'linear', 'log 10', or 'log 2'.  You can change the x axis type by selecting 
the x control and using the modification controls.  Note that as you change
the grid type, the offset/range information for the x-axis changes, also.
Log 10 and log 2 grids are quite similar.  In both cases, the offset, an 
integer power (of 10 or 2, respectively), refers to the left edge of the grid.
The range is either 1, 3, or 10 divisions.  An example of data that should be
viewed on a log scale is the AC Analysis found in the diff.out file.  (See
.B "Switch Analysis", 
below.)
.PP
.I The Miscellaneous Box:
This houses four command buttons.  The first, 
.B Commands,
opens and closes the "Alternate Commands" box.  The second, 
.B Y-Lock,
toggles locking on and off.
When locking is on, any change you make to one of the y-axis offset/range 
controls is carried out on all of them.  This can have the effect of moving
all the traces up or down simultaneously.  The 
.B Undo 
control returns all the settings to their previous values.  The
.B Redraw
button redraws the data, using the current settings.
.PP
.TP 8
.I Alternate Commands Box:
.B Load Data File:
Clicking this will bring up a dialog box in the middle of the grid.
You'll be prompted for the name of a SPICE file to load.  Enter the filename
and hit return, or hit return immediately to cancel the load.

.B Switch Analysis:
Clicking this button will bring up a dialog box listing all the analyses found
in the current SPICE file.  Double-click on the one you'd like to examine.

.B Curves:
While 
.I xsplot
is only capable of displaying four traces at once, a SPICE analysis can have
up to eight traces in it.  This button brings up a dialog box listing all the
curves found in the current analysis.  Select the ones you want and click
.B Ok
, or click
.B Cancel
if you don't want to change curves.

.B Big Picture:
This will bring up a zoomed-all-the-way-out, scaled-to-fit graph of the data.

.B Plot:
This will allow you to generate hard-copy, assuming you have an HP-GL plotter
and a working copy of 
.I splotter.
Choosing 
.B File
will prompt you for a file name to dump the plot data to, for later use.
Choosing
.B Plotter
will dump the plot file to a temporary file, and attempt to exec
"/usr/local/splotter".  It will complain if it is unable to do so.

.B Help:
This may eventually do something useful.  At the moment, it doesn't.  Click the
mouse inside the window to make it go away.

.B Digital:
Viewing Transient Analyses of digital circuits can be unpleasant, as the 
traces constantly overlap at 0V and 5V.  This button will adjust the settings
so that the traces appear stacked on the grid, rather than overlapping.
Provided that the traces range between 0V and +5V, that is.  A good example of
the usefulness of this feature can be seen by loading the data file "sreg.out".

.B Quit:
Exits the program.  Pretty obvious.
.SH MEASURING
.PP
One of the major advantages 
.I xsplot
has over the traditional ".PLOT" that 
SPICE generates is the ability to measure the output.  Clicking the left button
anywhere inside the Grid (or the Big Picture) will give you the x and y 
values associated with that particular screen coordinate.  Clicking and 
dragging the left button inside the Grid/Big Picture will drag an L-shaped 
pair of lines from the original point to the cursor.  Releasing the left 
button will give you the x and y values at the cursor point and the deltas 
between the two points (dX, dY).  It will also give you the slope of the line 
connecting the two points (dY/dX), which can be useful for measuring 
amplification.  Or something.
.PP
Clicking and dragging the RIGHT button inside the Grid/Big Picture will drag
around a rectangle from the original point to the cursor.  When you let go of
the right button, three lines will be drawn inside the box at 10%, 50%, and 90%
of it's vertical range.  This may be useful for measuring rise and fall times
of exponential outputs.  Or maybe not.
.SH ZOOMING
.I xsplot
allows you to directly zoom in on interesting parts of the data without 
fiddling around the the offset/range controls.  To do this, locate a point of
interest (on either the Grid or the Big Picture), and draw a rectangle around
it by clicking the MIDDLE mouse button at one corner, and dragging it to the
opposite corner.  When you let go of the button, the program will zoom in as 
well as it's able to on the data, preserving the nice, round-number-osity of
the range/offset controls.  Also of interest:  simply clicking the middle
button inside the grid area (without dragging it anywhere) will zoom to the
initial 'best-fit' settings.
.SH CURSOR MADNESS!
(a summary of the button usage)
.TP 8
.I Inside the Grid Area:
The LEFT button is used for measuring data.  The MIDDLE button is used for
zooming in.  The RIGHT button is used for drawing 10%, 50%, and 90% cutoffs.
.TP 8
.I Outside the Grid Area:
The LEFT button is used to operate the controls.  The MIDDLE button is a 
shortcut for the Big Picture command.  The RIGHT button is a shortcut for the
Redraw command.
.SH MISCELLANEOUS
.PP
If less than 30 data points are visible on the grid, the actual points will
be drawn, in addition to the lines connecting them.
.PP
.I xsplot
attempts to acquire 8 r/w color cells for it's purposes.  If it succeeds, 
you'll get to use the program in color, the way it was meant to be.  If not,
it'll only use two colors ("xsplot.Foreground" and "xsplot.Background" in your
".Xdefaults" file).  Then again, since it's only likely to fail on a monochrome
display, the two colors probably aren't very meaningful.  Either way, if it
goes into monochrome, traces will be drawn with different stipple patterns.
Decidedly less fun.
.SH LIMITATIONS
.TP 8
* Only the first 1000 data points of an analysis are used.
.TP 8
* Analyses must not have more than 8 dependent (output)
variables.
.TP 8
* There is an upper limit of 20 analyses per file, which should
be more than ANYONE needs.
.TP 8
* There should only be one SPICE run per output file.  If your
SPICE input file has multiple jobs in it, you should split them up first.
.TP 8
* xsplot is fairly hard-wired to the format of SPICE output.  
In particular, things like the number of lines between a title and the 
start of data are expected to remain the same.  It works with the output 
of SPICE 2g.6.  It MAY work with other versions of SPICE, but then again, 
it may not.  I can't guarantee anything.
.TP 8
* xsplot gets it's data from the results of '.PRINT' statements.  You should 
probably strip out any '.PLOT' statements you might have in your input file, 
as they slow the run down, and are Completely Ignored by 
.I xsplot.
They won't interfere with it's ability to parse the file, though.
.TP 8
* xsplot only supports the DC, AC, and TRANSIENT analyses 
generated by SPICE.  It will not display NOISE or FOURIER analyses, for the 
simple reason that I've never seen one.  If some of you analog types out would 
like it to deal with these analyses, kindly send me some data, and I'll see 
what I can do about it.
.SH USING XSPLOT TO VIEW NON-SPICE DATA
On the off chance that you'd like to view some non-SPICE data with
.I xsplot,
it can be done, and it's only slightly painful.  Generate, or edit up a data
file that looks like the one below.  Note that case is important.  The '.PRINT'
line says that the data should be plotted on a linear grid (as the default),
(by virtue of being a DC analysis), specifies the number of traces, and their
names.  It is important that the 'DC ANALYSIS' line start in column 0, and be
typed EXACTLY as shown here.  The 8 ignored lines can be blank.  After that
comes the actual data points.  The first number on each line is the common 
x-value, and the other numbers are the y-values (1-8, depending on the number
of labels specified in the .PRINT line).  The end of data coincides with the
end of the file.  Note:  if the data would look more appropriate on a 
logarithmic grid, change the two 'DC's to 'AC'.  Also, note that you can't
specify the x-axis label.  The x-axis will always be labeled
'VIN' for a DC analysis, and 'FREQ' for an AC analysis.  Nothing can be done
about this, as far as 
.I xsplot
is concerned.  For hard-copy, however, you can edit the SPIF file before 
sending it to the plotter.  See "The SPIF Spec", below.
.SH THE SPIF SPEC
When you tell 
.I xsplot
to plot, it will generate a file in this format, and (hopefully) 'splotter' 
will be able to drive the actual plotter.
.PP
SPIF files are plain text files, and can be easily created/edited with any
text editor.
.TP 25
The First Line:       The name of the SPICE file.
.TP 25
The Second Line:      The name of the analysis.
.TP 25
The Third Line:       The grid type  (an integer)
(0=Linear)
(1=Log 10, 1 division)
(2=Log 10, 3 divisions)
(3=Log 10, 10 divisions)
(4=Log 2, 1 division)
(5=Log 2, 3 divisions)
(6=Log 2, 10 divisions)
.TP 25
The Fourth Line:      The number of curves in the plot.
(an integer, from 1 to 4).
.TP 25
The Fifth Line:       The names of the axes 
(2-5 words, separated by spaces).
The first word is the name of the (common) x-axis.  The second (and following)
words are the names of the curves.
.TP 25
The Sixth Line:       The x-axis offset and range info.

If the grid type equals 0, this line will be in the form "x.xxxExx  x.xxxExx",
where the first number is the offset, and the second, the range.

If the grid type equals 1,2, or 3, the line will be in the form "10^x  y",
where x is an integer in the range +/-19, and 10^x is the value at the left
edge.  y will be an integer, either 1,3, or 10, specifying the number of 
divisions.

If the grid type 4,5, or 6, this line will be in the form "2^x  y", where x is
an integer in the range +/-19, and 2^x is the value at the left edge.  y will
be an integer, either 1,3 or 10, specifying the number of divisions.
.TP 25
The Seventh Line:     The y-axis offset and range info.
There will be from 1 to 4 lines (depending on the number of curves).  Each line
will be in the form "x.xxxxExx  x.xxxxExx" where the first number is the
offset, and the second number is the range.
.TP 25
The Rest of the File: This will be an indeterminant number of
lines, each with an x-coordinate and 1-4 y-coordinates separated by spaces.

The coordinates will be integers in the range +/- 32K.  The plotting program
should clip these coordinates to the rante 0-400 on both axes (0,0 = 
bottom-left).

The end of the data will coincide with the end of the SPIF file.
.SH BUGS
If you are foolish enough to try to plot negative values on a log scale, the 
program will treat them as '0'.  The resulting graph probably won't look the
way you'd expect, but you should be doing such a thing anyhow...
.SH AUTHOR
John Bradley, University of Pennsylvania  (bradley@cis.upenn.edu)
.SH DESIGNER
Filip Fuma, University of Pennsylvania  (fuma@cis.upenn.edu)
\Rogue\Monster\
else
  echo "will not over write ./xsplot/xsplot.l"
fi
echo "Finished archive 3 of 4"
exit

bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)

xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE 
output.  It will drive an HP-GL plotter for hardcopy.  It can be used to look
at non-SPICE data, also.  Why, it could be the Neatest Thing Ever.  Probably
not, though.

Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and
4.3, and on random Vaxen under Ultrix 1.2 and 2.0)

  --John Bradley  -  University of Pennsylvania  -  bradley@cis.upenn.edu

Part 4 of 4
------------------------cut here----------------------
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -d ./xsplot`
then
  mkdir ./xsplot
  echo "mkdir ./xsplot"
fi
if `test ! -s ./xsplot/Makefile`
then
echo "writing ./xsplot/Makefile"
cat > ./xsplot/Makefile << '\Rogue\Monster\'
INCLUDES = ./include
XLIB = -lX
CFLAGS = -I$(INCLUDES)
CLIBS = -lm

OBJS = xsplot.o xsplotctl.o xsplotmac.o xsplotgr.o xsplotio.o xsplotdlg.o \
       xsplotdiv.o

all: xsplot

xsplot: $(OBJS) $(INCLUDES)/xsplot.h
	cc $(CFLAGS) -o xsplot $(OBJS) $(XLIB) $(CLIBS)

$(OBJS): $(INCLUDES)/xsplot.h

clean:
	rm -f $(OBJS)
\Rogue\Monster\
else
  echo "will not over write ./xsplot/Makefile"
fi
if `test ! -s ./xsplot/README`
then
echo "writing ./xsplot/README"
cat > ./xsplot/README << '\Rogue\Monster\'
Installation notes:  It should.  Without problems.  If you intend to do any
plotting, you should define SPLOTTER in xsplotgr.c to reflect where splotter
is installed.  Or maybe you should just install splotter in /usr/local, like
any NORMAL person.  See the splotter for further hard-copy related information.

Another thing you may want to change is the function 'crash()' in xsplot.c.
This function is called whenever an XError happens, and dumps core.  This is
helpful to me (to aid in debugging) but isn't necessarily something you'd want
it doing in production.  You can easily modify it NOT to crash.

I've personally tested this on a (monochrome) IBM RT PC running 4.2, and a 
(colorful) MicroVax II GPX running Ultrix 2.0.  It compiles on both with no 
changes, and since I don't do any sort of hairy FP or bizarre OS calls, 
it should work on virtually anything.  At the start of the program, it 
attempts to grab 8 r/w color cells.  If it succeeds, it'll run in color, if 
not, it stipples things in b/w.  Needless to say, the color version is much 
more entertaining.

It may also interest you to know that this program points out a couple of bugs
in the 10.4 RT implementation of X.  In particular, XDrawDashed doesn't.  Also,
XDraw has this annoying misfeature that causes it to reset the line pattern
for each line segment that it draws.  The practical upshot of which is, if your
line segments are short, you only ever see the first couple bits of the line
pattern.  This prevented me from making the monochrome line patterns vastly
different, as I can only count on the first two or three pixels being drawn.
(Can't even count on that, actually, but that's the way it is.)  If you're
running on a monochrome display that keeps the draws the lines properly no
matter how close the points are, you may (or may not) want to make the 
patterns different-er.  Or maybe you ought to just run it on a color display,
like a Real Man.

About the colors:  I don't care if you don't like the colors.  After all, what
do YOU know?  (Actually, I'm not too crazy about them myself, but I limited 
myself to 8 colors (so it'll run on lame 4-plane displays, such as these HP
bobcats we've got lying around), so there wasn't too much choice involved.)
If you think you can do better, go for it.  You're also welcome to modify it
to use 16 or 32 colors, which should be more than sufficient.

Limitations of xsplot:  xsplot will deal with a maximum of 1000 data points,
in any single analysis.  There's no fundamental reason WHY, and you could
certainly change MAXPTS (in include/xsplot.h) to something larger, if this is
a problem.  1000 seems like a fine number to me, though.  Besides, there's 
historical reasons.  Be sure to change the appropriate number in splotter, 
also, if you plan to be running it.  

Also, there's a limit of 20 analyses per file (more than enough, I should 
think).  These analyses may have up to 8 dependent variables, of which any
4 can be seen at once.

A somewhat more realistic limitation of xsplot is that it only currently 
supports the DC, AC, and Transient analyses of SPICE.  Noise, Fourier, and
whatever other simulations SPICE can handle AREN'T dealt with.  This hasn't
proved to be a limitation in our lab (digital stuff, mostly), but I could see
it being a problem for some of you RF-types out there, or whatever, so if 
someone sends me examples of these analyses, I'll probably throw them into
xsplot, also.  ("Dammit Mister, I'm a Scientist, not an Engineer!")

Likewise, if you have some SPICE file that xsplot doesn't parse correctly,
and you think it should, send it to me, and I'll see what I can do about it.

Rumor has it that that there's a gratuitous bit of entertainment in the code.
Find it.


John Bradley  -  University of Pennsylvania  -  bradley@cis.upenn.edu

\Rogue\Monster\
else
  echo "will not over write ./xsplot/README"
fi
if `test ! -s ./xsplot/diff.out`
then
echo "writing ./xsplot/diff.out"
cat > ./xsplot/diff.out << '\Rogue\Monster\'
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     INPUT LISTING                    TEMPERATURE =   27.000 DEG C

0***********************************************************************



 .WIDTH IN=72 OUT=80     
 .OPT ACCT LIST NODE LVLCOD=2    
 .TF V(5) VIN    
 .DC VIN -0.25 0.25 0.005
 .AC DEC 10 1 10GHZ      
 .TRAN 5NS 500NS 
 VIN 1 0 SIN(0 0.1 5MEG) AC 1    
 VCC 8 0 12      
 VEE 9 0 -12     
 Q1 4 2 6 QNL    
 Q2 5 3 6 QNL    
 RS1 1 2 1K      
 RS2 3 0 1K      
 RC1 4 8 10K     
 RC2 5 8 10K     
 Q3 6 7 9 QNL    
 Q4 7 7 9 QNL    
 RBIAS 7 8 20K   
 .MODEL QNL NPN(BF=80 RB=100 CCS=2PF TF=0.3NS TR=6NS CJE=3PF CJC=2PF     
 +   VA=50)      
 .PRINT DC V(4) V(5)     
 .PRINT AC VM(5) VP(5)   
 .PRINT TRAN V(4) V(5)   
 .END    
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     CIRCUIT ELEMENT SUMMARY          TEMPERATURE =   27.000 DEG C

0***********************************************************************




0**** RESISTORS
0     NAME        NODES     VALUE  TC1        TC2


      RS1         1    2   1.00D+03   0.00D+00   0.00D+00
      RS2         3    0   1.00D+03   0.00D+00   0.00D+00
      RC1         4    8   1.00D+04   0.00D+00   0.00D+00
      RC2         5    8   1.00D+04   0.00D+00   0.00D+00
      RBIAS       7    8   2.00D+04   0.00D+00   0.00D+00


0**** INDEPENDENT SOURCES
0     NAME        NODES   DC VALUE   AC VALUE   AC PHASE   TRANSIENT


      VIN         1    0   0.00D+00   1.00D+00   0.00D+00  SIN     
0                                          OFFSET.......   0.00D+00
                                           AMPLITUDE....   1.00D-01
                                           FREQUENCY....   5.00D+06
                                           DELAY........   0.00D+00
                                           THETA........   0.00D+00

      VCC         8    0   1.20D+01   0.00D+00   0.00D+00          
      VEE         9    0  -1.20D+01   0.00D+00   0.00D+00          


0**** BIPOLAR JUNCTION TRANSISTORS
0     NAME        C    B    E    S  MODEL       AREA


      Q1          4    2    6    0  QNL        1.000          
      Q2          5    3    6    0  QNL        1.000          
      Q3          6    7    9    0  QNL        1.000          
      Q4          7    7    9    0  QNL        1.000          
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     ELEMENT NODE TABLE               TEMPERATURE =   27.000 DEG C

0***********************************************************************


0      0    RS2      VIN      VCC      VEE      Q1       Q2       Q3      
            Q4      
0      1    RS1      VIN     
0      2    RS1      Q1      
0      3    RS2      Q2      
0      4    RC1      Q1      
0      5    RC2      Q2      
0      6    Q1       Q2       Q3      
0      7    RBIAS    Q3       Q4       Q4      
0      8    RC1      RC2      RBIAS    VCC     
0      9    VEE      Q3       Q4      
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     BJT MODEL PARAMETERS             TEMPERATURE =   27.000 DEG C

0***********************************************************************




             QNL     
0TYPE        NPN   
0IS        1.00D-16
0BF          80.000
0NF           1.000
0VAF       5.00D+01
0BR           1.000
0NR           1.000
0RB         100.000
0CJE       3.00D-12
0TF        3.00D-10
0CJC       2.00D-12
0TR        6.00D-09
0CJS       2.00D-12
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     DC TRANSFER CURVES               TEMPERATURE =   27.000 DEG C

0***********************************************************************



   VIN          V(4)        V(5)        
X
 
 -2.500E-01     1.196E+01  -7.957E-01
 -2.450E-01     1.195E+01  -7.948E-01
 -2.400E-01     1.195E+01  -7.938E-01
 -2.350E-01     1.194E+01  -7.926E-01
 -2.300E-01     1.193E+01  -7.912E-01
 -2.250E-01     1.191E+01  -7.897E-01
 -2.200E-01     1.190E+01  -7.880E-01
 -2.150E-01     1.189E+01  -7.860E-01
 -2.100E-01     1.187E+01  -7.839E-01
 -2.050E-01     1.185E+01  -7.816E-01
 -2.000E-01     1.183E+01  -7.791E-01
 -1.950E-01     1.181E+01  -7.764E-01
 -1.900E-01     1.179E+01  -7.735E-01
 -1.850E-01     1.177E+01  -7.703E-01
 -1.800E-01     1.174E+01  -7.669E-01
 -1.750E-01     1.172E+01  -7.634E-01
 -1.700E-01     1.169E+01  -7.596E-01
 -1.650E-01     1.166E+01  -7.555E-01
 -1.600E-01     1.163E+01  -7.513E-01
 -1.550E-01     1.160E+01  -7.468E-01
 -1.500E-01     1.157E+01  -7.420E-01
 -1.450E-01     1.154E+01  -7.369E-01
 -1.400E-01     1.151E+01  -7.316E-01
 -1.350E-01     1.147E+01  -7.258E-01
 -1.300E-01     1.144E+01  -7.197E-01
 -1.250E-01     1.140E+01  -7.130E-01
 -1.200E-01     1.136E+01  -7.058E-01
 -1.150E-01     1.133E+01  -6.976E-01
 -1.100E-01     1.129E+01  -6.883E-01
 -1.050E-01     1.124E+01  -6.772E-01
 -1.000E-01     1.120E+01  -6.627E-01
 -9.500E-02     1.115E+01  -6.407E-01
 -9.000E-02     1.108E+01  -5.907E-01
 -8.500E-02     1.093E+01  -4.536E-01
 -8.000E-02     1.076E+01  -2.784E-01
 -7.500E-02     1.056E+01  -8.128E-02
 -7.000E-02     1.034E+01   1.382E-01
 -6.500E-02     1.009E+01   3.807E-01
 -6.000E-02     9.827E+00   6.462E-01
 -5.500E-02     9.537E+00   9.346E-01
 -5.000E-02     9.225E+00   1.245E+00
 -4.500E-02     8.891E+00   1.577E+00
 -4.000E-02     8.538E+00   1.929E+00
 -3.500E-02     8.167E+00   2.299E+00
 -3.000E-02     7.779E+00   2.685E+00
 -2.500E-02     7.376E+00   3.086E+00
 -2.000E-02     6.962E+00   3.500E+00
 -1.500E-02     6.537E+00   3.923E+00
 -1.000E-02     6.105E+00   4.354E+00
 -5.000E-03     5.669E+00   4.790E+00
  0.000E+00     5.229E+00   5.229E+00
  5.000E-03     4.790E+00   5.668E+00
  1.000E-02     4.353E+00   6.104E+00
  1.500E-02     3.921E+00   6.536E+00
  2.000E-02     3.497E+00   6.960E+00
  2.500E-02     3.083E+00   7.374E+00
  3.000E-02     2.682E+00   7.776E+00
  3.500E-02     2.294E+00   8.163E+00
  4.000E-02     1.924E+00   8.535E+00
  4.500E-02     1.571E+00   8.887E+00
  5.000E-02     1.238E+00   9.221E+00
  5.500E-02     9.268E-01   9.532E+00
  6.000E-02     6.375E-01   9.822E+00
  6.500E-02     3.708E-01   1.009E+01
  7.000E-02     1.272E-01   1.033E+01
  7.500E-02    -9.349E-02   1.055E+01
  8.000E-02    -2.918E-01   1.075E+01
  8.500E-02    -4.644E-01   1.093E+01
  9.000E-02    -5.416E-01   1.102E+01
  9.500E-02    -5.641E-01   1.107E+01
  1.000E-01    -5.757E-01   1.112E+01
  1.050E-01    -5.829E-01   1.116E+01
  1.100E-01    -5.881E-01   1.119E+01
  1.150E-01    -5.920E-01   1.123E+01
  1.200E-01    -5.949E-01   1.126E+01
  1.250E-01    -5.972E-01   1.130E+01
  1.300E-01    -5.989E-01   1.133E+01
  1.350E-01    -6.003E-01   1.136E+01
  1.400E-01    -6.013E-01   1.140E+01
  1.450E-01    -6.020E-01   1.143E+01
  1.500E-01    -6.025E-01   1.146E+01
  1.550E-01    -6.027E-01   1.149E+01
  1.600E-01    -6.027E-01   1.152E+01
  1.650E-01    -6.026E-01   1.155E+01
  1.700E-01    -6.023E-01   1.158E+01
  1.750E-01    -6.018E-01   1.160E+01
  1.800E-01    -6.011E-01   1.163E+01
  1.850E-01    -6.003E-01   1.165E+01
  1.900E-01    -5.994E-01   1.168E+01
  1.950E-01    -5.982E-01   1.170E+01
  2.000E-01    -5.970E-01   1.173E+01
  2.050E-01    -5.956E-01   1.175E+01
  2.100E-01    -5.940E-01   1.177E+01
  2.150E-01    -5.923E-01   1.179E+01
  2.200E-01    -5.904E-01   1.181E+01
  2.250E-01    -5.884E-01   1.183E+01
  2.300E-01    -5.863E-01   1.185E+01
  2.350E-01    -5.840E-01   1.186E+01
  2.400E-01    -5.815E-01   1.188E+01
  2.450E-01    -5.789E-01   1.189E+01
  2.500E-01    -5.762E-01   1.190E+01
Y
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     SMALL SIGNAL BIAS SOLUTION       TEMPERATURE =   27.000 DEG C

0***********************************************************************


  NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE


 (  1)    0.0000    (  2)   -0.0077    (  3)   -0.0077    (  4)    5.2291

 (  5)    5.2291    (  6)   -0.7700    (  7)  -11.2212    (  8)   12.0000

 (  9)  -12.0000    




     VOLTAGE SOURCE CURRENTS

     NAME       CURRENT


     VIN      -7.661D-06

     VCC      -2.515D-03

     VEE       2.531D-03


     TOTAL POWER DISSIPATION   6.05D-02  WATTS
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     OPERATING POINT INFORMATION      TEMPERATURE =   27.000 DEG C

0***********************************************************************


0
0**** BIPOLAR JUNCTION TRANSISTORS


0            Q1        Q2        Q3        Q4      
0MODEL     QNL       QNL       QNL       QNL     
 IB        7.67E-06  7.67E-06  1.42E-05  1.42E-05
 IC        6.78E-04  6.78E-04  1.37E-03  1.13E-03
 VBE          0.762     0.762     0.779     0.779
 VBC         -5.237    -5.237   -10.451     0.000
 VCE          5.999     5.999    11.230     0.779
 BETADC      88.380    88.380    96.724    80.002
 GM        2.62E-02  2.62E-02  5.29E-02  4.38E-02
 RPI       3.37E+03  3.37E+03  1.83E+03  1.83E+03
 RX        1.00E+02  1.00E+02  1.00E+02  1.00E+02
 RO        8.15E+04  8.15E+04  4.41E+04  4.41E+04
 CPI       1.29E-11  1.29E-11  2.10E-11  1.82E-11
 CMU       1.01E-12  1.01E-12  8.19E-13  2.00E-12
 CBX       0.00E+00  0.00E+00  0.00E+00  0.00E+00
 CCS       2.00E-12  2.00E-12  2.00E-12  2.00E-12
 BETAAC      88.339    88.339    96.683    79.961
 FT        2.99E+08  2.99E+08  3.86E+08  3.44E+08




0****     SMALL-SIGNAL CHARACTERISTICS

0     V(5)/VIN                                 =  8.790D+01
0     INPUT RESISTANCE AT VIN                  =  8.935D+03
0     OUTPUT RESISTANCE AT V(5)                =  9.446D+03
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     AC ANALYSIS                      TEMPERATURE =   27.000 DEG C

0***********************************************************************



     FREQ       VM(5)       VP(5)       
X
 
  1.000E+00     8.790E+01  -8.385E-05
  1.259E+00     8.790E+01  -1.056E-04
  1.585E+00     8.790E+01  -1.329E-04
  1.995E+00     8.790E+01  -1.673E-04
  2.512E+00     8.790E+01  -2.106E-04
  3.162E+00     8.790E+01  -2.652E-04
  3.981E+00     8.790E+01  -3.338E-04
  5.012E+00     8.790E+01  -4.203E-04
  6.310E+00     8.790E+01  -5.291E-04
  7.943E+00     8.790E+01  -6.661E-04
  1.000E+01     8.790E+01  -8.385E-04
  1.259E+01     8.790E+01  -1.056E-03
  1.585E+01     8.790E+01  -1.329E-03
  1.995E+01     8.790E+01  -1.673E-03
  2.512E+01     8.790E+01  -2.106E-03
  3.162E+01     8.790E+01  -2.652E-03
  3.981E+01     8.790E+01  -3.338E-03
  5.012E+01     8.790E+01  -4.203E-03
  6.310E+01     8.790E+01  -5.291E-03
  7.943E+01     8.790E+01  -6.661E-03
  1.000E+02     8.790E+01  -8.385E-03
  1.259E+02     8.790E+01  -1.056E-02
  1.585E+02     8.790E+01  -1.329E-02
  1.995E+02     8.790E+01  -1.673E-02
  2.512E+02     8.790E+01  -2.106E-02
  3.162E+02     8.790E+01  -2.652E-02
  3.981E+02     8.790E+01  -3.338E-02
  5.012E+02     8.790E+01  -4.203E-02
  6.310E+02     8.790E+01  -5.291E-02
  7.943E+02     8.790E+01  -6.661E-02
  1.000E+03     8.790E+01  -8.385E-02
  1.259E+03     8.790E+01  -1.056E-01
  1.585E+03     8.790E+01  -1.329E-01
  1.995E+03     8.790E+01  -1.673E-01
  2.512E+03     8.790E+01  -2.106E-01
  3.162E+03     8.790E+01  -2.652E-01
  3.981E+03     8.790E+01  -3.338E-01
  5.012E+03     8.790E+01  -4.203E-01
  6.310E+03     8.790E+01  -5.291E-01
  7.943E+03     8.789E+01  -6.660E-01
  1.000E+04     8.789E+01  -8.385E-01
  1.259E+04     8.788E+01  -1.056E+00
  1.585E+04     8.788E+01  -1.329E+00
  1.995E+04     8.786E+01  -1.673E+00
  2.512E+04     8.784E+01  -2.105E+00
  3.162E+04     8.781E+01  -2.650E+00
  3.981E+04     8.775E+01  -3.335E+00
  5.012E+04     8.767E+01  -4.195E+00
  6.310E+04     8.753E+01  -5.276E+00
  7.943E+04     8.732E+01  -6.632E+00
  1.000E+05     8.699E+01  -8.328E+00
  1.259E+05     8.647E+01  -1.044E+01
  1.585E+05     8.566E+01  -1.306E+01
  1.995E+05     8.443E+01  -1.629E+01
  2.512E+05     8.258E+01  -2.020E+01
  3.162E+05     7.988E+01  -2.487E+01
  3.981E+05     7.610E+01  -3.029E+01
  5.012E+05     7.107E+01  -3.636E+01
  6.310E+05     6.481E+01  -4.289E+01
  7.943E+05     5.759E+01  -4.957E+01
  1.000E+06     4.988E+01  -5.607E+01
  1.259E+06     4.223E+01  -6.210E+01
  1.585E+06     3.509E+01  -6.751E+01
  1.995E+06     2.876E+01  -7.224E+01
  2.512E+06     2.335E+01  -7.633E+01
  3.162E+06     1.883E+01  -7.990E+01
  3.981E+06     1.512E+01  -8.308E+01
  5.012E+06     1.210E+01  -8.603E+01
  6.310E+06     9.658E+00  -8.889E+01
  7.943E+06     7.683E+00  -9.179E+01
  1.000E+07     6.087E+00  -9.484E+01
  1.259E+07     4.797E+00  -9.815E+01
  1.585E+07     3.753E+00  -1.018E+02
  1.995E+07     2.909E+00  -1.059E+02
  2.512E+07     2.226E+00  -1.103E+02
  3.162E+07     1.677E+00  -1.152E+02
  3.981E+07     1.238E+00  -1.202E+02
  5.012E+07     8.944E-01  -1.252E+02
  6.310E+07     6.313E-01  -1.299E+02
  7.943E+07     4.351E-01  -1.340E+02
  1.000E+08     2.928E-01  -1.370E+02
  1.259E+08     1.933E-01  -1.383E+02
  1.585E+08     1.266E-01  -1.372E+02
  1.995E+08     8.414E-02  -1.334E+02
  2.512E+08     5.800E-02  -1.279E+02
  3.162E+08     4.170E-02  -1.219E+02
  3.981E+08     3.099E-02  -1.164E+02
  5.012E+08     2.353E-02  -1.116E+02
  6.310E+08     1.813E-02  -1.075E+02
  7.943E+08     1.410E-02  -1.041E+02
  1.000E+09     1.105E-02  -1.014E+02
  1.259E+09     8.698E-03  -9.907E+01
  1.585E+09     6.870E-03  -9.723E+01
  1.995E+09     5.437E-03  -9.576E+01
  2.512E+09     4.309E-03  -9.458E+01
  3.162E+09     3.418E-03  -9.364E+01
  3.981E+09     2.713E-03  -9.289E+01
  5.012E+09     2.154E-03  -9.230E+01
  6.310E+09     1.710E-03  -9.182E+01
  7.943E+09     1.358E-03  -9.145E+01
  1.000E+10     1.079E-03  -9.115E+01
Y
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     INITIAL TRANSIENT SOLUTION       TEMPERATURE =   27.000 DEG C

0***********************************************************************


  NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE


 (  1)    0.0000    (  2)   -0.0077    (  3)   -0.0077    (  4)    5.2291

 (  5)    5.2291    (  6)   -0.7700    (  7)  -11.2212    (  8)   12.0000

 (  9)  -12.0000    




     VOLTAGE SOURCE CURRENTS

     NAME       CURRENT


     VIN      -7.661D-06

     VCC      -2.515D-03

     VEE       2.531D-03


     TOTAL POWER DISSIPATION   6.05D-02  WATTS
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     OPERATING POINT INFORMATION      TEMPERATURE =   27.000 DEG C

0***********************************************************************


0
0**** BIPOLAR JUNCTION TRANSISTORS


0            Q1        Q2        Q3        Q4      
0MODEL     QNL       QNL       QNL       QNL     
 IB        7.67E-06  7.67E-06  1.42E-05  1.42E-05
 IC        6.78E-04  6.78E-04  1.37E-03  1.13E-03
 VBE          0.762     0.762     0.779     0.779
 VBC         -5.237    -5.237   -10.451     0.000
 VCE          5.999     5.999    11.230     0.779
 BETADC      88.380    88.380    96.724    80.002
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     TRANSIENT ANALYSIS               TEMPERATURE =   27.000 DEG C

0***********************************************************************



     TIME       V(4)        V(5)        
X
 
  0.000E+00     5.229E+00   5.229E+00
  5.000E-09     5.217E+00   5.237E+00
  1.000E-08     5.172E+00   5.272E+00
  1.500E-08     5.101E+00   5.333E+00
  2.000E-08     5.007E+00   5.417E+00
  2.500E-08     4.897E+00   5.520E+00
  3.000E-08     4.765E+00   5.648E+00
  3.500E-08     4.624E+00   5.787E+00
  4.000E-08     4.470E+00   5.943E+00
  4.500E-08     4.313E+00   6.103E+00
  5.000E-08     4.154E+00   6.270E+00
  5.500E-08     4.000E+00   6.432E+00
  6.000E-08     3.853E+00   6.590E+00
  6.500E-08     3.717E+00   6.736E+00
  7.000E-08     3.597E+00   6.868E+00
  7.500E-08     3.495E+00   6.982E+00
  8.000E-08     3.415E+00   7.073E+00
  8.500E-08     3.356E+00   7.141E+00
  9.000E-08     3.325E+00   7.180E+00
  9.500E-08     3.317E+00   7.194E+00
  1.000E-07     3.339E+00   7.176E+00
  1.050E-07     3.385E+00   7.132E+00
  1.100E-07     3.461E+00   7.057E+00
  1.150E-07     3.558E+00   6.958E+00
  1.200E-07     3.683E+00   6.831E+00
  1.250E-07     3.825E+00   6.686E+00
  1.300E-07     3.988E+00   6.517E+00
  1.350E-07     4.163E+00   6.338E+00
  1.400E-07     4.353E+00   6.144E+00
  1.450E-07     4.545E+00   5.947E+00
  1.500E-07     4.742E+00   5.745E+00
  1.550E-07     4.935E+00   5.549E+00
  1.600E-07     5.121E+00   5.358E+00
  1.650E-07     5.295E+00   5.179E+00
  1.700E-07     5.452E+00   5.016E+00
  1.750E-07     5.591E+00   4.872E+00
  1.800E-07     5.705E+00   4.752E+00
  1.850E-07     5.795E+00   4.654E+00
  1.900E-07     5.855E+00   4.586E+00
  1.950E-07     5.889E+00   4.544E+00
  2.000E-07     5.891E+00   4.533E+00
  2.050E-07     5.867E+00   4.548E+00
  2.100E-07     5.811E+00   4.596E+00
  2.150E-07     5.733E+00   4.666E+00
  2.200E-07     5.627E+00   4.766E+00
  2.250E-07     5.504E+00   4.884E+00
  2.300E-07     5.360E+00   5.026E+00
  2.350E-07     5.206E+00   5.180E+00
  2.400E-07     5.039E+00   5.350E+00
  2.450E-07     4.870E+00   5.524E+00
  2.500E-07     4.698E+00   5.703E+00
  2.550E-07     4.531E+00   5.879E+00
  2.600E-07     4.371E+00   6.051E+00
  2.650E-07     4.223E+00   6.210E+00
  2.700E-07     4.092E+00   6.355E+00
  2.750E-07     3.978E+00   6.481E+00
  2.800E-07     3.887E+00   6.585E+00
  2.850E-07     3.818E+00   6.665E+00
  2.900E-07     3.777E+00   6.715E+00
  2.950E-07     3.760E+00   6.741E+00
  3.000E-07     3.774E+00   6.733E+00
  3.050E-07     3.812E+00   6.700E+00
  3.100E-07     3.880E+00   6.634E+00
  3.150E-07     3.970E+00   6.545E+00
  3.200E-07     4.088E+00   6.427E+00
  3.250E-07     4.223E+00   6.290E+00
  3.300E-07     4.381E+00   6.131E+00
  3.350E-07     4.549E+00   5.960E+00
  3.400E-07     4.731E+00   5.774E+00
  3.450E-07     4.917E+00   5.585E+00
  3.500E-07     5.107E+00   5.391E+00
  3.550E-07     5.292E+00   5.202E+00
  3.600E-07     5.471E+00   5.019E+00
  3.650E-07     5.637E+00   4.849E+00
  3.700E-07     5.787E+00   4.693E+00
  3.750E-07     5.918E+00   4.556E+00
  3.800E-07     6.024E+00   4.443E+00
  3.850E-07     6.107E+00   4.352E+00
  3.900E-07     6.159E+00   4.291E+00
  3.950E-07     6.186E+00   4.254E+00
  4.000E-07     6.181E+00   4.250E+00
  4.050E-07     6.150E+00   4.270E+00
  4.100E-07     6.087E+00   4.323E+00
  4.150E-07     6.003E+00   4.398E+00
  4.200E-07     5.890E+00   4.503E+00
  4.250E-07     5.761E+00   4.626E+00
  4.300E-07     5.611E+00   4.773E+00
  4.350E-07     5.451E+00   4.932E+00
  4.400E-07     5.278E+00   5.107E+00
  4.450E-07     5.103E+00   5.286E+00
  4.500E-07     4.926E+00   5.470E+00
  4.550E-07     4.753E+00   5.651E+00
  4.600E-07     4.588E+00   5.827E+00
  4.650E-07     4.436E+00   5.992E+00
  4.700E-07     4.299E+00   6.142E+00
  4.750E-07     4.180E+00   6.273E+00
  4.800E-07     4.085E+00   6.381E+00
  4.850E-07     4.012E+00   6.466E+00
  4.900E-07     3.967E+00   6.522E+00
  4.950E-07     3.943E+00   6.555E+00
  5.000E-07     3.945E+00   6.560E+00
Y
0
         JOB CONCLUDED
1*******02/04/86 ********  SPICE 2G.6    3/15/83 ********19:57:46*****

0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR                                          

0****     JOB STATISTICS SUMMARY           TEMPERATURE =   27.000 DEG C

0***********************************************************************


   NUNODS NCNODS NUMNOD NUMEL  DIODES  BJTS  JFETS  MFETS

       10     10     14    12       0     4      0      0

0  NUMTEM ICVFLG JTRFLG JACFLG INOISE  IDIST   NOGO
0       1    101    101    101      0      0      0

0  NSTOP   NTTBR   NTTAR   IFILL    IOPS    PERSPA

      17.     57.     57.      0.     94.   80.277

0  NUMTTP  NUMRTP  NUMNIT  MAXMEM  MEMUSE  COPYKNT

       57.      0.    158.  400000    2736    22172.

0         READIN                    1.22
0         SETUP                     0.30
0         TRCURV                    4.95            230.
0         DCAN                      1.02             16.
0         DCDCMP                   1.533              4.
0         DCSOL                    1.000
0         ACAN                      2.90            101.
0         TRANAN                    5.05            158.
0         OUTPUT                    3.25
0         LOAD                     5.250
0         CODGEN                   0.000              0.
0         CODEXC                   0.000
0         MACINS                   0.000
0         OVERHEAD                  0.13
0         TOTAL JOB TIME           18.82
 FORTRAN STOP
\Rogue\Monster\
else
  echo "will not over write ./xsplot/diff.out"
fi
if `test ! -d ./xsplot/include`
then
  mkdir ./xsplot/include
  echo "mkdir ./xsplot/include"
fi
if `test ! -s ./xsplot/include/cursor`
then
echo "writing ./xsplot/include/cursor"
cat > ./xsplot/include/cursor << '\Rogue\Monster\'
#define cursor_width 16
#define cursor_height 16
#define cursor_x_hot 3
#define cursor_y_hot 1
static short cursor_bits[] = {
   0x0000, 0x0008, 0x0018, 0x0038,
   0x0078, 0x00f8, 0x01f8, 0x03f8,
   0x07f8, 0x00f8, 0x00d8, 0x0188,
   0x0180, 0x0300, 0x0300, 0x0000};
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/cursor"
fi
if `test ! -s ./xsplot/include/cursor.mask`
then
echo "writing ./xsplot/include/cursor.mask"
cat > ./xsplot/include/cursor.mask << '\Rogue\Monster\'
#define cursor_mask_width 16
#define cursor_mask_height 16
static short cursor_mask_bits[] = {
   0x000c, 0x001c, 0x003c, 0x007c,
   0x00fc, 0x01fc, 0x03fc, 0x07fc,
   0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
   0x03cc, 0x0780, 0x0780, 0x0300};
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/cursor.mask"
fi
if `test ! -s ./xsplot/include/icon`
then
echo "writing ./xsplot/include/icon"
cat > ./xsplot/include/icon << '\Rogue\Monster\'
#define icon_width 64
#define icon_height 48
static short icon_bits[] = {
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0x49ff, 0xfc92, 0xffff,
   0xffff, 0x49ff, 0xfc92, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff,
   0xaaab, 0xaaaa, 0xaaaa, 0xaaaa,
   0xfffd, 0xffff, 0xffff, 0xffff,
   0x4447, 0x4444, 0xaa44, 0xa2aa,
   0x0005, 0x0040, 0xae00, 0xe2aa,
   0x4447, 0x4444, 0xfa44, 0xbfff,
   0xaaad, 0xaaea, 0x56aa, 0xd555,
   0x4447, 0x4444, 0xfa44, 0xbfef,
   0x0005, 0x0040, 0x0e00, 0xe038,
   0x4447, 0x4444, 0xea44, 0xadab,
   0xaaad, 0xaaea, 0x0eaa, 0xe038,
   0x4447, 0x4444, 0xea44, 0xadab,
   0x0005, 0x0040, 0x0e00, 0xe038,
   0x4447, 0x4444, 0xfa44, 0xbfef,
   0xaaad, 0xaaea, 0x56aa, 0xd555,
   0x4447, 0x4444, 0xfa44, 0xbfff,
   0x0005, 0x0040, 0x0e00, 0xe000,
   0x4447, 0x4444, 0x8a44, 0xafdf,
   0xaaad, 0xaaea, 0xaeaa, 0xefdf,
   0x4447, 0x4444, 0x0a44, 0xa000,
   0x0005, 0x0040, 0x8e00, 0xefdf,
   0x4447, 0x4444, 0xaa44, 0xafdf,
   0xfffd, 0xffff, 0x0fff, 0xe000,
   0x4447, 0x4444, 0x8a44, 0xafdf,
   0x0005, 0x0040, 0xae00, 0xefdf,
   0x4447, 0x4444, 0x0a44, 0xa000,
   0xaaad, 0xaaea, 0x8eaa, 0xefdf,
   0x4447, 0x4444, 0xaa44, 0xafdf,
   0x0005, 0x0040, 0x0e00, 0xe000,
   0x4447, 0x4444, 0xfa44, 0xbfff,
   0xaaad, 0xaaea, 0x56aa, 0xd555,
   0x4447, 0x4444, 0xfa44, 0xbfef,
   0x0005, 0x0040, 0x0e00, 0xe038,
   0x4447, 0x4444, 0xea44, 0xafab,
   0xaaad, 0xaaea, 0x0eaa, 0xe038,
   0x4447, 0x4444, 0x6a44, 0xafab,
   0x0005, 0x0040, 0x0e00, 0xe038,
   0x4447, 0x4444, 0x6a44, 0xafab,
   0xaaad, 0xaaea, 0x0eaa, 0xe038,
   0x4447, 0x4444, 0x6a44, 0xafab,
   0x0005, 0x0040, 0x0e00, 0xe038,
   0x4447, 0x4444, 0xfa44, 0xbfef,
   0xfffd, 0xffff, 0x57ff, 0xd555,
   0xaaab, 0xaaaa, 0xaaaa, 0xaaaa,
   0xffff, 0xffff, 0xffff, 0xffff};
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/icon"
fi
if `test ! -s ./xsplot/include/arrows.h`
then
echo "writing ./xsplot/include/arrows.h"
cat > ./xsplot/include/arrows.h << '\Rogue\Monster\'
#define arr_width 19
#define arr_height 19

static short arrl_bits[] = {           /* left arrow */
   0x0000, 0x0000, 0x0200, 0x0000,
   0x0300, 0x0000, 0x0380, 0x0000,
   0x03c0, 0x0000, 0x03e0, 0x0000,
   0xfff0, 0x0003, 0xfff8, 0x0003,
   0xfffc, 0x0003, 0xfffe, 0x0003,
   0xfffc, 0x0003, 0xfff8, 0x0003,
   0xfff0, 0x0003, 0x03e0, 0x0000,
   0x03c0, 0x0000, 0x0380, 0x0000,
   0x0300, 0x0000, 0x0200, 0x0000,
   0x0000, 0x0000};


static short arrl_mask_bits[] = {      /* left arrow mask */
   0x0600, 0x0000, 0x0700, 0x0000,
   0x0780, 0x0000, 0x07c0, 0x0000,
   0x07e0, 0x0000, 0xfff0, 0x0007,
   0xfff8, 0x0007, 0xfffc, 0x0007,
   0xfffe, 0x0007, 0xffff, 0x0007,
   0xfffe, 0x0007, 0xfffc, 0x0007,
   0xfff8, 0x0007, 0xfff0, 0x0007,
   0x07e0, 0x0000, 0x07c0, 0x0000,
   0x0780, 0x0000, 0x0700, 0x0000,
   0x0600, 0x0000};


static short arrr_bits[] = {           /* right arrow */
   0x0000, 0x0000, 0x0200, 0x0000,
   0x0600, 0x0000, 0x0e00, 0x0000,
   0x1e00, 0x0000, 0x3e00, 0x0000,
   0x7ffe, 0x0000, 0xfffe, 0x0000,
   0xfffe, 0x0001, 0xfffe, 0x0003,
   0xfffe, 0x0001, 0xfffe, 0x0000,
   0x7ffe, 0x0000, 0x3e00, 0x0000,
   0x1e00, 0x0000, 0x0e00, 0x0000,
   0x0600, 0x0000, 0x0200, 0x0000,
   0x0000, 0x0000};

static short arrr_mask_bits[] = {      /* right arrow mask */
   0x0300, 0x0000, 0x0700, 0x0000,
   0x0f00, 0x0000, 0x1f00, 0x0000,
   0x3f00, 0x0000, 0x7fff, 0x0000,
   0xffff, 0x0000, 0xffff, 0x0001,
   0xffff, 0x0003, 0xffff, 0x0007,
   0xffff, 0x0003, 0xffff, 0x0001,
   0xffff, 0x0000, 0x7fff, 0x0000,
   0x3f00, 0x0000, 0x1f00, 0x0000,
   0x0f00, 0x0000, 0x0700, 0x0000,
   0x0300, 0x0000};


static short arru_bits[] = {           /* up arrow */
   0x0000, 0x0000, 0x0200, 0x0000,
   0x0700, 0x0000, 0x0f80, 0x0000,
   0x1fc0, 0x0000, 0x3fe0, 0x0000,
   0x7ff0, 0x0000, 0xfff8, 0x0000,
   0xfffc, 0x0001, 0xfffe, 0x0003,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x0000, 0x0000};

static short arru_mask_bits[] = {      /* up arrow mask */
   0x0200, 0x0000, 0x0700, 0x0000,
   0x0f80, 0x0000, 0x1fc0, 0x0000,
   0x3fe0, 0x0000, 0x7ff0, 0x0000,
   0xfff8, 0x0000, 0xfffc, 0x0001,
   0xfffe, 0x0003, 0xffff, 0x0007,
   0xffff, 0x0007, 0x3fe0, 0x0000,
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0x3fe0, 0x0000};


static short arrd_bits[] = {           /* down arrow */
   0x0000, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0x1fc0, 0x0000,
   0x1fc0, 0x0000, 0xfffe, 0x0003,
   0xfffc, 0x0001, 0xfff8, 0x0000,
   0x7ff0, 0x0000, 0x3fe0, 0x0000,
   0x1fc0, 0x0000, 0x0f80, 0x0000,
   0x0700, 0x0000, 0x0200, 0x0000,
   0x0000, 0x0000};

static short arrd_mask_bits[] = {      /* down arrow mask */
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0x3fe0, 0x0000, 0x3fe0, 0x0000,
   0xffff, 0x0007, 0xffff, 0x0007,
   0xfffe, 0x0003, 0xfffc, 0x0001,
   0xfff8, 0x0000, 0x7ff0, 0x0000,
   0x3fe0, 0x0000, 0x1fc0, 0x0000,
   0x0f80, 0x0000, 0x0700, 0x0000,
   0x0200, 0x0000};

\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/arrows.h"
fi
if `test ! -s ./xsplot/include/titlebar.bm`
then
echo "writing ./xsplot/include/titlebar.bm"
cat > ./xsplot/include/titlebar.bm << '\Rogue\Monster\'
#define titlebar_width 80
#define titlebar_height 20
static short titlebar_bits[] = {
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff,
   0x8fff, 0xffff, 0xffff, 0xffff,
   0x07ff, 0xe7ff, 0xffff, 0xffff,
   0xffff, 0xf3ff, 0xe7fe, 0xfbff,
   0xffff, 0xffff, 0x63ff, 0xe7ff,
   0xf9ff, 0xffff, 0xffff, 0xc779,
   0xe627, 0xe0c1, 0xffff, 0xffff,
   0x8fb2, 0xe4c3, 0xf99c, 0xffff,
   0xffff, 0x1fc7, 0xe4e7, 0xf99c,
   0xffff, 0xffff, 0x37cf, 0xe4e6,
   0xf99c, 0xffff, 0xffff, 0x7b97,
   0x64e6, 0xd99c, 0xffff, 0xffff,
   0x713b, 0xa666, 0xe9cc, 0xffff,
   0xffff, 0x067d, 0xc707, 0xf1e1,
   0xffff, 0xffff, 0xffff, 0xffe7,
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffe7, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffe7, 0xffff, 0xffff,
   0xffff, 0xffff, 0xfff3, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff};
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/titlebar.bm"
fi
if `test ! -s ./xsplot/include/cursx`
then
echo "writing ./xsplot/include/cursx"
cat > ./xsplot/include/cursx << '\Rogue\Monster\'
#define cursx_width 9
#define cursx_height 9
#define cursx_x_hot 4
#define cursx_y_hot 4
static short cursx_bits[] = {
   0x0000, 0x0082, 0x0044, 0x0028,
   0x0000, 0x0028, 0x0044, 0x0082,
   0x0000};
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/cursx"
fi
if `test ! -s ./xsplot/include/cursx.mask`
then
echo "writing ./xsplot/include/cursx.mask"
cat > ./xsplot/include/cursx.mask << '\Rogue\Monster\'
static short cursx_mask_bits[] = {
   0x0183, 0x01c7, 0x00ee, 0x007c,
   0x0038, 0x007c, 0x00ee, 0x01c7,
   0x0183};
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/cursx.mask"
fi
if `test ! -s ./xsplot/include/xsplot.h`
then
echo "writing ./xsplot/include/xsplot.h"
cat > ./xsplot/include/xsplot.h << '\Rogue\Monster\'
/*
 * xsplot.h  -  #defines, global variables, data structures for xsplot
 *
 */

#define REVDATE "Rev: 6/2/87"

/* other include files */
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <strings.h>
#include <X/Xlib.h>

/* constants (array sizes, mostly) */
#define MAXBUT    40     /* number of buttons in controls array */
#define MAXANAL   20     /* maximum number of analyses */
#define MAXPTS    1001   /* maximum number of points in an analysis */
#define MYPERANAL 8      /* maximum number of curves per analysis */

/* Scale Types */
#define LINEAR 0
#define LOG10  1
#define OCTAVE 2

/* Analysis Types */
#define DC    0
#define AC    1
#define TRANS 2

/* bizarrities */
#define DEGSTR "\007"    /* a string containing the degree symbol (6x10 fnt)*/
#define MAXDSTR 58       /* max len of string in LoadDlog box */

/* grid size/position info */
#define GTop         1       /* grid size/position info */
#define GBottom    401
#define GLeft        1
#define GRight     401
#define GLRmid     201
#define GTBmid     201
 
#define GLeftFP      1.0     /* grid size/position info floats, */
#define GRightFP   401.0     /* used in scaling calculations */
#define GTopFP       1.0
#define GBottomFP  401.0
#define GTBmidFP   201.0
#define GLRmidFP   201.0


/* handy-dandy functions */
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? -(a) : (a))
#define swap(a, b, t) {t=a; a=b; b=t;}

/* patterns used for lines in MONO mode.  Also used for grid */
#define PATSOLID 0xffff     /* solid line */
#define PAT2     0xaaaa     /* every other pixel on */
#define PAT4     0x8888     /* every fourth pixel on */
#define PATDASH  0xcccc     /* two on, two off */
#define PATDASH4 0xf0f0     /* four on, four off */
#define PATDDASH 0xf6f6     /* four on, one off, two on, one off */

/* size constants used all over the place */
#define WIDTH  640   /* size of main window */
#define HEIGHT 480
#define GSIZE  400   /* size of grid window */

/* defines for setting up the control panels */
#define CBH 19       /* size of color buttons */
#define CBW 41

#define PANELH 15    /* minimum size of a panel */
#define BUTH (19+5)  /* size of buttons + space between */

#define CTLX 430
#define CTLY 45
#define CTLW 200
#define CTLW2 97

#define PREX CTLX
#define PREY CTLY
#define PREW CTLW
#define PREH (PANELH+BUTH)

#define TRAX CTLX
#define TRAY (PREY+PREH+5)
#define TRAW CTLW
#define TRAH (PANELH+BUTH)

#define SCAX CTLX
#define SCAY (TRAY+TRAH+5)
#define SCAW CTLW2
#define SCAH (PANELH+2*BUTH)

#define MSRX (CTLX+CTLW2+6)
#define MSRY SCAY
#define MSRW CTLW2
#define MSRH (PANELH+2*BUTH)

#define OFFX CTLX
#define OFFY (SCAY+SCAH+5)
#define OFFW CTLW
#define OFFH (PANELH+5*BUTH)

#define MODX CTLX
#define MODY (OFFY+OFFH+5)
#define MODW CTLW2
#define MODH (PANELH+4*BUTH)

#define MISX (CTLX+CTLW2+6)
#define MISY MODY
#define MISW CTLW2
#define MISH (PANELH+4*BUTH)

/* structure definitions */
struct _button { Window   win;
                 short    x,y;
                 short    w,h;
                 char     *st;
                 int      invert;
                 FontInfo *finfo; };
typedef struct _button Button;


struct _cbutton { Window win; };
typedef struct _cbutton CButton;


struct _range { int   power, multiplier;
               double val;
               char   str[20]; };
typedef struct _range Range;


struct _offset { double val;
                 char   str[20]; };
typedef struct _offset Offset;


struct _anal   { char   title[80];
                 char   labels[MYPERANAL+1][32];
                 int    numys, numpts, type; };
typedef struct _anal Anal;


struct _dlist  { float dat[MAXPTS];
                 char  label[32]; };
typedef struct _dlist Dlist;


/* nasty ol' global variables */

#ifndef MAIN
#define WHERE extern
#else 
#define WHERE
#endif

/* X stuff */
WHERE Window   mainW, iconW, titleW, gridW, presetW, traceW, scaleW;
WHERE Window   measureW, offsetW, modifyW, miscW, commandW, errW;
WHERE Window   dlogW, LoadDlog, SwitchDlog, CurvDlog, PlotDlog, HelpDlog;
WHERE Window   PlotNDlog, AboutDlog, diversW;
WHERE Cursor   arrow,noncurs,cursx;
WHERE Pixmap   titlePix,titlePixInv;
WHERE Bitmap   leftmask,rightmask,upmask,downmask;
WHERE Font     butfont,dlogfont;
WHERE FontInfo *butfinfo,*dlogfinfo;
WHERE int      ForeColor, BackColor;
WHERE Pattern  linepats[4], GridPat2, GridPat4, RBoxPat[4];
WHERE Vertex   curve[MAXPTS];           /* used for plotting data */

/* colors for color display */
WHERE int      gridFcol, gridBcol, panFcol, panBcol, butFcol, butBcol;
WHERE int      mainFcol, mainBcol, dlgFcol, dlgBcol, errFcol, errBcol;
WHERE int      trcol[4];
WHERE Pixmap   gridFpix, gridBpix, panFpix, panBpix, butFpix, butBpix;
WHERE Pixmap   mainFpix, mainBpix, dlgFpix, dlgBpix, errFpix, errBpix;
WHERE Pixmap   trpix[4];

/* Splot stuff */
WHERE Anal     anals[MAXANAL];
WHERE Dlist    xlist,ylist[4];
WHERE Range    ranges[5];
WHERE Offset   offsets[5];
WHERE Button   butts[MAXBUT], dbutts[3], curvbutts[8];
WHERE CButton  CButts[4];
WHERE int      ind[4];     /* points from curve#(0-3) to dlist#(0-MYPERANAL) */
WHERE Anal     *theAnal;   /* points to anal[curanal] (current analysis) */

WHERE int      LeftArr, RightArr, UpArr[4], DownArr[4];

WHERE int      selCB, tbInvert, comUp, Vis159, R159[4];

WHERE int      mono;
WHERE long     pid;

WHERE char     label[5][16], *units[5];

WHERE int      L10Offset, L10Range, OctOffset, OctRange;

WHERE int      numy, xscal, yscal, ylock, NOPARSE, numpts, numanals, curanal;
WHERE int      dlscnt;

WHERE char     basfname[128], errstr[128], dlogstr[64];

/* global variables that need to be initialized */

#ifdef MAIN
      int      mult    [9]={1,2,5,10,20,50,100,200,500};
      char     *multstr[9]={"1","2","5","10","20","50","100","200","500"};
      char     *prefix [9]={" p"," n"," u"," m"," "," K"," M"," G"," T"};
      char     *scals  [3]={"linear","log 10","log 2"};
      char     *SpTitle[3]={"DC TRANSFER","AC ANALYSIS","TRANSIENT ANALYSIS"};

#else

extern int  mult[9];
extern char *multstr[9], *prefix[9], *scals[3], *SpTitle[3];

#endif
\Rogue\Monster\
else
  echo "will not over write ./xsplot/include/xsplot.h"
fi
if `test ! -s ./xsplot/sreg.out`
then
echo "writing ./xsplot/sreg.out"
cat > ./xsplot/sreg.out << '\Rogue\Monster\'
1*******01/24/86 ********  SPICE 2G.6    3/15/83 ********06:25:07*****

0SHIFT                                                                           

0****     INPUT LISTING                    TEMPERATURE =   27.000 DEG C

0***********************************************************************




 .SUBCKT FLIP 1 2 9 11 10 13 14  
 XNAND1 4 8 7 GNAND      
 XNAND2 6 4 5 NAND       
 XGATE1 7 9 13 GATE      
 XGATE2 7 6 14 GATE      
 XINVR1 1 3 GINVR
 XINVR2 2 1 INVR 
 XGATE3 3 4 14 GATE      
 XGATE4 3 2 13 GATE      
 XINVR3 12 11 INVR       
 XNAND4 5 10 11 NAND     
 XNAND5 8 12 10 NAND     
 .ENDS FLIP      
         
 .SUBCKT GINVR 2 3       
 MDRIVE 2 3 0 0 NMOSE L=4U W=16U 
 VDD 1 0 5       
 MLOAD 1 2 2 0 NMOSD L=10U W=4U  
 .ENDS GINVR     
         
 .SUBCKT NAND 1 2 3      
 MDRIVE1 1 2 4 0 NMOSE L=4U W=16U
 MDRIVE2 4 3 0 0 NMOSE L=4U W=16U
 MLOAD 5 1 1 0 NMOSD L=10U W=4U  
 VDD 5 0 5       
 .ENDS NAND      
         
 .SUBCKT GNAND 1 2 3     
 MDRIVE1 1 2 4 0 NMOSE L=4U W=16U
 MDRIVE2 4 3 0 0 NMOSE L=4U W=32U
 MLOAD 5 1 1 0 NMOSD L=10U W=4U  
 VDD 5 0 5       
 .ENDS GNAND     
         
 .SUBCKT INVR 2 3
 MDRIVE 2 3 0 0 NMOSE L=4U W=8U  
 VDD 1 0 5       
 MLOAD 1 2 2 0 NMOSD L=10U W=4U  
 .ENDS INVR      
         
 .SUBCKT GATE 2 3 4      
 MPASS 2 4 3 0 NMOSE L=4U W=4U   
 .ENDS GATE      
         
 VCLK1 1 0 PULSE(0.2 5.0 0N 5N 5N 45N 100N)      
 VCLK2 2 0 PULSE(5.0 0.2 0N 5N 5N 45N 100N)      
 VSIN  3 0 PULSE(0.2 5.0 100N 5N 5N 95N 400N)    
 VLD 4 0 0       
 VDIN 5 0 0      
         
 X1  6  7 3 5 4 1 2 FLIP 
 X2  8  9 6 5 4 1 2 FLIP 
 X3 10 11 8 5 4 1 2 FLIP 
         
 .IC V(6)=0.2 V(7)=5 V(8)=0.2 V(9)=5 V(10)=0.2 V(11)=5   
 .TRAN 10N 500N  
 .PRINT TRAN V(1) V(2) V(3) V(6) V(8) V(10) V(1) V(2) V(3) V(6) V(8) V(10)       
         
 .OPTIONS NOMOD NOPAGE   
         
 .MODEL NMOSE NMOS LEVEL=2.00000 LD=0.826296U TOX=544.000E-10    
 +NSUB=2.090161E+15 VTO=1.14181 KP=3.730740E-05 GAMMA=0.628861   
 +PHI=0.600000 UO=300.000 UEXP=1.001000E-03 UCRIT=1.000000E+06   
 +DELTA=1.15554 VMAX=100000. XJ=1.31233U LAMBDA=3.101167E-02     
 +NFS=1.902288E+12 NEFF=1.001000E-02 NSS=0.000000E+00 TPG=1.00000
 +RSH=25.4 CGSO=1.6E-10 CGDO=1.6E-10 CGBO=1.7E-10 CJ=1.1E-4      
 +MJ=0.5 CJSW=5E-10 MJSW=0.33    
         
 .MODEL NMOSD NMOS LEVEL=2.00000 LD=1.01616U TOX=544.000E-10     
 +NSUB=1.000000E+16 VTO=-3.78687 KP=3.281897E-05 GAMMA=0.371508  
 +PHI=0.600000 UO=900.000 UEXP=1.001000E-03 UCRIT=804753.
 +DELTA=2.79525 VMAX=674713. XJ=0.600132U LAMBDA=1.000000E-06    
 +NFS=4.310000E+12 NEFF=1.001000E-02 NSS=0.000000E+00 TPG=1.00000
 +RSH=25.4 CGSO=1.6E-10 CGDO=1.6E-10 CGBO=1.7E-10 CJ=1.1E-4      
 +MJ=0.5 CJSW=5E-10 MJSW=0.33    
         
 .END    
0****     INITIAL TRANSIENT SOLUTION       TEMPERATURE =   27.000 DEG C

  NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE     NODE   VOLTAGE


 (  1)    0.2000    (  2)    5.0000    (  3)    0.2000    (  4)    0.        (  5)    0.        (  6)    0.2001    (  7)    5.0000

 (  8)    0.1999    (  9)    5.0000    ( 10)    0.1999    ( 11)    5.0000    ( 12)    0.1558    ( 13)    5.0000    ( 14)    4.4777

 ( 15)    4.9999    ( 16)    5.0000    ( 17)    0.1558    ( 18)    5.0000    ( 19)    4.9997    ( 20)    5.0000    ( 21)    0.1954

 ( 22)    0.1954    ( 23)    5.0000    ( 24)    4.9127    ( 25)    5.0000    ( 26)    4.9997    ( 27)    5.0000    ( 28)    0.1954

 ( 29)    0.1954    ( 30)    5.0000    ( 31)    4.9127    ( 32)    5.0000    ( 33)    0.0574    ( 34)    5.0000    ( 35)    0.0000

 ( 36)    5.0000    ( 37)    5.0000    ( 38)    5.0000    ( 39)    5.0000    ( 40)    0.0885    ( 41)    5.0000    ( 42)    4.5516

 ( 43)    5.0000    ( 44)    4.2754    ( 45)    5.0000    ( 46)    0.0962    ( 47)    5.0000    ( 48)    5.0000    ( 49)    5.0000

 ( 50)    5.0000    ( 51)    0.0885    ( 52)    5.0000    ( 53)    4.5516    ( 54)    5.0000    ( 55)    4.2754    ( 56)    5.0000

 ( 57)    0.0962    ( 58)    5.0000    ( 59)    5.0000    ( 60)    5.0000    ( 61)    5.0000    ( 62)    0.0885    ( 63)    5.0000

 ( 64)    4.5516    ( 65)    5.0000    




     VOLTAGE SOURCE CURRENTS

     NAME       CURRENT


     VCLK1     0.   d+00

     VCLK2     0.   d+00

     VSIN      3.393d-10

     VLD       0.   d+00

     VDIN      0.   d+00

     VDD.XNA* -9.148d-05

     VDD.XNA* -6.321d-09

     VDD.XIN* -9.102d-05

     VDD.XIN* -6.934d-12

     VDD.XIN* -1.080d-09

     VDD.XNA* -1.096d-09

     VDD.XNA* -2.130d-09

     VDD.XNA* -1.461d-08

     VDD.XNA* -9.107d-05

     VDD.XIN* -9.102d-05

     VDD.XIN* -6.934d-12

     VDD.XIN* -1.080d-09

     VDD.XNA* -1.096d-09

     VDD.XNA* -2.130d-09

     VDD.XNA* -1.461d-08

     VDD.XNA* -9.107d-05

     VDD.XIN* -9.102d-05

     VDD.XIN* -6.934d-12

     VDD.XIN* -1.080d-09

     VDD.XNA* -1.096d-09

     VDD.XNA* -2.130d-09


     TOTAL POWER DISSIPATION   2.73d-03  WATTS
0****     OPERATING POINT INFORMATION      TEMPERATURE =   27.000 DEG C

0
0**** MOSFETS


0            MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MPASS.X*  MPASS.X*  MDRIVE.*  MLOAD.X*  MDRIVE.*  MLOAD.X*
0MODEL     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSE     NMOSD     NMOSE     NMOSD   
 ID        9.15e-05  9.15e-05  9.15e-05  5.95e-09  5.94e-09  6.32e-09  3.41e-10 -3.50e-10  3.21e-09  9.10e-05  3.82e-09  1.93e-12
 VGS          4.943     4.478     0.        0.156     5.000     0.        0.        0.000     0.156     0.        0.200     0.   
 VDS          0.098     0.057     4.844     5.000     0.000     0.000     4.278    -0.522     0.200     4.800     5.000     0.000
 VBS         -0.057     0.       -0.156    -0.000     0.       -5.000    -0.200    -5.000     0.       -0.200     0.       -5.000


0            MPASS.X*  MPASS.X*  MDRIVE.*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*  MDRIVE2*
0MODEL     NMOSE     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE   
 ID        5.08e-10 -5.09e-10  1.06e-09  1.07e-09  1.08e-09  1.07e-09  1.09e-09  2.11e-09  2.10e-09  2.12e-09  1.46e-08  1.45e-08
 VGS          4.844    -4.800     0.        0.       -0.089     0.        0.        0.448     0.        0.        0.725     0.195
 VDS          0.000    -4.844     5.000     0.000     4.911     0.089     0.000     0.448     4.552     0.000     0.724     4.275
 VBS         -0.156    -5.000     0.       -5.000    -0.089     0.       -5.000    -4.552     0.       -5.000    -4.275     0.   


0            MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MPASS.X*  MPASS.X*  MDRIVE.*  MLOAD.X*  MDRIVE.*  MLOAD.X*  MPASS.X*  MPASS.X*
0MODEL     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSE     NMOSD     NMOSE     NMOSD     NMOSE     NMOSE   
 ID        1.46e-08  9.11e-05  9.11e-05  9.11e-05 -1.43e-11  1.39e-11  1.83e-04  9.10e-05  3.82e-09  1.93e-12 -1.17e-11  1.90e-12
 VGS          0.        4.903     5.000     0.       -0.000     4.805     4.913     0.        0.200     0.        0.000    -4.800
 VDS          0.000     0.099     0.096     4.805    -0.005     0.000     0.200     4.800     5.000     0.000    -0.087    -0.087
 VBS         -5.000    -0.096     0.       -0.195    -0.200    -0.195     0.       -0.200     0.       -5.000    -5.000    -5.000


0            MDRIVE.*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*
0MODEL     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD     NMOSE   
 ID        1.06e-09  1.07e-09  1.08e-09  1.07e-09  1.09e-09  2.11e-09  2.10e-09  2.12e-09  1.46e-08  1.45e-08  1.46e-08  9.11e-05
 VGS          0.        0.       -0.089     0.        0.        0.448     0.        0.        0.725     0.195     0.        4.903
 VDS          5.000     0.000     4.911     0.089     0.000     0.448     4.552     0.000     0.724     4.275     0.000     0.099
 VBS          0.       -5.000    -0.089     0.       -5.000    -4.552     0.       -5.000    -4.275     0.       -5.000    -0.096


0            MDRIVE2*  MLOAD.X*  MPASS.X*  MPASS.X*  MDRIVE.*  MLOAD.X*  MDRIVE.*  MLOAD.X*  MPASS.X*  MPASS.X*  MDRIVE.*  MLOAD.X*
0MODEL     NMOSE     NMOSD     NMOSE     NMOSE     NMOSE     NMOSD     NMOSE     NMOSD     NMOSE     NMOSE     NMOSE     NMOSD   
 ID        9.10e-05  9.11e-05 -1.38e-11  1.31e-11  1.83e-04  9.10e-05  3.82e-09  1.93e-12 -1.17e-11  1.90e-12  1.06e-09  1.07e-09
 VGS          5.000     0.        0.000     4.805     4.913     0.        0.200     0.        0.000    -4.800     0.        0.   
 VDS          0.096     4.805    -0.005     0.000     0.200     4.800     5.000     0.000    -0.087    -0.087     5.000     0.000
 VBS          0.       -0.195    -0.200    -0.195     0.       -0.200     0.       -5.000    -5.000    -5.000     0.       -5.000


0            MDRIVE1*  MDRIVE2*  MLOAD.X*  MDRIVE1*  MDRIVE2*  MLOAD.X*
0MODEL     NMOSE     NMOSE     NMOSD     NMOSE     NMOSE     NMOSD   
 ID        1.08e-09  1.07e-09  1.09e-09  2.11e-09  2.10e-09  2.12e-09
 VGS         -0.089     0.        0.        0.448     0.        0.   
 VDS          4.911     0.089     0.000     0.448     4.552     0.000
 VBS         -0.089     0.       -5.000    -4.552     0.       -5.000
0****     TRANSIENT ANALYSIS               TEMPERATURE =   27.000 DEG C


     TIME       V(1)        V(2)        V(3)        V(6)        V(8)        V(10)       V(1)        V(2)        
X
 
  0.   e+00     2.000e-01   5.000e+00   2.000e-01   2.001e-01   1.999e-01   1.999e-01   2.000e-01   5.000e+00
  1.000e-08     5.000e+00   2.000e-01   2.000e-01   4.903e+00   1.006e-01   1.006e-01   5.000e+00   2.000e-01
  2.000e-08     5.000e+00   2.000e-01   2.000e-01   4.987e+00   1.006e-01   1.006e-01   5.000e+00   2.000e-01
  3.000e-08     5.000e+00   2.000e-01   2.000e-01   4.992e+00   1.006e-01   1.006e-01   5.000e+00   2.000e-01
  4.000e-08     5.000e+00   2.000e-01   2.000e-01   4.995e+00   1.006e-01   1.006e-01   5.000e+00   2.000e-01
  5.000e-08     5.000e+00   2.000e-01   2.000e-01   4.995e+00   1.006e-01   1.006e-01   5.000e+00   2.000e-01
  6.000e-08     2.000e-01   5.000e+00   2.000e-01   1.651e-01   4.999e+00   1.006e-01   2.000e-01   5.000e+00
  7.000e-08     2.000e-01   5.000e+00   2.000e-01   1.545e-01   5.000e+00   1.006e-01   2.000e-01   5.000e+00
  8.000e-08     2.000e-01   5.000e+00   2.000e-01   1.502e-01   4.999e+00   1.006e-01   2.000e-01   5.000e+00
  9.000e-08     2.000e-01   5.000e+00   2.000e-01   1.474e-01   5.000e+00   1.006e-01   2.000e-01   5.000e+00
  1.000e-07     2.000e-01   5.000e+00   2.000e-01   1.455e-01   5.000e+00   1.006e-01   2.000e-01   5.000e+00
  1.100e-07     5.000e+00   2.000e-01   5.000e+00   1.449e-01   4.900e+00   1.006e-01   5.000e+00   2.000e-01
  1.200e-07     5.000e+00   2.000e-01   5.000e+00   1.431e-01   4.988e+00   1.006e-01   5.000e+00   2.000e-01
  1.300e-07     5.000e+00   2.000e-01   5.000e+00   1.419e-01   4.992e+00   1.006e-01   5.000e+00   2.000e-01
  1.400e-07     5.000e+00   2.000e-01   5.000e+00   1.407e-01   4.994e+00   1.006e-01   5.000e+00   2.000e-01
  1.500e-07     5.000e+00   2.000e-01   5.000e+00   1.396e-01   4.996e+00   1.006e-01   5.000e+00   2.000e-01
  1.600e-07     2.000e-01   5.000e+00   5.000e+00   5.001e+00   1.651e-01   5.001e+00   2.000e-01   5.000e+00
  1.700e-07     2.000e-01   5.000e+00   5.000e+00   5.000e+00   1.545e-01   5.000e+00   2.000e-01   5.000e+00
  1.800e-07     2.000e-01   5.000e+00   5.000e+00   5.000e+00   1.502e-01   5.000e+00   2.000e-01   5.000e+00
  1.900e-07     2.000e-01   5.000e+00   5.000e+00   5.000e+00   1.474e-01   5.000e+00   2.000e-01   5.000e+00
  2.000e-07     2.000e-01   5.000e+00   5.000e+00   5.000e+00   1.454e-01   5.000e+00   2.000e-01   5.000e+00
  2.100e-07     5.000e+00   2.000e-01   2.000e-01   4.900e+00   1.448e-01   5.000e+00   5.000e+00   2.000e-01
  2.200e-07     5.000e+00   2.000e-01   2.000e-01   4.987e+00   1.431e-01   5.000e+00   5.000e+00   2.000e-01
  2.300e-07     5.000e+00   2.000e-01   2.000e-01   4.992e+00   1.416e-01   5.000e+00   5.000e+00   2.000e-01
  2.400e-07     5.000e+00   2.000e-01   2.000e-01   4.994e+00   1.407e-01   5.000e+00   5.000e+00   2.000e-01
  2.500e-07     5.000e+00   2.000e-01   2.000e-01   4.996e+00   1.396e-01   5.000e+00   5.000e+00   2.000e-01
  2.600e-07     2.000e-01   5.000e+00   2.000e-01   1.655e-01   5.001e+00   1.655e-01   2.000e-01   5.000e+00
  2.700e-07     2.000e-01   5.000e+00   2.000e-01   1.545e-01   5.000e+00   1.545e-01   2.000e-01   5.000e+00
  2.800e-07     2.000e-01   5.000e+00   2.000e-01   1.501e-01   5.000e+00   1.501e-01   2.000e-01   5.000e+00
  2.900e-07     2.000e-01   5.000e+00   2.000e-01   1.475e-01   5.000e+00   1.475e-01   2.000e-01   5.000e+00
  3.000e-07     2.000e-01   5.000e+00   2.000e-01   1.455e-01   5.000e+00   1.455e-01   2.000e-01   5.000e+00
  3.100e-07     5.000e+00   2.000e-01   2.000e-01   1.449e-01   4.902e+00   1.446e-01   5.000e+00   2.000e-01
  3.200e-07     5.000e+00   2.000e-01   2.000e-01   1.431e-01   4.987e+00   1.430e-01   5.000e+00   2.000e-01
  3.300e-07     5.000e+00   2.000e-01   2.000e-01   1.418e-01   4.992e+00   1.417e-01   5.000e+00   2.000e-01
  3.400e-07     5.000e+00   2.000e-01   2.000e-01   1.408e-01   4.994e+00   1.406e-01   5.000e+00   2.000e-01
  3.500e-07     5.000e+00   2.000e-01   2.000e-01   1.398e-01   4.996e+00   1.397e-01   5.000e+00   2.000e-01
  3.600e-07     2.000e-01   5.000e+00   2.000e-01   1.394e-01   1.655e-01   5.000e+00   2.000e-01   5.000e+00
  3.700e-07     2.000e-01   5.000e+00   2.000e-01   1.387e-01   1.544e-01   5.000e+00   2.000e-01   5.000e+00
  3.800e-07     2.000e-01   5.000e+00   2.000e-01   1.380e-01   1.502e-01   5.000e+00   2.000e-01   5.000e+00
  3.900e-07     2.000e-01   5.000e+00   2.000e-01   1.374e-01   1.474e-01   5.000e+00   2.000e-01   5.000e+00
  4.000e-07     2.000e-01   5.000e+00   2.000e-01   1.369e-01   1.454e-01   5.000e+00   2.000e-01   5.000e+00
  4.100e-07     5.000e+00   2.000e-01   2.000e-01   1.366e-01   1.444e-01   5.000e+00   5.000e+00   2.000e-01
  4.200e-07     5.000e+00   2.000e-01   2.000e-01   1.361e-01   1.431e-01   5.000e+00   5.000e+00   2.000e-01
  4.300e-07     5.000e+00   2.000e-01   2.000e-01   1.357e-01   1.418e-01   5.000e+00   5.000e+00   2.000e-01
  4.400e-07     5.000e+00   2.000e-01   2.000e-01   1.352e-01   1.408e-01   5.000e+00   5.000e+00   2.000e-01
  4.500e-07     5.000e+00   2.000e-01   2.000e-01   1.348e-01   1.397e-01   5.000e+00   5.000e+00   2.000e-01
  4.600e-07     2.000e-01   5.000e+00   2.000e-01   1.346e-01   1.392e-01   1.649e-01   2.000e-01   5.000e+00
  4.700e-07     2.000e-01   5.000e+00   2.000e-01   1.343e-01   1.384e-01   1.545e-01   2.000e-01   5.000e+00
  4.800e-07     2.000e-01   5.000e+00   2.000e-01   1.339e-01   1.378e-01   1.502e-01   2.000e-01   5.000e+00
  4.900e-07     2.000e-01   5.000e+00   2.000e-01   1.336e-01   1.372e-01   1.474e-01   2.000e-01   5.000e+00
  5.000e-07     2.000e-01   5.000e+00   2.000e-01   1.332e-01   1.365e-01   1.453e-01   2.000e-01   5.000e+00
Y
0
         JOB CONCLUDED
0         TOTAL JOB TIME         3309.52
\Rogue\Monster\
else
  echo "will not over write ./xsplot/sreg.out"
fi
echo "Finished archive 4 of 4"
exit