buhrt@cs.indiana.edu (Jeff Buhrt) (06/06/91)
Submitted-by: Jeff Buhrt <prslnk!buhrt@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@uunet.uu.net if you want that tool. # Contents: CHANGES format.c psc.c screen.c # Wrapped by kent@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",@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@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@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@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@uunet.uu.net.