v20i039: sc - The SC Spreadsheet, release 6.16, Part05/07
Jeff Buhrt
prslnk!buhrt at cs.indiana.edu
Thu Jun 6 03:28:36 AEST 1991
Submitted-by: Jeff Buhrt <prslnk!buhrt at cs.indiana.edu>
Posting-number: Volume 20, Issue 39
Archive-name: sc/part05
#! /bin/sh
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents: CHANGES format.c psc.c screen.c
# Wrapped by kent at sparky on Wed Jun 5 09:22:20 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 5 (of 7)."'
if test -f 'CHANGES' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'CHANGES'\"
else
echo shar: Extracting \"'CHANGES'\" \(16317 characters\)
sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
XCHANGES BETWEEN 6.16 and 6.15
XTom Tkacik
X -fixed a bug in ^W
XJonathan I. Kamens
X - added Makefile rules so scqref and psc don't clobber .o's
XLarry Philps
X - fixed a SCO XENIX vs M_XENIX problem
X - fixed a problem where dosval() might not xmalloc enough memory
XDave Close
X - fix for Xenix 2.3 to reset terminal modes
X
XCHANGES BETWEEN 6.15 and 6.14
XLowell Skoog
X - fixed a bug in 'F'ormat
XHenk Hesselink
X - format.c double neg. sign
X - interp.c minr/minc bug, plus modflg wasn't set
X - fixed a hardcoded path in sc.doc
X - improvement:
X -show current cell format in top line
X -[buhrt: go into edit mode on the old format if it existed
X otherwise insert mode]
XJonathan Crompron
X - made sure doformat() does a checkbounds()
XStephen (Steve) M. Brooks
X - pointed out -s in psc was broke
XMichael Richardson
X - fixed negative numbers in exponential format
X
XCHANGES BETWEEN 6.14 and 6.13
XMats Wichmann
X - Sys V R4 patches, fixed 'Press RETURN ...' on a shell command
XTim Theisen
X - changed #define for memcpy/memset under ultrix
XRick Walker
X - Added @myrow and @mycol to give the row/col of the current cell
X 'The two functions are @myrow and @mycol, which return the numerical
X row and column of the calling cell. The cell directly above a cell
X in the D column could then be accessed by @nval("d", at myrow-1).'
X NOTE: @myrow and @mycol can't be used in specifying ranges.
X
XCHANGES BETWEEN 6.13 and 6.12
XRick Walker
X - pointed out a move(x,y)-> (y,x) in sc.c
XGlenn Barry
X - Further SunOS 4.X cleanups
XTom Tkacik
X - made sure 'J' moves downward 1/2 a screen even at the bottom
XDavid I. Dalva
X - pointed out crypt may not be in /bin/crypt
XGregory Bond
X - allows the vi-mode editing of very long expressions
X (> 1 screen width) to work on 2nd + subsequent lines
XTom Anderson
X - "let A1 = aaa" (where aaa is defined as A0:A0) is now valid
X - added autolabeling
X 'When there is an empty cell to the left of a cell that has
X just been defined (with /d), a label is created in the blank
X cell. The label holds the definition that has just been
X created. This labeling is only done for definitions of single
X cells (and not for ranges).'
X 'The feature can be turned on and off with a toggle (^T)
X command'
XPetri Wessman
X - Added support for SLaTeX, 'a Scandinavian version of LaTeX, in
X intensive use ... in Finland and in Sweden'
XJeff Buhrt
X - vmtbl.c explictly set arrays of pointers to NULL, vs memset()
X - psc [-P] plain numbers only:a number only when there is no [-+eE]
X [-S] all numbers are strings
X - psc: a number must end in [0-9.eE] anything else makes it a string
X (4, 4., 4.5, and 4e are numbers; 4-, 4+, etc are not).
X - psc: made sure we grow enough when we call growtbl()
X - cleaned up the Makefile w/ a few suggestions
X - SIGWINCH is delt with next time the screen would update (testing)
X - added IDLOKBAD to get around a SysV curses bug (see Makefile)
X - moved screen functions into screen.c (except for one indirect
X 'repaint()' call in sc.c, and help.c)
X
XCHANGES BETWEEN 6.12 and 6.11
XJames Dugal
X - added format.c to SRCS in Makefile
X - noted RETURN didn't enter insert mode
XPeter King
X - pointed out iscntrl is broken on some other systems as well
X - sent some lint cleanups
XMichael Richardson
X - patch to stop format looping when scientific notation was selected
XGlenn T. Barry
X - code to turn on hardware scrolling and added 'slow speed display'
X speedups, default for SYSV3 or see -DSUNOS41SYSV in Makefile.
XTom Tkacik
X - fixes to make sure J and K move same amount, and re-added H code
XJeff Buhrt
X - fixed a possible xfree(NULL) in getent() (found when adding K_VAL)
X - merged compiler cleanups
X* - added $(name)qref to print a Quick Reference card
X - got rid of INVALIDS that may have been left around
X* - pressing return on a empty line puts you into insert mode
X (like in <=Sc6.1). When entering you can also press ESC
X to go into the editor (no change); this is also documented
X now so it might stay around this time.
X
XCHANGES BETWEEN 6.11 and 6.10
X
XJonathan I. Kamens
X - sc.doc now mentions the tutorial file in the FILES section
XAndy Fyfe
X - pointed out 3 locations where a NULL should have been '\0'
XRobert Bond
X - pointed out the ERROR could hide a cellerror
XPiercarlo Grandi
X - H,J,I,K now move 1/2 screen
XUlf Noren
X - changes for AIX V3.1
X - defined CHTYPE and NLS for the preprocessor. CHTYPE is
X the type of every character in a curses window.
X - Added KEY_BACKSPACE to nmgetch
X - strtof ifdef
X - Iteration change: when Sc says: "Still changing after 9 iterations"
X Sc at that point will have eval'd 9 times
XChris Metcalf
X - pointed out I broke setlist when adding 'goto {error,invalid}'
XJames P. Dugal
X - iscntrl() wasn't handling TABS though CRs under Pyramid OSx4.1
XPeter King
X - BROKENCURSES patch for nl()/nonl() bug on some BSD systems
X - backups, tutorial file, and man references now depend on $name
X - DFLTPAGER to DFLT_PAGER fix
X
XCHANGES BETWEEN 6.10 and 6.9
X
XTom Tkacik
X - when moving off the current table (resizing) now move the cursor
X on 'l' or 'k'.
X - patches to sc.doc to correctly format the vi-mode notes
XJim Clausing
X - made sure / doesn't try to divide by zero.
XTom Kloos
X - correction to substr() example in help.c
XPiercarlo "Peter" Grandi
X - Disable non-constant expressions while loading
X - Added extra code in dealing w/ floating point exceptions
X - #ifdef'd SAVENAME (vs hardcoded SC.SAVE) to allowing changing the
X emergency save name.
XCasey Leedom
X - Makefile changes: man extension, RINT note, make values should
X never be left undefined and then referenced, don't leave
X around *.old's
XTom Anderson
X - patches to add type of column format (note format now has 3 args)
XJeff Buhrt
X - xmalloc/xfree fatal() will now call diesave()
X (MAKE SURE the saved file is ok if this were to happen)
X - history[] is now a circular queue, this will cut down on the
X number of data moves and also xmalloc/xfree calls
X (idea from Keith Bostic)
X - cells with an error (ex: divide by 0) will show 'ERROR'
X - you can 'goto error' (or 'goto') to find an ERROR (for next ERROR)
XRobert Bond
X - When in numeric mode the ^B, ^F, ^N, ^P key will end a numeric entry.
X
XCHANGES BETWEEN 6.9 and 6.8
X
XJim Richardson
X - pointed out vi mode was not documented in sc.doc
X - found a nasty buffer limit bug in savedot()
X - a side effect was ^D could cause a core dump (-Jeff)
XTim Wilson
X - Hints on compiling on Ultrix
XEric Putz
X -patch for printfile() (sc died on huge # of columns in a W)
XJeffrey C Honig
X -patch for lex.c which bombed on SunOS 4.1 if $TERM was not set
XTom Kloos
X -psc now calls [+-.] strings vs numbers.
X -also pointed out a format reversal problem
XJack Goral
X -changes to Makefile to compile under SCO Unix V rel 3.2.0
XMark Nagel
X -changes to allow arbitrarily complex formatting of cells
XKim Sanders
X -^W generated an incorrect equation (line was not started at beginning)
XMike Schwartz
X -a put command will use the same encryption key as when the
X file was read.
X >I have a suggestion for making the encyrption option of "sc" more
X >usable: Right now, if you use the -x option when you start up sc, it
X >prompts you for the key (just like "vi -x" does). But when you try to
X >write the file out using the Put command, it asks for the key again
X >each time. Why not make it use the same key you used before (as "vi
X >-x" does)? That would really help, because as it is, each time you try
X >to save the file you run the risk of mistyping the key.
X >
X >You might think this causes a security problem, since the key is then
X >an argument to crypt, and hence is visible from ps. But when crypt
X >runs, the first thing it does is to copy the key to an internal buffer
X >and then zero out the argv copy, so the window of vulnerability is
X >vanishingly small.
XAdri Verhoef
X - pointed out a ^D caused a core dump (fixed)
XGene H. Olson
X - format now grows the spreadsheet before setting the column format.
X - removed an extra ';' that caused a possible column number trashing
XPaul Eggert
X -sc now also has round-to-even, also known as ``banker's rounding''.
X >With round-to-even, a number exactly halfway between two values is
X >rounded to whichever is even; e.g. rnd(0.5)=0, rnd(1.5)=2,
X >rnd(2.5)=2, rnd(3.5)=4. This is the default rounding mode for
X >IEEE floating point, for good reason: it has better numeric
X >properties. For example, if X+Y is an integer,
X >then X+Y = rnd(X)+rnd(Y) with round-to-even,
X >but not always with sc's rounding (which is
X >round-to-positive-infinity). I ran into this problem when trying to
X >split interest in an account to two people fairly.
X -While we're on the subject, @round(X,Y) should also work when Y
X >is negative. For example, @round(123,-2) should yield 100.
X
X
XCHANGES BETWEEN 6.8 and 6.7
X
XJeff Buhrt (with help from some beta testers-Thank you)
X 1) added a per row memory allocation
X -runs in about 1/2 run time and 1/3 the space of 6.6vm.1
X -insert/delete row now just moves pointers (# == maxrow+1-currow)
X and blanks one row (of columns (maxcol))
X -as the number of cells grows the size is more linear
X (no more ##Meg images except for 100,000's of rows....)
X -row to column pointer translation is done by a macro (ATBL)
X that returns a pointer to the cell pointer.
X *ATBL would be a pointer to a *ent (cell).
X -the maximum # of columns is limited by ABSMAXCOLS or
X sizeof(struct ent *)*maxcols (whichever is smaller)
X (702 * 4 = 2808 is no real limit even for 286 large model)
X -the maximum # of rows is limited by the virtual memory limit or
X sizeof(struct ent **)*maxrows (whichever is smaller)
X (4*X=64k, X=16384 rows (excluding malloc overhead) on
X a '286 large model. Even w/ 3.25Meg and 10Mhz)
X (plus of course any memory used for cells)
X 2) dolookup (int vs double)
X 3) dolookup calling eval w/ ent * not enode *
X (dolookup called w/ ent * not enode *)
X 4) cleaned up a lot of .... *x = 0 to (.... *)0 (cmds, interp)
X 5) psc: fwidth/precision were reversed on the output
X 6) Backup copy (on save) using same mode to [path/]#file~
X (will prompt if a backup fails)
X 7) put y/n prompt function into yn_ask(mesg)
X 8) found a move(x,y) in sc -> move(y,x) and only move when needed
X 9) we use FullUpdate || changed (to see if ANY cells changed)
X before trying to redraw the screen in update
X (now we don't try to redraw every time a key is hit)
X -if we are stand[ing]out we do not create a cell just to force a
X standout inside the repaint section of update()
X -only draw blank cells if we cleared it or it is standing out
X reason: the less work (what to update) curses has to do, the faster
X a screen update will be (less cpu required)
X 14) {insert, delete}col replaced w/ {open,close}col(currow, numcol_to_insert)
X (limits looping)
X 6.7.1.1
X 15) goto nonexistant cell may loop
X 16) make sure that startup size will at least fill the screen w/ cells.
X 17) added version.c
X 6.7.1.2
X 18) When we would normally die w/o saving (SIGQUIT, etc), we now ask
X if people would like to save the current spreadsheet.
X If 'y', saves to the current file name, otherwise ~/SC.SAVE,
X then /tmp/SC.SAVE if all else fails.
X 6.7.1.3
X 19) don't use malloc.c for production code
X 20) progname is now truncated to just the basename (systems w/ long paths
X caused problems)
X
XCHANGES BETWEEN 6.1 and 6.7
X
XDave Lewis -
X Found and fixed a null pointer derefrece in the 'R' command.
X
XRob McMahon -
X Changed the ctl() macro to work with ANSI style compilers.
X Cleaned up some non-readonly text problems.
X
XRick Linck -
X Fixed a bug in lex.c - Ann Arbor Ambassadors have long ks and ke
X termcap entries.
X
XSam Drake -
X A fix for undefined C_* symbols in AIX.
X
XPeter Brower -
X Cleaned up the INTERNATIONAL ifdefs with more portable code.
X
XGlen Ditchfield
X Cleaned up a problem in crypt.c when the encrypted file shrank.
X
XBob Bond -
X Vi style editing for the command line.
X A bug in range name aliases.
X
XJeff Buhrt -
X -Added "~" filename expansion.
X -702 columns (A-ZZ) and unlimited rows/cells based on max. memory
X -fixed a few bugs
X -slightly decreased CPU usage
X -MAKES backup copies of files
X -understands ~$HOME stuff
X
XCHANGES BETWEEN 5.1 and 6.1:
X
XAndy Valencia -
X xmalloc aligns data to a double boundary.
X
XLawrence Cipriani -
X Fixed a bug in the "do you want to save this" sequence.
X
XSoren Lundsgaard -
X A null pointer derefrence.
X
XRick Perry -
X Cleaned up a problem with modchk() in sc.c.
X
XGregory Bond -
X Added code for multi argument versions of @min and @max.
X
XTad Mannes -
X Added code to save/restore hidden rows and columns when the
X data base is saved or restored.
X
XMarius Olafsson -
X INTERNATIONAL changes. Allows full 8 bit characters (if
X curses supports them.)
X
XKurt Horton -
X Added support for @pv, @fv and @pmt financial functins.
X Tested lots of different systems, linting.
X
XJohn Campbell -
X Support for VMS. See VMS_NOTES.
X
XPeter King -
X User selection of row or column order for recalculation.
X Also affects order of traversing regions in /f and /r
X User setting of automatic or manual recalculation.
X User setting of number of times to try recalculation.
X + and - commands when in non-numeric mode to do
X increment and decrement operations.
X @index, @stindex, @atan2, @lookup functions.
X Save/restore options.
X Support for TeX, LaTeX, and better support for tbl in "T" cmd.
X Provision of a copyent function to copy entries (same code repeated
X in several locations)
X Forwrow, backrow, forwcol, backcol functions to replace
X repeated code
X Correct interpretation of ESCAPE or ^G as an abort when in a
X two character command such as 'ar' or 'ac'
X Cleanup in eval() - catches non-trap function errors.
X
XBob Bond -
X Added search options to "g".
X Added supression of hidden columns to "W"
X Added the mod operator "%"
X New help functions.
X Constant prescale "$"
X Added string matching to @lookup.
X Some more bug fixes.
X Testing, integration, documentation.
X
XAlan Silverstein-
X Greatly revised the manual entry.
X Added menus for ^E command and row/column commands, which
X involved a bunch of code cleanup.
X
X Changed top row display to clearly indicate string labels
X versus number parts, and to distinguish string functions from
X constant labels.
X
X When the character cursor is on a cell (not topline), ^H
X (backspace) is like ^B (move back one cell), rather than being
X ignored.
X
X When the character cursor is on a cell (not topline), ^I (tab)
X is like ^F (move forward one cell), rather than being ignored.
X ^R is no longer identical with ^L. Now ^R highlights all cells
X which should be entered by a user because they contain constant
X numeric values (not the result of a numeric expression).
X
X Added a ^X command, similar to ^R, which highlights cells which
X have expressions. It also displays the expressions in the
X highlighted cells as left-justified strings, instead of the
X label and/or value of the cell.
X
X Added indirection functions (@nval() and @sval()) for simple
X table lookups. Given a column name and row number, they return
X the numeric or string value of the selected cell.
X
X Added external functions (@ext()) for non-trivial
X computations. Given a command name and argument, it calls the
X command and reads back one output line.
X
X Added a ^T,e command to toggle enabling of external functions.
X
X Changed ^T,t to only control the top line display, and added
X ^T,c to control current cell highlighting. (Separated the
X functions.)
X
X "!" (shell escape) gives a vi-style warning if there were any
X changes since the last write. (No change to manual entry.)
X
X Fixed some startup, error, and prompt messages to be cleaner
X and/or more consistent. (No changes to manual entry.)
X
X Fixed a bug: If @substr() upper bound (third parameter) is
X past the end of the string operand, return the substring
X through the end of the string, rather than returning a null
X string.
X
X Fixed a bug: Reset SIGINT to default after forking before
X calling shell escape program and before starting pipeline (for
X commands which support this). Didn't reset SIGINT before
X calling crypt and external functions because in both cases it
X should be irrelevant. (No change to manual entry.)
X
XCHANGES BETWEEN 6.1 and 6.2:
X
X
XChris Cole-
X Compatibility with Lotus 1-2-3
X a) @hlookup(expr,range,expr)
X b) @vlookup(expr,range,expr)
X c) @round(expr,expr)
X d) @if(expr,expr,expr)
X e) @abs(expr)
END_OF_FILE
if test 16317 -ne `wc -c <'CHANGES'`; then
echo shar: \"'CHANGES'\" unpacked with wrong size!
fi
# end of 'CHANGES'
fi
if test -f 'format.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'format.c'\"
else
echo shar: Extracting \"'format.c'\" \(14370 characters\)
sed "s/^X//" >'format.c' <<'END_OF_FILE'
X/*****************************************************************************
X *
X * Mark Nagel <nagel at ics.uci.edu>
X * 20 July 1989
X *
X * $Revision: 6.16 $
X *
X * bool
X * format(fmt, num, buf, buflen)
X * char *fmt;
X * double num;
X * char buf[];
X * int buflen;
X *
X * The format function will produce a string representation of a number
X * given a _format_ (described below) and a double value. The result is
X * written into the passed buffer -- if the resulting string is too
X * long to fit into the passed buffer, the function returns false.
X * Otherwise the function returns true.
X *
X * The fmt parameter contains the format to use to convert the number.
X *
X * # Digit placeholder. If the number has fewer digits on either
X * side of the decimal point than there are '#' characters in
X * the format, the extra '#' characters are ignored. The number
X * is rounded to the number of digit placeholders as there are
X * to the right of the decimal point. If there are more digits
X * in the number than there are digit placeholders on the left
X * side of the decimal point, then those digits are displayed.
X *
X * 0 Digit placeholder. Same as for '#' except that the number
X * is padded with zeroes on either side of the decimal point.
X * The number of zeroes used in padding is determined by the
X * number of digit placeholders after the '0' for digits on
X * the left side of the decimal point and by the number of
X * digit placeholders before the '0' for digits on the right
X * side of the decimal point.
X *
X * . Decimal point. Determines how many digits are placed on
X * the right and left sides of the decimal point in the number.
X * Note that numbers smaller than 1 will begin with a decimal
X * point if the left side of the decimal point contains only
X * a '#' digit placeholder. Use a '0' placeholder to get a
X * leading zero in decimal formats.
X *
X * % Percentage. For each '%' character in the format, the actual
X * number gets multiplied by 100 (only for purposes of formatting
X * -- the original number is left unmodified) and the '%' character
X * is placed in the same position as it is in the format.
X *
X * , Thousands separator. The presence of a ',' in the format
X * (multiple commas are treated as one) will cause the number
X * to be formatted with a ',' separating each set of three digits
X * in the integer part of the number with numbering beginning
X * from the right end of the integer.
X *
X * \ Quote. This character causes the next character to be
X * inserted into the formatted string directly with no
X * special interpretation.
X *
X * E- E+ e- e+
X * Scientific format. Causes the number to formatted in scientific
X * notation. The case of the 'E' or 'e' given is preserved. If
X * the format uses a '+', then the sign is always given for the
X * exponent value. If the format uses a '-', then the sign is
X * only given when the exponent value is negative. Note that if
X * there is no digit placeholder following the '+' or '-', then
X * that part of the formatted number is left out. In general,
X * there should be one or more digit placeholders after the '+'
X * or '-'.
X *
X * ; Format selector. Use this character to separate the format
X * into two distinct formats. The format to the left of the
X * ';' character will be used if the number given is zero or
X * positive. The format to the right of the ';' character is
X * used if the number given is negative.
X *
X * Any
X * Self insert. Any other character will be inserted directly
X * into the formatted number with no change made to the actual
X * number.
X *
X *****************************************************************************/
X
X/*****************************************************************************/
X
X#include <stdio.h>
X#include "sc.h"
X
X#define bool int
X#define true 1
X#define false 0
X#define EOS '\0'
X#define MAXBUF 256
X
Xextern char
X *strcpy(),
X *strcat();
X
Xstatic char
X *fmt_int(),
X *fmt_frac(),
X *fmt_exp();
X
Xstatic void
X reverse();
X
X/*****************************************************************************/
X
Xbool
Xformat(fmt, val, buf, buflen)
X char *fmt;
X double val;
X char *buf;
X int buflen;
X{
X register char *cp;
X char *tmp, *tp;
X bool comma = false, negative = false;
X char *integer = NULL, *decimal = NULL;
X char *exponent = NULL;
X int exp_val, width;
X char prtfmt[32];
X static char *mantissa = NULL;
X static char *tmpfmt1 = NULL, *tmpfmt2 = NULL, *exptmp = NULL;
X static unsigned mantlen = 0, fmtlen = 0;
X char *fraction = NULL;
X int zero_pad = 0;
X
X if (fmt == NULL)
X return(true);
X
X if (strlen(fmt) + 1 > fmtlen)
X { fmtlen = strlen(fmt) + 40;
X tmpfmt1 = xrealloc(tmpfmt1, fmtlen);
X tmpfmt2 = xrealloc(tmpfmt2, fmtlen);
X exptmp = xrealloc(exptmp, fmtlen);
X }
X fmt = strcpy(tmpfmt1, fmt);
X if (buflen + 1 > mantlen)
X { mantlen = buflen + 40;
X mantissa = xrealloc(mantissa, mantlen);
X }
X
X /*
X * select positive or negative format if necessary
X */
X for (cp = fmt; *cp != ';' && *cp != EOS; cp++)
X {
X if (*cp == '\\')
X cp++;
X }
X if (*cp == ';')
X {
X if (val < 0.0)
X {
X val = -val; /* format should provide sign if desired */
X fmt = cp + 1;
X }
X else
X {
X *cp = EOS;
X }
X }
X
X /*
X * extract other information from format and produce a
X * format string stored in tmpfmt2 also xmalloc()'d above
X */
X tmp = tmpfmt2;
X for (cp = fmt, tp = tmp; *cp != EOS; cp++)
X {
X switch (*cp)
X {
X case '\\':
X *tp++ = *cp++;
X *tp++ = *cp;
X break;
X
X case ',':
X comma = true;
X break;
X
X case '.':
X if (decimal == NULL)
X decimal = tp;
X *tp++ = *cp;
X break;
X
X case '%':
X val *= 100.0;
X *tp++ = *cp;
X break;
X
X default:
X *tp++ = *cp;
X break;
X }
X }
X *tp = EOS;
X fmt = tmpfmt2;
X
X if (val < 0.0)
X { negative = true;
X val = -val;
X }
X /*
X * extract the exponent from the format if present
X */
X for (cp = fmt; *cp != EOS; cp++)
X { if (*cp == '\\')
X {
X cp++;
X }
X else if (*cp == 'e' || *cp == 'E')
X {
X if (cp[1] == '+' || cp[1] == '-')
X {
X exponent = strcpy(exptmp, cp);
X *cp = EOS;
X exp_val = 0;
X if (val!=0.0) {
X while (val < 1.0)
X {
X val *= 10.0;
X exp_val--;
X }
X while (val >= 10.0)
X {
X val /= 10.0;
X exp_val++;
X }
X }
X break;
X }
X }
X }
X
X /*
X * determine maximum decimal places and use sprintf
X * to build initial character form of formatted value.
X */
X width = 0;
X if (decimal)
X {
X *decimal++ = EOS;
X for (cp = decimal; *cp != EOS; cp++)
X {
X switch (*cp)
X {
X case '\\':
X cp++;
X break;
X
X case '#':
X width++;
X break;
X
X case '0':
X zero_pad = ++width;
X break;
X }
X }
X zero_pad = strlen(decimal) - zero_pad;
X }
X (void) sprintf(prtfmt, "%%.%dlf", width);
X (void) sprintf(mantissa, prtfmt, val);
X for (cp = integer = mantissa; *cp != '.' && *cp != EOS; cp++)
X {
X if (*integer == '0')
X integer++;
X }
X if (*cp == '.')
X {
X fraction = cp + 1;
X *cp = EOS;
X cp = fraction + strlen(fraction) - 1;
X for (; zero_pad > 0; zero_pad--, cp--)
X {
X if (*cp == '0')
X *cp = EOS;
X }
X }
X
X /*
X * format the puppy
X */
X {
X static char *citmp = NULL, *cftmp = NULL;
X static unsigned cilen = 0, cflen = 0;
X char *ci, *cf, *ce;
X int len_ci, len_cf, len_ce;
X bool ret = false;
X
X ci = fmt_int(integer, fmt, comma, negative);
X len_ci = strlen(ci);
X if (len_ci >= cilen)
X { cilen = len_ci + 40;
X citmp = xrealloc(citmp, cilen);
X }
X ci = strcpy(citmp, ci);
X
X cf = (fraction) ? fmt_frac(fraction, decimal) : "";
X len_cf = strlen(cf);
X if (len_cf >= cflen)
X { cflen = len_cf + 40;
X cftmp = xrealloc(cftmp, cilen);
X }
X cf = strcpy(cftmp, cf);
X
X ce = (exponent) ? fmt_exp(exp_val, exponent) : "";
X len_ce = strlen(ce);
X/*
X * Skip copy assuming sprintf doesn't call our format functions
X * ce = strcpy(xmalloc((unsigned)((len_ce = strlen(ce)) + 1)), ce);
X */
X if (len_ci + len_cf + len_ce < buflen)
X {
X (void) sprintf(buf, "%s%s%s", ci, cf, ce);
X ret = true;
X }
X
X return (ret);
X }
X}
X
X/*****************************************************************************/
X
Xstatic char *
Xfmt_int(val, fmt, comma, negative)
X char *val; /* integer part of the value to be formatted */
X char *fmt; /* integer part of the format */
X bool comma; /* true if we should comma-ify the value */
X bool negative; /* true if the value is actually negative */
X{
X int digit, f, v;
X int thousands = 0;
X char *cp;
X static char buf[MAXBUF];
X char *bufptr = buf;
X
X /*
X * locate the leftmost digit placeholder
X */
X for (cp = fmt; *cp != EOS; cp++)
X {
X if (*cp == '\\')
X cp++;
X else if (*cp == '#' || *cp == '0')
X break;
X }
X digit = (*cp == EOS) ? -1 : cp - fmt;
X
X /*
X * format the value
X */
X f = strlen(fmt) - 1;
X v = (digit >= 0) ? strlen(val) - 1 : -1;
X while (f >= 0 || v >= 0)
X {
X if (f > 0 && fmt[f-1] == '\\')
X {
X *bufptr++ = fmt[f--];
X }
X else if (f >= 0 && (fmt[f] == '#' || fmt[f] == '0'))
X {
X if (v >= 0 || fmt[f] == '0')
X {
X *bufptr++ = v < 0 ? '0' : val[v];
X if (comma && (thousands = (thousands + 1) % 3) == 0 && v > 0)
X {
X *bufptr++ = ',';
X }
X v--;
X }
X }
X else if (f >= 0)
X {
X *bufptr++ = fmt[f];
X }
X if (v >= 0 && f == digit)
X {
X continue;
X }
X f--;
X }
X
X if (negative && digit >= 0)
X *bufptr++ = '-';
X *bufptr = EOS;
X reverse(buf);
X
X return (buf);
X}
X
X/*****************************************************************************/
X
Xstatic char *
Xfmt_frac(val, fmt)
X char *val; /* fractional part of the value to be formatted */
X char *fmt; /* fractional portion of format */
X{
X static char buf[MAXBUF];
X register char *bufptr = buf;
X register char *fmtptr = fmt, *valptr = val;
X
X *bufptr++ = '.';
X while (*fmtptr != EOS)
X {
X if (*fmtptr == '\\')
X {
X *bufptr++ = *++fmtptr;
X }
X else if (*fmtptr == '#' || *fmtptr == '0')
X {
X if (*valptr != EOS || *fmtptr == '0')
X {
X *bufptr++ = (*valptr != EOS) ? *valptr++ : *fmtptr;
X }
X }
X else
X {
X *bufptr++ = *fmtptr;
X }
X fmtptr++;
X }
X *bufptr = EOS;
X
X return (buf);
X}
X
X/*****************************************************************************/
X
Xstatic char *
Xfmt_exp(val, fmt)
X int val; /* value of the exponent */
X char *fmt; /* exponent part of the format */
X{
X static char buf[MAXBUF];
X register char *bufptr = buf;
X char valbuf[64];
X bool negative = false;
X
X *bufptr++ = *fmt++;
X if (*fmt == '+')
X *bufptr++ = (val < 0) ? '-' : '+';
X else if (val < 0)
X *bufptr++ = '-';
X fmt++;
X *bufptr = EOS;
X
X if (val < 0)
X {
X val = -val;
X negative = false;
X }
X (void) sprintf(valbuf, "%d", val);
X
X (void) strcat(buf, fmt_int(valbuf, fmt, false, negative));
X return (buf);
X}
X
X/*****************************************************************************/
X
Xstatic void
Xreverse(buf)
X register char *buf;
X{
X register char *cp = buf + strlen(buf) - 1;
X register char tmp;
X
X while (buf < cp)
X {
X tmp = *cp;
X *cp-- = *buf;
X *buf++ = tmp;
X }
X}
X
X/*****************************************************************************/
X/*
X * Tom Anderson <toma at hpsad.hp.com>
X * 10/14/90
X *
X * This routine takes a value and formats it using fixed, scientific,
X * or engineering notation. The format command 'f' determines which
X * format is used. The formats are: example
X * 0: Fixed point (default) 0.00010
X * 1: Scientific 1.00E-04
X * 2: Engineering 100.00u
X *
X * The format command 'f' now uses three values. The first two are the
X * width and precision, and the last one is the format value 0, 1, or 2 as
X * described above. The format value is passed in the variable fmt.
X *
X * This formatted value is written into the passed buffer. if the
X * resulting string is too long to fit into the passed buffer, the
X * function returns false. Otherwise the function returns true.
X *
X * When a number is formatted as engineering and is outside of the range
X * of typically used engineering exponents, the format reverts to
X * scientific.
X *
X * To preserve compatability with old spreadsheet files, the third value
X * may be missing, and the default will be fixed point (format 0).
X *
X * When an old style sheet is saved, the third value will be stored.
X *
X */
X
X#define REFMTFIX 0
X#define REFMTFLT 1
X#define REFMTENG 2
Xchar engmult[] = "afpnum kMGT";
X
Xbool
Xengformat(fmt, width, lprecision, val, buf, buflen)
Xint fmt;
Xint width;
Xint lprecision;
Xdouble val;
Xchar *buf;
Xint buflen;
X{
X int engind = 0;
X double engmant, pow(), engabs, engexp;
X if (buflen < width) return (false);
X if (fmt == REFMTFIX)
X (void) sprintf(buf,"%*.*f", width, lprecision, val);
X if (fmt == REFMTFLT)
X (void) sprintf(buf,"%*.*E", width, lprecision, val);
X if (fmt == REFMTENG)
X {
X if (val == 0e0) /* Hack to get zeroes to line up in engr fmt */
X {
X (void) sprintf((buf-1),"%*.*f ", width, lprecision, val);
X }
X else
X {
X engabs=(val);
X if (engabs < 0e0) engabs= -engabs;
X if ((engabs >= 1e-18) && (engabs < 1e-15 )) engind=0;
X if ((engabs >= 1e-15) && (engabs < 1e-12 )) engind=1;
X if ((engabs >= 1e-12) && (engabs < 1e-9 )) engind=2;
X if ((engabs >= 1e-9) && (engabs < 1e-6 )) engind=3;
X if ((engabs >= 1e-6) && (engabs < 1e-3 )) engind=4;
X if ((engabs >= 1e-3) && (engabs < 1 )) engind=5;
X if ((engabs >= 1) && (engabs < 1e3 )) engind=6;
X if ((engabs >= 1e3) && (engabs < 1e6 )) engind=7;
X if ((engabs >= 1e6) && (engabs < 1e9 )) engind=8;
X if ((engabs >= 1e9) && (engabs < 1e12 )) engind=9;
X if ((engabs >= 1e12) && (engabs < 1e15 )) engind=10;
X if ((engabs <1e-18) || (engabs >=1e15))
X {
X /* Revert to floating point */
X (void) sprintf(buf,"%*.*E", width, lprecision, val);
X }
X else
X {
X engexp= (double) (engind-6)*3;
X engmant= val/pow(10.0e0,engexp);
X (void) sprintf(buf,"%*.*f%c", width-1,
X lprecision, engmant, engmult[engind]);
X }
X }
X }
X return (true);
X}
END_OF_FILE
if test 14370 -ne `wc -c <'format.c'`; then
echo shar: \"'format.c'\" unpacked with wrong size!
fi
# end of 'format.c'
fi
if test -f 'psc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'psc.c'\"
else
echo shar: Extracting \"'psc.c'\" \(7176 characters\)
sed "s/^X//" >'psc.c' <<'END_OF_FILE'
X/* Sc parse routine
X *
X * usage psc options
X * options:
X * -L Left justify strings. Default is right justify.
X * -r Assemble data into rows first, not columns.
X * -R n Increment by n between rows
X * -C n Increment by n between columns
X * -n n Length of the row (column) should be n.
X * -s v Top left location in the spreadsheet should be v; eg, k5
X * -d c Use c as the delimiter between the fields.
X * -k Keep all delimiters - Default is strip multiple delimiters to 1.
X * -f suppress 'format' lines in output
X * -S Use strings vs numbers for numbers
X * -P Use numbers only when there is no [-+eE] (plain numbers only)
X *
X * Author: Robert Bond
X * Adjustments: Jeff Buhrt and Eric Putz
X */
Xchar *rev = "$Revision: 6.16 $";
X
X#include <ctype.h>
X#include <stdio.h>
X#include "sc.h"
X
X#define END 0
X#define NUM 1
X#define ALPHA 2
X#define SPACE 3
X#define EOL 4
X
Xextern char *optarg;
Xextern int optind;
Xchar *coltoa();
Xchar *progname;
X
X#ifdef SYSV3
Xextern void exit();
X#else
Xextern int exit();
X#endif
X
Xint *fwidth;
Xint *precision;
Xint maxcols;
Xint *realfmt;
X
X/* option flags reset */
Xint colfirst = FALSE;
Xint leftadj = FALSE;
Xint r0 = 0;
Xint c0 = 0;
Xint rinc = 1;
Xint cinc = 1;
Xint len = 20000;
Xchar delim1 = ' ';
Xchar delim2 = '\t';
Xint strip_delim = TRUE;
Xint drop_format = FALSE;
Xint strnums = FALSE;
Xint plainnums = FALSE;
X
Xchar token[1000];
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X int curlen;
X int curcol, coff;
X int currow, roff;
X int first;
X int c;
X register effr, effc;
X int i,j;
X register char *p;
X
X progname = argv[0];
X while ((c = getopt(argc, argv, "rfLks:R:C:n:d:SPv")) != EOF) {
X switch(c) {
X case 'r':
X colfirst = TRUE;
X break;
X case 'L':
X leftadj = TRUE;
X break;
X case 's':
X c0 = getcol(optarg);
X r0 = getrow(optarg);
X break;
X case 'R':
X rinc = atoi(optarg);
X break;
X case 'C':
X cinc = atoi(optarg);
X break;
X case 'n':
X len = atoi(optarg);
X break;
X case 'd':
X delim1 = optarg[0];
X delim2 = '\0';
X break;
X case 'k':
X strip_delim = FALSE;
X break;
X case 'f':
X drop_format = TRUE;
X break;
X case 'S':
X strnums = TRUE;
X break;
X case 'P':
X plainnums = TRUE;
X break;
X case 'v':
X (void) fprintf(stderr,"%s: %s\n", progname, rev);
X default:
X (void) fprintf(stderr,"Usage: %s [-rkfLSPv] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
X exit(1);
X }
X }
X
X if (optind < argc) {
X (void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
X exit(1);
X }
X
X /* setup the spreadsheet arrays */
X if (!growtbl(GROWNEW, 0, 0))
X exit(1);
X
X curlen = 0;
X curcol = c0; coff = 0;
X currow = r0; roff = 0;
X first = TRUE;
X
X while(1) {
X
X effr = currow+roff;
X effc = curcol+coff;
X
X switch(scan()) {
X case END:
X if(drop_format) exit(0);
X for (i = 0; i<maxcols; i++) {
X if (fwidth[i])
X (void) printf("format %s %d %d\n", coltoa(i),
X fwidth[i]+1, precision[i]);
X }
X exit(0);
X case NUM:
X first = FALSE;
X (void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
X if (effc >= maxcols - 1)
X { if (!growtbl(GROWCOL, 0, effc))
X { (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
X continue;
X }
X }
X i = 0;
X j = 0;
X p = token;
X while (*p && *p != '.') {
X p++; i++;
X }
X if (*p) {
X p++; i++;
X }
X while (*p) {
X p++; i++; j++;
X }
X { int ow, nw;
X
X ow = fwidth[effc] - precision[effc];
X if (precision[effc] < j)
X precision[effc] = j;
X
X if (fwidth[effc] < i)
X fwidth[effc] = i;
X
X /* now make sure:
X * 1234.567890 (format 11 6)
X * 1234567.890 (format 11 3)
X * both show (format 14 6)
X * (really it uses 15 6 to separate columns)
X */
X if ((nw = i - j) > ow)
X fwidth[effc] += nw - (fwidth[effc] - precision[effc]);
X }
X break;
X case ALPHA:
X first = FALSE;
X if (leftadj)
X (void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token);
X else
X (void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token);
X if (effc >= maxcols - 1)
X { if (!growtbl(GROWCOL, 0, effc))
X { (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
X continue;
X }
X }
X i = strlen(token);
X if (i > fwidth[effc])
X fwidth[effc] = i;
X break;
X case SPACE:
X if (first && strip_delim)
X break;
X if (colfirst)
X roff++;
X else
X coff++;
X break;
X case EOL:
X curlen++;
X roff = 0;
X coff = 0;
X first = TRUE;
X if (colfirst) {
X if (curlen >= len) {
X curcol = c0;
X currow += rinc;
X curlen = 0;
X } else {
X curcol += cinc;
X }
X } else {
X if (curlen >= len) {
X currow = r0;
X curcol += cinc;
X curlen = 0;
X } else {
X currow += rinc;
X }
X }
X break;
X }
X }
X}
X
Xscan()
X{
X register int c;
X register char *p;
X register int founddigit;
X
X p = token;
X c = getchar();
X
X if (c == EOF)
X return(END);
X
X if (c == '\n')
X return(EOL);
X
X if (c == delim1 || c == delim2) {
X if (strip_delim) {
X while ((c = getchar()) && (c == delim1 || c == delim2))
X ;
X (void)ungetc(c, stdin);
X }
X return(SPACE);
X }
X
X if (c == '\"') {
X while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
X *p++ = c;
X if (c != '\"')
X (void)ungetc(c, stdin);
X *p = '\0';
X return(ALPHA);
X }
X
X while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
X *p++ = c;
X c = getchar();
X }
X *p = '\0';
X (void)ungetc(c, stdin);
X
X p = token;
X c = *p;
X founddigit = FALSE;
X /*
X * str_nums always returns numbers as strings
X * plainnums returns 'numbers' with [-+eE] in them as strings
X * lastprtnum makes sure a number ends in one of [0-9eE.]
X */
X if (!strnums && (isdigit(c) || c == '.' || c == '-' || c == '+')) {
X int lastprtnum = FALSE;
X
X while(isdigit(c) || c == '.' || (!plainnums && (c == '-' ||
X c == '+' || c == 'e' || c == 'E'))) {
X if (isdigit(c))
X lastprtnum = founddigit = TRUE;
X else
X if (!(c == '.' || c == 'e' || c == 'E'))
X lastprtnum = FALSE;
X c = *p++;
X }
X if (c == '\0' && founddigit && lastprtnum)
X return(NUM);
X else
X return(ALPHA);
X }
X
X return(ALPHA);
X}
X
X/* turns [A-Z][A-Z] into a number */
Xgetcol(p)
Xchar *p;
X{
X register col;
X
X col = 0;
X if (!p)
X return(0);
X while(*p && !isalpha(*p))
X p++;
X if (!*p)
X return(0);
X col = ((*p & 0137) - 'A');
X if (isalpha(*++p))
X col = (col + 1)*26 + ((*p & 0137) - 'A');
X return(col);
X}
X
X/* given a string turn it into a row number */
Xgetrow(p)
Xchar *p;
X{
X int row;
X
X row = 0;
X if (!p)
X return(0);
X while(*p && !isdigit(*p))
X p++;
X if (!*p)
X return(0);
X while(*p && isdigit(*p))
X { row = row * 10 + *p - '0';
X p++;
X }
X return(row);
X}
X
X/* turns a column number into [A-Z][A-Z] */
Xchar *
Xcoltoa(col)
Xint col;
X{
X static char rname[3];
X register char *p = rname;
X
X if (col < 0 || col > 27*26) /* A-Z, AA-ZZ */
X (void) fprintf(stderr,"coltoa: invalid col: %d", col);
X
X if (col > 25) {
X *p++ = col/26 + 'A' - 1;
X col %= 26;
X }
X *p++ = col+'A';
X *p = '\0';
X return(rname);
X}
END_OF_FILE
if test 7176 -ne `wc -c <'psc.c'`; then
echo shar: \"'psc.c'\" unpacked with wrong size!
fi
# end of 'psc.c'
fi
if test -f 'screen.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'screen.c'\"
else
echo shar: Extracting \"'screen.c'\" \(13867 characters\)
sed "s/^X//" >'screen.c' <<'END_OF_FILE'
X/* SC A Spreadsheet Calculator
X * Curses based Screen driver
X *
X * original by James Gosling, September 1982
X * modifications by Mark Weiser and Bruce Israel,
X * University of Maryland
X *
X * More mods Robert Bond, 12/86
X * More mods by Alan Silverstein, 3-4/88, see list of changes.
X * Currently supported by sequent!sawmill!buhrt (Jeff Buhrt)
X * $Revision: 6.16 $
X *
X */
X
X
X#include <curses.h>
X#include "sc.h"
X
X#ifdef BROKENCURSES
X /* nl/nonl bug fix */
X#undef nl
X#undef nonl
X#define nl() (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty))
X#define nonl() (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty))
X#endif
X
Xvoid repaint();
X
Xchar under_cursor = ' '; /* Data under the < cursor */
Xchar mode_ind = '.';
Xextern char revmsg[];
X
Xint rows, cols;
Xint lastmx, lastmy; /* Screen address of the cursor */
Xint lastcol; /* Spreadsheet Column the cursor was in last */
Xextern int *fwidth;
Xextern int showrange; /* Causes ranges to be highlighted */
Xextern int showneed; /* Causes cells needing values to be highlighted */
Xextern int showexpr; /* Causes cell exprs to be displayed, highlighted */
X
X/*
X * update() does general screen update
X *
X * standout last time in update()?
X * At this point we will let curses do work
X */
Xint standlast = FALSE;
X
Xvoid
Xupdate (anychanged)
Xint anychanged; /* did any cell really change in value? */
X{
X register row, col;
X register struct ent **pp;
X int mxrow, mxcol;
X int minsr = 0, minsc = 0, maxsr = 0, maxsc = 0;
X register r;
X register i;
X static int lastcurcol = -1, lastcurrow = -1;
X
X /*
X * place the cursor on the screen, set col, curcol, stcol, lastcol as
X * needed
X */
X if ((curcol != lastcurcol) || FullUpdate)
X {
X while (col_hidden[curcol]) /* You can't hide the last row or col */
X curcol++;
X
X /* First see if the last display still covers curcol */
X if (stcol <= curcol) {
X for (i = stcol, cols = 0, col = RESCOL;
X (col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
X cols++;
X
X if (col_hidden[i])
X continue;
X col += fwidth[i];
X }
X }
X while (stcol + cols - 1 < curcol || curcol < stcol) {
X FullUpdate++;
X if (stcol - 1 == curcol) { /* How about back one? */
X stcol--;
X } else if (stcol + cols == curcol) { /* Forward one? */
X stcol++;
X } else {
X /* Try to put the cursor in the center of the screen */
X col = (COLS - RESCOL - fwidth[curcol]) / 2 + RESCOL;
X stcol = curcol;
X for (i=curcol-1; i >= 0 && col-fwidth[i] > RESCOL; i--)
X { stcol--;
X if (col_hidden[i])
X continue;
X col -= fwidth[i];
X }
X }
X /* Now pick up the counts again */
X for (i = stcol, cols = 0, col = RESCOL;
X (col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
X cols++;
X if (col_hidden[i])
X continue;
X col += fwidth[i];
X }
X }
X lastcurcol = curcol;
X }
X
X /* Now - same process on the rows as the columns */
X if ((currow != lastcurrow) || FullUpdate)
X {
X while (row_hidden[currow]) /* You can't hide the last row or col */
X currow++;
X if (strow <= currow) {
X for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++)
X { rows++;
X if (row_hidden[i])
X continue;
X row++;
X }
X }
X
X while (strow + rows - 1 < currow || currow < strow) {
X FullUpdate++;
X if (strow - 1 == currow) { /* How about up one? */
X strow--;
X } else if (strow + rows == currow) { /* Down one? */
X strow++;
X } else {
X /* Try to put the cursor in the center of the screen */
X row = (LINES - RESROW) / 2 + RESROW;
X strow = currow;
X for (i=currow-1; i >= 0 && row-1 > RESROW; i--) {
X strow--;
X if (row_hidden[i])
X continue;
X row--;
X }
X }
X /* Now pick up the counts again */
X for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
X rows++;
X if (row_hidden[i])
X continue;
X row++;
X }
X }
X lastcurrow = currow;
X }
X mxcol = stcol + cols - 1;
X mxrow = strow + rows - 1;
X
X /* Get rid of cursor standout on the cell at previous cursor position */
X if (!FullUpdate)
X { if (showcell)
X repaint(lastmx, lastmy, fwidth[lastcol]);
X
X (void) move(lastmy, lastmx+fwidth[lastcol]);
X
X if ((inch() & A_CHARTEXT ) == '<')
X (void) addch(under_cursor);
X }
X
X /* where is the the cursor now? */
X lastmy = RESROW;
X for (row = strow; row < currow; row++)
X if (!row_hidden[row])
X lastmy++;
X
X lastmx = RESCOL;
X for (col = stcol; col < curcol; col++)
X if (!col_hidden[col])
X lastmx += fwidth[col];
X lastcol = curcol;
X
X if (FullUpdate || standlast) {
X (void) move(2, 0);
X (void) clrtobot();
X (void) standout();
X
X for (row=RESROW, i=strow; i <= mxrow; i++) {
X if (row_hidden[i])
X continue;
X (void) move(row,0);
X if (maxrows < 1000)
X (void) printw("%-*d", RESCOL-1, i);
X else
X (void) printw("%-*d", RESCOL, i);
X row++;
X }
X (void) move(2,0);
X (void) printw("%*s", RESCOL, " ");
X
X for (col=RESCOL, i = stcol; i <= mxcol; i++) {
X register int k;
X if (col_hidden[i])
X continue;
X (void) move(2, col);
X k = fwidth[i]/2;
X if (k == 0)
X (void) printw("%1s", coltoa(i));
X else
X (void) printw("%*s%-*s", k, " ", fwidth[i]-k, coltoa(i));
X col += fwidth[i];
X }
X (void) standend();
X }
X
X if (showrange) {
X minsr = showsr < currow ? showsr : currow;
X minsc = showsc < curcol ? showsc : curcol;
X maxsr = showsr > currow ? showsr : currow;
X maxsc = showsc > curcol ? showsc : curcol;
X
X if (showtop) {
X (void) move(1,0);
X (void) clrtoeol();
X (void) printw("Default range: %s",
X r_name(minsr, minsc, maxsr, maxsc));
X }
X }
X
X
X /* Repaint the visible screen */
X if (showrange || anychanged || FullUpdate || standlast)
X {
X /* may be reset in loop, if not next time we will do a FullUpdate */
X if (standlast)
X { FullUpdate = TRUE;
X standlast = FALSE;
X }
X
X for (row = strow, r = RESROW; row <= mxrow; row++) {
X register c = RESCOL;
X int do_stand = 0;
X int fieldlen;
X int nextcol;
X
X if (row_hidden[row])
X continue;
X for (pp = ATBL(tbl, row, col = stcol); col <= mxcol;
X pp += nextcol - col, col = nextcol, c += fieldlen) {
X
X nextcol = col+1;
X if (col_hidden[col]) {
X fieldlen = 0;
X continue;
X }
X
X fieldlen = fwidth[col];
X
X /*
X * Set standout if:
X *
X * - showing ranges, and not showing cells which need to be filled
X * in, and not showing cell expressions, and in a range, OR
X *
X * - if showing cells which need to be filled in and this one is
X * of that type (has a value and doesn't have an expression,
X * or it is a string expression), OR
X *
X * - if showing cells which have expressions and this one does.
X */
X if ((showrange && (! showneed) && (! showexpr)
X && (row >= minsr) && (row <= maxsr)
X && (col >= minsc) && (col <= maxsc))
X || (showneed && (*pp) && ((*pp) -> flags & is_valid)
X && (((*pp) -> flags & is_strexpr) || !((*pp) -> expr)))
X || (showexpr && (*pp) && ((*pp) -> expr)))
X {
X (void) move(r, c);
X (void) standout();
X standlast++;
X if (!*pp) /* no cell, but standing out */
X { (void) printw("%*s", fwidth[col], " ");
X (void) standend();
X continue;
X }
X else
X do_stand = 1;
X }
X else
X do_stand = 0;
X
X if ((*pp) && ((*pp) -> flags & is_changed || FullUpdate) || do_stand) {
X if (do_stand) {
X (*pp) -> flags |= is_changed;
X } else {
X (void) move(r, c);
X (*pp) -> flags &= ~is_changed;
X }
X
X /*
X * Show expression; takes priority over other displays:
X */
X
X if ((*pp)->cellerror)
X (void) printw("%*.*s", fwidth[col], fwidth[col],
X (*pp)->cellerror == CELLERROR ? "ERROR" : "INVALID");
X else
X if (showexpr && ((*pp) -> expr)) {
X linelim = 0;
X editexp(row, col); /* set line to expr */
X linelim = -1;
X showstring(line, /* leftflush = */ 1, /* hasvalue = */ 0,
X row, col, & nextcol, mxcol, & fieldlen, r, c);
X } else {
X /*
X * Show cell's numeric value:
X */
X
X if ((*pp) -> flags & is_valid) {
X char field[FBUFLEN];
X
X if ((*pp) -> format) {
X (void) format((*pp) -> format, (*pp) -> v,
X field, sizeof(field));
X } else {
X (void) engformat(realfmt[col], fwidth[col],
X precision[col], (*pp) -> v,
X field, sizeof(field));
X }
X if (strlen(field) > fwidth[col]) {
X for(i = 0; i<fwidth[col]; i++)
X (void)addch('*');
X } else {
X for(i = 0; i < fwidth[col] - strlen(field);i++)
X (void)addch(' ');
X (void)addstr(field);
X }
X }
X
X /*
X * Show cell's label string:
X */
X
X if ((*pp) -> label) {
X showstring((*pp) -> label,
X (*pp) -> flags & is_leftflush,
X (*pp) -> flags & is_valid,
X row, col, & nextcol, mxcol,
X & fieldlen, r, c);
X }
X else /* repaint a blank cell: */
X if ((do_stand || !FullUpdate) &&
X ((*pp)->flags & is_changed) &&
X !((*pp)->flags & is_valid) && !(*pp)->label) {
X (void) printw("%*s", fwidth[col], " ");
X }
X } /* else */
X
X if (do_stand) {
X (void) standend();
X do_stand = 0;
X }
X }
X }
X r++;
X }
X }
X
X /* place 'cursor marker' */
X if (showcell && (! showneed) && (! showexpr)) {
X (void) move(lastmy, lastmx);
X (void) standout();
X repaint(lastmx, lastmy, fwidth[lastcol]);
X (void) standend();
X }
X (void) move(lastmy, lastmx+fwidth[lastcol]);
X under_cursor = (inch() & A_CHARTEXT);
X (void) addch('<');
X
X (void) move(0, 0);
X (void) clrtoeol();
X if (linelim >= 0) {
X (void) addch(mode_ind);
X (void) addstr("> ");
X (void) addstr(line);
X (void) move((linelim + 3) / COLS, (linelim+3) % COLS);
X } else {
X if (showtop) { /* show top line */
X register struct ent *p1;
X
X int printed = 0; /* printed something? */
X
X /* show the current cell's format */
X (void) printw("%s%d ", coltoa(curcol), currow);
X if ((p1 = *ATBL(tbl, currow, curcol)) && p1->format)
X printw("(%s) ", p1->format);
X else
X printw("(%d %d %d) ", fwidth[curcol], precision[curcol],
X realfmt[curcol]);
X
X if (p1) {
X if (p1 -> expr) {
X /* has expr of some type */
X linelim = 0;
X editexp(currow, curcol); /* set line to expr */
X linelim = -1;
X }
X
X /*
X * Display string part of cell:
X */
X
X if ((p1 -> expr) && (p1 -> flags & is_strexpr)) {
X (void) addstr((p1 -> flags & is_leftflush) ? "<{" : ">{");
X (void) addstr(line);
X (void) addstr("} "); /* and this '}' is for vi % */
X printed = 1;
X
X } else if (p1 -> label) {
X /* has constant label only */
X (void) addstr ((p1 -> flags & is_leftflush) ? "<\"" : ">\"");
X (void) addstr (p1 -> label);
X (void) addstr ("\" ");
X printed = 1;
X }
X
X /*
X * Display value part of cell:
X */
X
X if (p1 -> flags & is_valid) {
X /* has value or num expr */
X if ((! (p1 -> expr)) || (p1 -> flags & is_strexpr))
X (void) sprintf (line, "%.15g", p1 -> v);
X
X (void) addch ('[');
X (void) addstr (line);
X (void) addch (']');
X *line = '\0'; /* this is the input buffer ! */
X printed = 1;
X }
X }
X if (! printed)
X (void) addstr ("[]");
X }
X (void) move(lastmy, lastmx+fwidth[lastcol]);
X }
X
X if (revmsg[0]) {
X (void) move(0, 0);
X (void) clrtoeol (); /* get rid of topline display */
X (void) printw(revmsg);
X *revmsg = '\0'; /* don't show it again */
X (void) move (lastmy, lastmx + fwidth[lastcol]);
X }
X
X FullUpdate = FALSE;
X}
X
X/* redraw what is under the cursor from curses' idea of the screen */
Xvoid
Xrepaint(x, y, len)
Xint x, y, len;
X{
X int c;
X
X while(len-- > 0) {
X (void) move(y, x);
X c = inch() & A_CHARTEXT;
X (void) addch(c);
X x++;
X }
X}
X
Xint seenerr;
X
X/* error routine for yacc (gram.y) */
Xvoid
Xyyerror(err)
Xchar *err; {
X if (seenerr) return;
X seenerr++;
X (void) move(1,0);
X (void) clrtoeol();
X (void) printw("%s: %.*s<=%s",err,linelim,line,line+linelim);
X}
X
X#ifdef XENIX2_3
Xstruct termio tmio;
X#endif
X
Xvoid
Xstartdisp()
X{
X#ifdef XENIX2_3
X (void) ioctl (fileno (stdin), TCGETA, & tmio);
X#endif
X (void) initscr();
X (void) clear();
X#ifdef VMS
X VMS_read_raw = 1;
X#else
X nonl();
X noecho ();
X cbreak();
X#endif
X initkbd();
X scrollok(stdscr, 1);
X
X#ifndef IDLOKBAD
X# ifdef SYSV3
X /*
X * turn hardware insert/delete on, if possible.
X * turn on scrolling for systems with SYSVr3.{1,2} (SYSVr3.0 has this set
X * as the default)
X */
X idlok(stdscr,TRUE);
X# endif
X#else /*
X * This seems to fix (with an empty spreadsheet):
X * a) Redrawing the bottom half of the screen when you
X * move between row 9 <-> 10
X * b) the highlighted row labels being trash when you
X * move between row 9 <-> 10
X * c) On an xterm on Esix Rev. D+ from eating lines
X * -goto (or move) a few lines (or more) past the bottom
X * of the screen, goto (or move) to the top line on the
X * screen, move upward and the current line is deleted, the
X * others move up even when they should not, check by
X * noticing the rows become 2, 3, 40, 41, 42... (etc).
X */
X idlok(stdscr,FALSE);
X#endif
X
X FullUpdate++;
X}
X
Xvoid
Xstopdisp()
X{
X deraw();
X resetkbd();
X endwin();
X#ifdef XENIX2_3
X (void) ioctl (fileno (stdin), TCSETAW, & tmio);
X#endif
X}
X
X/* init curses */
X#ifdef VMS
X
Xgoraw()
X{
X VMS_read_raw = 1;
X FullUpdate++;
X}
X
Xderaw()
X{
X (void) move (LINES - 1, 0);
X (void) clrtoeol();
X (void) refresh();
X VMS_read_raw = 0;
X}
X
X#else /* VMS */
Xvoid
Xgoraw()
X{
X#if SYSV2 || SYSV3
X fixterm();
X#else /* SYSV2 || SYSV3 */
X cbreak();
X nonl();
X noecho ();
X#endif /* SYSV2 || SYSV3 */
X kbd_again();
X (void) clear();
X FullUpdate++;
X}
X
X/* clean up curses */
Xvoid
Xderaw()
X{
X (void) move (LINES - 1, 0);
X (void) clrtoeol();
X (void) refresh();
X#if SYSV2 || SYSV3
X resetterm();
X#else
X nocbreak();
X nl();
X echo();
X#endif
X resetkbd();
X}
X
X#endif /* VMS */
END_OF_FILE
if test 13867 -ne `wc -c <'screen.c'`; then
echo shar: \"'screen.c'\" unpacked with wrong size!
fi
# end of 'screen.c'
fi
echo shar: End of archive 5 \(of 7\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 7 archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list