/* SC A Spreadsheet Calculator
* original by James Gosling, September 1982
* modifications by Mark Weiser and Bruce Israel,
* More mods Robert Bond, 12/86
#if defined(BSD42) || defined(BSD43)
if (currow
>= maxrows
- 1 || maxrow
>= maxrows
- 1) {
if (!growtbl(GROWROW
, 0, 0))
for (curcol
= 0; curcol
<= maxcol
; curcol
++) {
register struct ent
*p
= *ATBL(tbl
, currow
- 1, curcol
);
n
= lookat (currow
, curcol
);
(void)copyent ( n
, p
, 1, 0);
for (curcol
= 0; curcol
<= maxcol
; curcol
++) {
register struct ent
*p
= *ATBL(tbl
, currow
, curcol
);
if (p
&& (p
-> flags
& is_valid
) && !p
-> expr
)
if (curcol
>= maxcols
- 1 || maxcol
>= maxcols
- 1) {
if (!growtbl(GROWCOL
, 0, 0))
for (currow
= 0; currow
<= maxrow
; currow
++) {
register struct ent
*p
= *ATBL(tbl
, currow
, curcol
- 1);
n
= lookat (currow
, curcol
);
for (currow
= 0; currow
<= maxrow
; currow
++) {
register struct ent
*p
= *ATBL(tbl
, currow
, curcol
);
if (p
&& (p
-> flags
& is_valid
) && !p
-> expr
)
while (--arg
>=0) openrow (currow
);
erase_area(currow
, 0, currow
+ arg
- 1, maxcol
);
while (--arg
>=0) closerow (--currow
);
valueize_area(currow
, 0, currow
+ arg
- 1, maxcol
);
valueize_area(0, curcol
, maxrow
, curcol
+ arg
- 1);
erase_area(sr
, sc
, er
, ec
)
register struct ent
**pp
;
for (r
= sr
; r
<= er
; r
++) {
for (c
= sc
; c
<= ec
; c
++) {
valueize_area(sr
, sc
, er
, ec
)
for (r
= sr
; r
<= er
; r
++) {
for (c
= sc
; c
<= ec
; c
++) {
p
->expr
= (struct enode
*)0;
register struct ent
*p
, *n
;
register int deltar
, deltac
;
error ("No data to pull");
for (p
= to_fix
; p
; p
= p
->next
) {
numrows
= mxrow
- minrow
+ 1;
numcols
= mxcol
- mincol
+ 1;
deltar
= currow
- minrow
;
deltac
= curcol
- mincol
;
} else if (to_insert
== 'c') {
opencol(curcol
, numcols
);
for (p
= to_fix
; p
; p
= p
->next
) {
n
= lookat (p
->row
+ deltar
, p
->col
+ deltac
);
copyent( n
, p
, deltar
, deltac
);
n
-> flags
= p
-> flags
& ~is_deleted
;
for (i
=0; i
<maxcols
; i
++)
error ("No hidden columns to show");
(void) sprintf(line
,"show %s:", coltoa(i
));
(void) sprintf(line
+ strlen(line
),"%s",coltoa(j
));
for (i
=0; i
<maxrows
; i
++)
error ("No hidden rows to show");
(void) sprintf(line
,"show %d:%d", i
, j
);
* Given a row/column command letter, emit a small menu, then read a qualifier
* character for a row/column command and convert it to 'r' (row), 'c'
* (column), or 0 (unknown). If ch is 'p', an extra qualifier 'm' is allowed.
error ("%sow/column: r: row c: column%s",
(ch
== 'i') ? "Insert r" :
(ch
== 'a') ? "Append r" :
(ch
== 'd') ? "Delete r" :
(ch
== 'v') ? "Values r" :
(ch
== 's') ? "Show r" : "R",
(ch
== 'p') ? " m: merge" : "");
case ctl('b'): return ('r');
case ctl('n'): return ('c');
case 'm': return ((ch
== 'p') ? 'm' : 0);
case ctl('g'): return (ESC
);
struct ent
**tmprow
, **pp
;
if (rs
> maxrow
) maxrow
= rs
;
if (maxrow
>= maxrows
- 1 || rs
> maxrows
- 1) {
if (!growtbl(GROWROW
, rs
, 0))
* save the last active row+1, shift the rows downward, put the last
* row in place of the first
for (r
= maxrow
; r
> rs
; r
--) {
row_hidden
[r
] = row_hidden
[r
-1];
for (c
= 0; c
< maxcols
; c
++, pp
++)
tbl
[r
] = tmprow
; /* the last row was never used.... */
register struct ent
**pp
;
/* save the row and empty it out */
for (c
=maxcol
+1; --c
>=0; pp
++) {
/* move the rows, put the deleted row at the end */
for (; r
< maxrows
- 1; r
++) {
row_hidden
[r
] = row_hidden
[r
+1];
for (c
= 0; c
< maxcols
; c
++, pp
++)
register struct ent
**pp
;
register lim
= maxcol
-cs
+1;
if ((maxcol
>= maxcols
- 1) && !growtbl(GROWCOL
, 0, maxcol
))
for (i
= maxcol
; i
> cs
; i
--) {
fwidth
[i
] = fwidth
[i
-numcol
];
precision
[i
] = precision
[i
-numcol
];
col_hidden
[i
] = col_hidden
[i
-numcol
];
for (c
= cs
; c
- cs
< numcol
; c
++)
for (r
=0; r
<=maxrow
; r
++) {
pp
= ATBL(tbl
, r
, maxcol
);
for (c
=lim
; --c
>=0; pp
--)
for (c
= cs
; c
- cs
< numcol
; c
++, pp
++)
register struct ent
**pp
;
register lim
= maxcol
-cs
;
{ sprintf(buf
, "Can't delete %d column%s %d columns left", numcol
,
(numcol
> 1 ? "s," : ","), lim
+1);
erase_area(0, curcol
, maxrow
, curcol
+ numcol
- 1);
/* clear then copy the block left */
lim
= maxcols
- numcol
- 1;
for (r
=0; r
<=maxrow
; r
++) {
for (c
= cs
; c
- cs
< numcol
; c
++)
if (q
= *ATBL(tbl
, r
, c
))
for (c
=cs
; c
<= lim
; c
++, pp
++)
for (i
= cs
; i
< maxcols
- numcol
- 1; i
++) {
fwidth
[i
] = fwidth
[i
+numcol
];
precision
[i
] = precision
[i
+numcol
];
col_hidden
[i
] = col_hidden
[i
+numcol
];
for (; i
< maxcols
- 1; i
++) {
if (VALID_CELL(p
, currow
, curcol
)) {
if (r
>= 0 && r
< maxrows
&&
if (!VALID_CELL(p
, currow
, curcol
)) {
while (!VALID_CELL(p
, currow
, curcol
) && currow
> 0)
while (!VALID_CELL(p
, currow
, curcol
) && currow
< maxrows
-1)
while (!VALID_CELL(p
, currow
, curcol
) && curcol
> 0)
while (!VALID_CELL(p
, currow
, curcol
) && curcol
< maxcols
-1)
error (""); /* clear line */
while (VALID_CELL(p
, currow
, curcol
) && currow
> 0)
while (VALID_CELL(p
, currow
, curcol
) && currow
< maxrows
-1)
while (VALID_CELL(p
, currow
, curcol
) && curcol
> 0)
while (VALID_CELL(p
, currow
, curcol
) && curcol
< maxcols
-1)
if (!VALID_CELL(p
, currow
, curcol
)) {
if (w
> COLS
- RESCOL
- 2) {
error("Format too large - Maximum = %d", COLS
- RESCOL
- 2);
error("Precision too large");
fwidth
[i
] = w
, precision
[i
] = p
;
return; /* No reason to do this */
(void) fprintf(f
, "set");
(void) fprintf(f
," !autocalc");
(void) fprintf(f
, " iterations = %d", propagation
);
if(calc_order
!= BYROWS
)
(void) fprintf(f
, " bycols");
(void) fprintf(f
, " numeric");
(void) fprintf(f
, " prescale");
(void) fprintf(f
, " extfun");
(void) fprintf(f
, " !cellcur");
(void) fprintf(f
, " !toprow");
(void) fprintf(f
, " tblstyle = %s", tbl_style
== TBL
? "tbl" :
tbl_style
== LATEX
? "latex" :
tbl_style
== TEX
? "tex" : "0" );
printfile (fname
, r0
, c0
, rn
, cn
)
register struct ent
**pp
;
if ((strcmp(fname
, curfile
) == 0) &&
!yn_ask("Confirm that you want to destroy the data base: (y,n)"))
if ((f
= openout(fname
, &pid
)) == (FILE *)0)
{ error ("Can't create file \"%s\"", fname
);
for (row
=r0
;row
<=rn
; row
++) {
pline
[plinelim
=0] = '\0';
for (pp
= ATBL(tbl
, row
, col
=c0
); col
<=cn
;
pp
+= nextcol
-col
, col
= nextcol
, c
+= fieldlen
) {
while (plinelim
<c
) pline
[plinelim
++] = ' ';
if ((*pp
)->flags
&is_valid
) {
(void)sprintf (pline
+plinelim
,"%*.*f",fwidth
[col
],
precision
[col
], (*pp
)->v
);
plinelim
+= strlen (pline
+plinelim
);
/* Figure out if the label slops over to a blank field */
while (slen
> fieldlen
&& nextcol
<= cn
&&
!((nc
= lookat(row
,nextcol
))->flags
& is_valid
) &&
if (!col_hidden
[nextcol
])
fieldlen
+= fwidth
[nextcol
];
/* Now justify and print */
start
= (*pp
)->flags
& is_leftflush
? pline
+ c
: pline
+ c
+ fieldlen
- slen
;
last
= pline
+ c
+ fieldlen
;
fp
= plinelim
< c
? pline
+ plinelim
: pline
+ c
;
if (!((*pp
)->flags
& is_valid
) || fieldlen
!= fwidth
[col
])
if (plinelim
< fp
- pline
)
pline
[plinelim
++] = '\n';
tblprintfile (fname
, r0
, c0
, rn
, cn
)
register struct ent
**pp
;
char coldelim
= DEFCOLDELIM
;
if ((strcmp(fname
, curfile
) == 0) &&
!yn_ask("Confirm that you want to destroy the data base: (y,n)"))
if ((f
= openout(fname
, &pid
)) == (FILE *)0)
{ error ("Can't create file \"%s\"", fname
);
if ( tbl_style
== TBL
) {
fprintf(f
,".\\\" ** %s spreadsheet output \n.TS\n",progname
);
fprintf(f
,"tab(%c);\n",coldelim
);
for (col
=c0
;col
<=cn
; col
++) fprintf(f
," n");
else if ( tbl_style
== LATEX
) {
fprintf(f
,"%% ** %s spreadsheet output\n\\begin{tabular}{",progname
);
for (col
=c0
;col
<=cn
; col
++) fprintf(f
,"c");
else if ( tbl_style
== TEX
) {
fprintf(f
,"{\t%% ** %s spreadsheet output\n\\settabs %d \\columns\n",
for (row
=r0
; row
<=rn
; row
++) {
(void) fprintf (f
, "\\+");
for (pp
= ATBL(tbl
, row
, col
=c0
); col
<=cn
; col
++, pp
++) {
if ((*pp
)->flags
&is_valid
) {
(void) fprintf (f
,"%.*f",precision
[col
],
(void) fprintf (f
,"%s",s
);
(void) fprintf(f
,"%c",coldelim
);
if ( tbl_style
== LATEX
) {
if ( row
< rn
) (void) fprintf (f
, "\\\\");
else if ( tbl_style
== TEX
) {
(void) fprintf (f
, "\\cr");
(void) fprintf (f
,".TE\n.\\\" ** end of %s spreadsheet output\n", progname
);
else if ( tbl_style
== LATEX
)
(void) fprintf (f
,"\\end{tabular}\n%% ** end of %s spreadsheet output\n", progname
);
else if ( tbl_style
== TEX
)
(void) fprintf (f
,"}\n%% ** end of %s spreadsheet output\n", progname
);
copye (e
, Rdelta
, Cdelta
)
register struct enode
*e
;
register struct enode
*ret
;
if (e
== (struct enode
*)0) {
} else if (e
->op
& REDUCE
) {
ret
= (struct enode
*) xmalloc ((unsigned) sizeof (struct enode
));
newrow
=e
->e
.r
.left
.vf
& FIX_ROW
? e
->e
.r
.left
.vp
->row
:
e
->e
.r
.left
.vp
->row
+Rdelta
;
newcol
=e
->e
.r
.left
.vf
& FIX_COL
? e
->e
.r
.left
.vp
->col
:
e
->e
.r
.left
.vp
->col
+Cdelta
;
ret
->e
.r
.left
.vp
= lookat (newrow
, newcol
);
ret
->e
.r
.left
.vf
= e
->e
.r
.left
.vf
;
newrow
=e
->e
.r
.right
.vf
& FIX_ROW
? e
->e
.r
.right
.vp
->row
:
e
->e
.r
.right
.vp
->row
+Rdelta
;
newcol
=e
->e
.r
.right
.vf
& FIX_COL
? e
->e
.r
.right
.vp
->col
:
e
->e
.r
.right
.vp
->col
+Cdelta
;
ret
->e
.r
.right
.vp
= lookat (newrow
, newcol
);
ret
->e
.r
.right
.vf
= e
->e
.r
.right
.vf
;
ret
= (struct enode
*) xmalloc ((unsigned) sizeof (struct enode
));
newrow
=e
->e
.v
.vf
& FIX_ROW
? e
->e
.v
.vp
->row
:
newcol
=e
->e
.v
.vf
& FIX_COL
? e
->e
.v
.vp
->col
:
ret
->e
.v
.vp
= lookat (newrow
, newcol
);
ret
->e
.o
.right
= copye (e
->e
.o
.right
,0,0);
ret
->e
.o
.left
= (struct enode
*)0;
ret
->e
.s
= xmalloc((unsigned) strlen(e
->e
.s
)+1);
(void) strcpy(ret
->e
.s
, e
->e
.s
);
ret
->e
.o
.right
= copye (e
->e
.o
.right
,Rdelta
,Cdelta
);
ret
->e
.o
.left
= copye (e
->e
.o
.left
,Rdelta
,Cdelta
);
* sync_refs and syncref are used to remove references to
* deleted struct ents. Note that the deleted structure must still
* be hanging around before the call, but not referenced by an entry
* in tbl. Thus the free_ent, fix_ent calls in sc.c
for (i
=0; i
<=maxrow
; i
++)
for (j
=0; j
<=maxcol
; j
++)
if ((p
= *ATBL(tbl
, i
, j
)) && p
->expr
)
register struct enode
*e
;
if (e
== (struct enode
*)0)
else if (e
->op
& REDUCE
) {
e
->e
.r
.right
.vp
= lookat(e
->e
.r
.right
.vp
->row
, e
->e
.r
.right
.vp
->col
);
e
->e
.r
.left
.vp
= lookat(e
->e
.r
.left
.vp
->row
, e
->e
.r
.left
.vp
->col
);
e
->e
.v
.vp
= lookat(e
->e
.v
.vp
->row
, e
->e
.v
.vp
->col
);
{ if (!growtbl(GROWROW
, arg
+1, 0))
{ error("You can't hide the last row");
{ if ((arg
>= ABSMAXCOLS
-1) || !growtbl(GROWCOL
, 0, arg
+1))
{ error("You can't hide the last col");
/* Open the output file, setting up a pipe if needed */
while (*fname
&& (*fname
== ' ')) /* Skip leading blanks */
if (*fname
!= '|') { /* Open file if not pipe */
efname
= findhome(fname
);
if (!backup_file(efname
) &&
(yn_ask("Could not create backup copy, Save anyhow?: (y,n)") != 1))
return(fopen(efname
, "w"));
if ( pipe (pipefd
) < 0) {
error("Can't make pipe to child");
fprintf(stderr
, "No son tasks available yet under VMS--sorry\n");
if ((pid
=fork()) == 0) /* if child */
(void) close (0); /* close stdin */
(void) close (pipefd
[1]);
(void) dup (pipefd
[0]); /* connect to pipe input */
(void) signal (SIGINT
, SIG_DFL
); /* reset */
(void) execl ("/bin/sh", "sh", "-c", fname
, 0);
if ((f
= fdopen (pipefd
[1], "w")) == (FILE *)0)
error ("Can't fdopen output");
(void) close (pipefd
[1]);
while (pid
!= wait(&temp
)) /**/;
(void) printf("Press RETURN to continue ");
register struct ent
*n
, *p
;
if(!n
||!p
){error("internal error");return;}
n
-> expr
= copye (p
-> expr
, dr
, dc
);
xmalloc ((unsigned) (strlen (p
-> label
) + 1));
(void) strcpy (n
-> label
, p
-> label
);
write_fd (f
, r0
, c0
, rn
, cn
)
register struct ent
**pp
;
(void) fprintf (f
, "# This data file was generated by the Spreadsheet ");
(void) fprintf (f
, "Calculator.\n");
(void) fprintf (f
, "# You almost certainly shouldn't edit it.\n\n");
for (c
=0; c
<maxcols
; c
++)
if (fwidth
[c
] != DEFWIDTH
|| precision
[c
] != DEFPREC
)
(void) fprintf (f
, "format %s %d %d\n",coltoa(c
),fwidth
[c
],precision
[c
]);
(void) fprintf(f
, "hide %s\n", coltoa(c
));
(void) fprintf(f
, "hide %d\n", r
);
(void) fprintf(f
, "mdir \"%s\"\n", mdir
);
for (c
=c0
; c
<=cn
; c
++, pp
++)
(void) fprintf(f
, "%s\n",line
);
if ((*pp
)->flags
&is_valid
) {
(void) fprintf (f
, "%s\n",line
);
writefile (fname
, r0
, c0
, rn
, cn
)
return (cwritefile(fname
, r0
, c0
, rn
, cn
));
if (*fname
== '\0') fname
= curfile
;
(void) strcpy(save
,fname
);
if ((f
= openout(fname
, &pid
)) == (FILE *)0)
{ error ("Can't create file \"%s\"", fname
);
write_fd(f
, r0
, c0
, rn
, cn
);
(void) strcpy(curfile
, save
);
error("File \"%s\" written.",curfile
);
readfile (fname
,eraseflg
)
if (*fname
== '*' && mdir
) {
(void) strcpy(save
, mdir
);
(void) strcat(save
, fname
);
(void) strcpy(save
,fname
);
creadfile(save
, eraseflg
);
if (eraseflg
&& strcmp(fname
,curfile
) && modcheck(" first")) return;
if ((f
= fopen(findhome(save
), "r")) == (FILE *)0)
{ error ("Can't read file \"%s\"", save
);
if (eraseflg
) erasedb ();
while (fgets(line
,sizeof line
,f
)) {
if (line
[0] != '#') (void) yyparse ();
(void) strcpy(curfile
,save
);
for (c
= 0; c
<=maxcol
; c
++) {
for (r
= 0; r
<=maxrow
; r
++) {
register struct ent
**pp
= ATBL(tbl
, r
, 0);
for (c
=0; c
++<=maxcol
; pp
++)
if ((*pp
)->expr
) efree (*pp
, (*pp
) -> expr
);
if ((*pp
)->label
) xfree ((char *)((*pp
) -> label
));
{error ("At column A"); break;}
while(col_hidden
[curcol
] && curcol
)
if (curcol
< maxcols
- 1)
if (!growtbl(GROWCOL
, 0, arg
)) /* get as much as needed */
while(col_hidden
[curcol
]&&(curcol
<maxcols
-1))
if (currow
< maxrows
- 1)
if (!growtbl(GROWROW
, arg
, 0)) /* get as much as needed */
while (row_hidden
[currow
]&&(currow
<maxrows
-1))
{error ("At row zero"); break;}
while (row_hidden
[currow
] && currow
)
* Show a cell's label string or expression value. May overwrite value if
* there is one already displayed in the cell. Created from old code in
* update(), copied with minimal changes.
showstring (string
, leftflush
, hasvalue
, row
, col
, nextcolp
, mxcol
, fieldlenp
, r
, c
)
char *string
; /* to display */
int leftflush
; /* or rightflush */
int hasvalue
; /* is there a numeric value? */
int row
, col
; /* spreadsheet location */
int *nextcolp
; /* value returned through it */
int mxcol
; /* last column displayed? */
int *fieldlenp
; /* value returned through it */
int r
, c
; /* screen row and column */
register int nextcol
= *nextcolp
;
register int fieldlen
= *fieldlenp
;
/* This figures out if the label is allowed to
slop over into the next blank field */
while ((slen
> fieldlen
) && (nextcol
<= mxcol
) &&
!((nc
= lookat (row
, nextcol
)) -> flags
& is_valid
) &&
if (! col_hidden
[nextcol
])
fieldlen
+= fwidth
[nextcol
];
/* Now justify and print */
start
= leftflush
? field
: field
+ fieldlen
- slen
;
if ((! hasvalue
) || fieldlen
!= fwidth
[col
])
mvaddstr(r
, c
, field
); /* this is a macro */
(void) mvaddstr(r
, c
, field
);
register struct enode
*e
;
if (e
== (struct enode
*)0)
case O_SCONST
: case '#': case DATE
: case FMT
: case STINDEX
:
case EXT
: case SVAL
: case SUBSTR
:
return(etype(e
->e
.o
.right
->e
.o
.left
));
return(etype(e
->e
.o
.right
));
return(p
->flags
& is_strexpr
? STR
: NUM
);
/* return 1 if yes given, 0 otherwise */
if ( ch
!= 'y' && ch
!= 'Y' && ch
!= 'n' && ch
!= 'N' ) {
if (ch
== ctl('g') || ch
== ESC
)
error("y or n response required");
if (ch
== 'y' || ch
== 'Y')
static char *HomeDir
= NULL
;
{ HomeDir
= getenv("HOME");
if ((*pathptr
== '/') || (*pathptr
== '\0'))
{ strcpy(tmppath
, HomeDir
);
extern struct passwd
*getpwnam();
while ((*pathptr
!= '\0') && (*pathptr
!= '/'))
*(namep
++) = *(pathptr
++);
if ((pwent
= getpwnam(name
)) == NULL
)
{ sprintf(path
, "Can't find user %s", name
);
strcpy(tmppath
, pwent
->pw_dir
);
strcat(tmppath
, pathptr
);
* make a backup copy of a file, use the same mode and name in the format
* return 1 if we were successful, 0 otherwise
/* tpath will be the [path/]file ---> [path/]#file~ */
if ((tpp
= strrchr(tpath
, '/')) == NULL
)
sprintf(tpp
, "#%s~", fname
);
if (stat(path
, &statbuf
) == 0)
if ((buf
= xmalloc(statbuf
.st_blksize
)) == (char *)0)
if ((infd
= open(path
, O_RDONLY
, 0)) < 0)
if ((outfd
= open(tpath
, O_TRUNC
|O_WRONLY
|O_CREAT
,
while((count
= read(infd
, buf
, statbuf
.st_blksize
)) > 0)
while((count
= read(infd
, buf
, sizeof(buf
))) > 0)
{ if (write(outfd
, buf
, count
) != count
)
return((count
< 0) ? 0 : 1);