home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume35 / ss / part08 < prev    next >
Encoding:
Text File  |  1993-03-02  |  60.4 KB  |  2,535 lines

  1. Newsgroups: comp.sources.misc
  2. From: art@cs.ualberta.ca (Art Mulder)
  3. Subject: v35i094:  ss - Simple Spreadsheet program, v1.2b, Part08/11
  4. Message-ID: <1993Feb22.153118.21839@sparky.imd.sterling.com>
  5. X-Md4-Signature: eff1aec054304508edbe1afab14f84f1
  6. Date: Mon, 22 Feb 1993 15:31:18 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: art@cs.ualberta.ca (Art Mulder)
  10. Posting-number: Volume 35, Issue 94
  11. Archive-name: ss/part08
  12. Environment: curses, sunos, sysv, ultrix, sgi, dec, mips, sun
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  ss_12b/format.c ss_12b/menu_edit.c ss_12b/menu_file.c
  19. #   ss_12b/sc_stuff/vi.c ss_12b/ss.c
  20. # Wrapped by kent@sparky on Sat Feb 20 16:01:04 1993
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 8 (of 11)."'
  24. if test -f 'ss_12b/format.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'ss_12b/format.c'\"
  26. else
  27.   echo shar: Extracting \"'ss_12b/format.c'\" \(15050 characters\)
  28.   sed "s/^X//" >'ss_12b/format.c' <<'END_OF_FILE'
  29. X/*****************************************************************************
  30. X *
  31. X * Mark Nagel <nagel@ics.uci.edu>
  32. X * 20 July 1989
  33. X *
  34. X * $Revision: 6.21 $
  35. X *
  36. X * bool
  37. X * format(fmt, num, buf, buflen)
  38. X *  char *fmt;
  39. X *  double num;
  40. X *  char buf[];
  41. X *  int buflen;
  42. X *
  43. X * The format function will produce a string representation of a number
  44. X * given a _format_ (described below) and a double value.  The result is
  45. X * written into the passed buffer -- if the resulting string is too
  46. X * long to fit into the passed buffer, the function returns false.
  47. X * Otherwise the function returns true.
  48. X *
  49. X * The fmt parameter contains the format to use to convert the number.
  50. X *
  51. X *  #    Digit placeholder.  If the number has fewer digits on either
  52. X *      side of the decimal point than  there are '#' characters in
  53. X *      the format, the extra '#' characters are ignored.  The number
  54. X *      is rounded to the number of digit placeholders as there are
  55. X *      to the right of the decimal point.  If there are more digits
  56. X *      in the number than there are digit placeholders on the left
  57. X *      side of the decimal point, then those digits are displayed.
  58. X *
  59. X *  0    Digit placeholder.  Same as for '#' except that the number
  60. X *      is padded with zeroes on either side of the decimal point.
  61. X *      The number of zeroes used in padding is determined by the
  62. X *      number of digit placeholders after the '0' for digits on
  63. X *      the left side of the decimal point and by the number of
  64. X *      digit placeholders before the '0' for digits on the right
  65. X *      side of the decimal point.
  66. X *
  67. X *  .    Decimal point.  Determines how many digits are placed on
  68. X *      the right and left sides of the decimal point in the number.
  69. X *      Note that numbers smaller than 1 will begin with a decimal
  70. X *      point if the left side of the decimal point contains only
  71. X *      a '#' digit placeholder.  Use a '0' placeholder to get a
  72. X *      leading zero in decimal formats.
  73. X *
  74. X *  %    Percentage.  For each '%' character in the format, the actual
  75. X *      number gets multiplied by 100 (only for purposes of formatting
  76. X *      -- the original number is left unmodified) and the '%' character
  77. X *      is placed in the same position as it is in the format.
  78. X *
  79. X *  ,    Thousands separator.  The presence of a ',' in the format
  80. X *      (multiple commas are treated as one) will cause the number
  81. X *      to be formatted with a ',' separating each set of three digits
  82. X *      in the integer part of the number with numbering beginning
  83. X *      from the right end of the integer.
  84. X *
  85. X *  \    Quote.  This character causes the next character to be
  86. X *      inserted into the formatted string directly with no
  87. X *      special interpretation.
  88. X *
  89. X *  E- E+ e- e+
  90. X *    Scientific format.  Causes the number to formatted in scientific
  91. X *    notation.  The case of the 'E' or 'e' given is preserved.  If
  92. X *      the format uses a '+', then the sign is always given for the
  93. X *    exponent value.  If the format uses a '-', then the sign is
  94. X *    only given when the exponent value is negative.  Note that if
  95. X *    there is no digit placeholder following the '+' or '-', then
  96. X *    that part of the formatted number is left out.  In general,
  97. X *    there should be one or more digit placeholders after the '+'
  98. X *    or '-'.
  99. X *
  100. X *  ;    Format selector.  Use this character to separate the format
  101. X *    into two distinct formats.  The format to the left of the
  102. X *    ';' character will be used if the number given is zero or
  103. X *    positive.  The format to the right of the ';' character is
  104. X *      used if the number given is negative.
  105. X *    
  106. X *  Any
  107. X *    Self insert.  Any other character will be inserted directly
  108. X *    into the formatted number with no change made to the actual
  109. X *      number.
  110. X *
  111. X *****************************************************************************/
  112. X
  113. X#ifndef lint
  114. X  static char Sccsid[] = "%W% %G%";
  115. X#endif
  116. X
  117. X/*****************************************************************************/
  118. X
  119. X#include <stdio.h>
  120. X#include <sys/types.h>
  121. X#include <time.h>
  122. X#include "ss.h"
  123. X
  124. X#define bool    int
  125. X#define true    1
  126. X#define false    0
  127. X#define EOS    '\0'
  128. X#define MAXBUF    256
  129. X
  130. Xextern char
  131. X  *strcpy(),
  132. X  *strcat();
  133. X
  134. Xstatic char
  135. X  *fmt_int(),
  136. X  *fmt_frac(),
  137. X  *fmt_exp();
  138. X
  139. Xstatic void
  140. X  reverse();
  141. X
  142. X/*****************************************************************************/
  143. X
  144. Xbool
  145. Xformat(fmt, val, buf, buflen)
  146. X  char *fmt;
  147. X  double val;
  148. X  char *buf;
  149. X  int buflen;
  150. X{
  151. X  register char *cp;
  152. X  char *tmp, *tp;
  153. X  bool comma = false, negative = false;
  154. X  char *integer = NULL, *decimal = NULL;
  155. X  char *exponent = NULL;
  156. X  int exp_val, width;
  157. X  char prtfmt[32];
  158. X  static char        *mantissa = NULL;
  159. X  static char        *tmpfmt1 = NULL, *tmpfmt2 = NULL, *exptmp = NULL;
  160. X  static unsigned    mantlen = 0, fmtlen = 0;
  161. X  char *fraction = NULL;
  162. X  int zero_pad = 0;
  163. X
  164. X  if (fmt == NULL)
  165. X    return(true);
  166. X
  167. X  if (strlen(fmt) + 1 > fmtlen)
  168. X  {    fmtlen = strlen(fmt) + 40;
  169. X    tmpfmt1 = Realloc(tmpfmt1, fmtlen);
  170. X    tmpfmt2 = Realloc(tmpfmt2, fmtlen);
  171. X    exptmp = Realloc(exptmp, fmtlen);
  172. X  }
  173. X  fmt = strcpy(tmpfmt1, fmt);
  174. X  if (buflen + 1 > mantlen)
  175. X  {    mantlen = buflen + 40;
  176. X    mantissa = Realloc(mantissa, mantlen);
  177. X  }
  178. X
  179. X  /*
  180. X   * select positive or negative format if necessary
  181. X   */
  182. X  for (cp = fmt; *cp != ';' && *cp != EOS; cp++)
  183. X  {
  184. X    if (*cp == '\\')
  185. X      cp++;
  186. X  }
  187. X  if (*cp == ';')
  188. X  {
  189. X    if (val < 0.0)
  190. X    {
  191. X      val = -val;     /* format should provide sign if desired */
  192. X      fmt = cp + 1;
  193. X    }
  194. X    else
  195. X    {
  196. X      *cp = EOS;
  197. X    }
  198. X  }
  199. X  
  200. X  /*
  201. X   * extract other information from format and produce a
  202. X   * format string stored in tmpfmt2 also Malloc()'d above
  203. X   */
  204. X  tmp = tmpfmt2;
  205. X  for (cp = fmt, tp = tmp; *cp != EOS; cp++)
  206. X  {
  207. X    switch (*cp)
  208. X    {
  209. X      case '\\':
  210. X        *tp++ = *cp++;
  211. X        *tp++ = *cp;
  212. X    break;
  213. X
  214. X      case ',':
  215. X        comma = true;
  216. X    break;
  217. X
  218. X      case '.':
  219. X        if (decimal == NULL)
  220. X      decimal = tp;
  221. X    *tp++ = *cp;
  222. X    break;
  223. X    
  224. X      case '%':
  225. X        val *= 100.0;
  226. X    *tp++ = *cp;
  227. X    break;
  228. X    
  229. X      default:
  230. X        *tp++ = *cp;
  231. X    break;
  232. X    }
  233. X  }
  234. X  *tp = EOS;
  235. X  fmt = tmpfmt2;
  236. X
  237. X  if (val < 0.0)
  238. X  {    negative = true;
  239. X    val = -val;
  240. X  }
  241. X  /*
  242. X   * extract the exponent from the format if present
  243. X   */
  244. X  for (cp = fmt; *cp != EOS; cp++)
  245. X  { if (*cp == '\\')
  246. X    {
  247. X      cp++;
  248. X    }
  249. X    else if (*cp == 'e' || *cp == 'E')
  250. X    {
  251. X      if (cp[1] == '+' || cp[1] == '-')
  252. X      {
  253. X    exponent = strcpy(exptmp, cp);
  254. X    *cp = EOS;
  255. X    exp_val = 0;
  256. X    if (val!=0.0) {
  257. X      while (val < 1.0)
  258. X      {
  259. X        val *= 10.0;
  260. X        exp_val--;
  261. X      }
  262. X      while (val >= 10.0)
  263. X      {
  264. X        val /= 10.0;
  265. X        exp_val++;
  266. X      }
  267. X    }
  268. X    break;
  269. X      }
  270. X    }
  271. X  }
  272. X
  273. X  /*
  274. X   * determine maximum decimal places and use sprintf
  275. X   * to build initial character form of formatted value.
  276. X   */
  277. X  width = 0;
  278. X  if (decimal)
  279. X  {
  280. X    *decimal++ = EOS;
  281. X    for (cp = decimal; *cp != EOS; cp++)
  282. X    {
  283. X      switch (*cp)
  284. X      {
  285. X        case '\\':
  286. X          cp++;
  287. X      break;
  288. X
  289. X        case '#':
  290. X          width++;
  291. X      break;
  292. X
  293. X    case '0':
  294. X      zero_pad = ++width;
  295. X      break;
  296. X      }
  297. X    }
  298. X    zero_pad = strlen(decimal) - zero_pad;
  299. X  }
  300. X  (void) sprintf(prtfmt, "%%.%dlf", width);
  301. X  (void) sprintf(mantissa, prtfmt, val);
  302. X  for (cp = integer = mantissa; *cp != '.' && *cp != EOS; cp++)
  303. X  {
  304. X    if (*integer == '0')
  305. X      integer++;
  306. X  }
  307. X  if (*cp == '.')
  308. X  {
  309. X    fraction = cp + 1;
  310. X    *cp = EOS;
  311. X    cp = fraction + strlen(fraction) - 1;
  312. X    for (; zero_pad > 0; zero_pad--, cp--)
  313. X    {
  314. X      if (*cp == '0')
  315. X        *cp = EOS;
  316. X    }
  317. X  }
  318. X
  319. X  /*
  320. X   * format the puppy
  321. X   */
  322. X  {
  323. X    static    char *citmp = NULL, *cftmp = NULL;
  324. X    static    unsigned cilen = 0, cflen = 0;
  325. X    char *ci, *cf, *ce;
  326. X    int len_ci, len_cf, len_ce;
  327. X    bool ret = false;
  328. X    
  329. X    ci = fmt_int(integer, fmt, comma, negative);
  330. X    len_ci = strlen(ci);
  331. X    if (len_ci >= cilen)
  332. X    {    cilen = len_ci + 40;
  333. X    citmp = Realloc(citmp, cilen);
  334. X    }
  335. X    ci = strcpy(citmp, ci);
  336. X
  337. X    cf = (fraction) ? fmt_frac(fraction, decimal) : "";
  338. X    len_cf = strlen(cf);
  339. X    if (len_cf >= cflen)
  340. X    {    cflen = len_cf + 40;
  341. X    cftmp = Realloc(cftmp, cilen);
  342. X    }
  343. X    cf = strcpy(cftmp, cf);
  344. X
  345. X    ce = (exponent) ? fmt_exp(exp_val, exponent) : "";
  346. X    len_ce = strlen(ce);
  347. X/*
  348. X * Skip copy assuming sprintf doesn't call our format functions
  349. X *   ce = strcpy(Malloc((unsigned)((len_ce = strlen(ce)) + 1)), ce);
  350. X */
  351. X    if (len_ci + len_cf + len_ce < buflen)
  352. X    {
  353. X      (void) sprintf(buf, "%s%s%s", ci, cf, ce);
  354. X      ret = true;
  355. X    }
  356. X
  357. X    return (ret);
  358. X  }
  359. X}
  360. X
  361. X/*****************************************************************************/
  362. X
  363. Xstatic char *
  364. Xfmt_int(val, fmt, comma, negative)
  365. X  char *val;        /* integer part of the value to be formatted */
  366. X  char *fmt;        /* integer part of the format */
  367. X  bool comma;        /* true if we should comma-ify the value */
  368. X  bool negative;    /* true if the value is actually negative */
  369. X{
  370. X  int digit, f, v;
  371. X  int thousands = 0;
  372. X  char *cp;
  373. X  static char buf[MAXBUF];
  374. X  char *bufptr = buf;
  375. X
  376. X  /*
  377. X   * locate the leftmost digit placeholder
  378. X   */
  379. X  for (cp = fmt; *cp != EOS; cp++)
  380. X  {
  381. X    if (*cp == '\\')
  382. X      cp++;
  383. X    else if (*cp == '#' || *cp == '0')
  384. X      break;
  385. X  }
  386. X  digit = (*cp == EOS) ? -1 : cp - fmt;
  387. X
  388. X  /*
  389. X   * format the value
  390. X   */
  391. X  f = strlen(fmt) - 1;
  392. X  v = (digit >= 0) ? strlen(val) - 1 : -1;
  393. X  while (f >= 0 || v >= 0)
  394. X  {
  395. X    if (f > 0 && fmt[f-1] == '\\')
  396. X    {
  397. X      *bufptr++ = fmt[f--];
  398. X    }
  399. X    else if (f >= 0 && (fmt[f] == '#' || fmt[f] == '0'))
  400. X    {
  401. X      if (v >= 0 || fmt[f] == '0')
  402. X      {
  403. X        *bufptr++ = v < 0 ? '0' : val[v];
  404. X    if (comma && (thousands = (thousands + 1) % 3) == 0 && v > 0)
  405. X    {
  406. X      *bufptr++ = ',';
  407. X    }
  408. X    v--;
  409. X      }
  410. X    }
  411. X    else if (f >= 0)
  412. X    {
  413. X      *bufptr++ = fmt[f];
  414. X    }
  415. X    if (v >= 0 && f == digit)
  416. X    {
  417. X      continue;
  418. X    }
  419. X    f--;
  420. X  }
  421. X    
  422. X  if (negative && digit >= 0)
  423. X    *bufptr++ = '-';
  424. X  *bufptr = EOS;
  425. X  reverse(buf);
  426. X
  427. X  return (buf);
  428. X}
  429. X
  430. X/*****************************************************************************/
  431. X
  432. Xstatic char *
  433. Xfmt_frac(val, fmt)
  434. X  char *val;        /* fractional part of the value to be formatted */
  435. X  char *fmt;        /* fractional portion of format */
  436. X{
  437. X  static char buf[MAXBUF];
  438. X  register char *bufptr = buf;
  439. X  register char *fmtptr = fmt, *valptr = val;
  440. X
  441. X  *bufptr++ = '.';
  442. X  while (*fmtptr != EOS)
  443. X  {
  444. X    if (*fmtptr == '\\')
  445. X    {
  446. X      *bufptr++ = *++fmtptr;
  447. X    }
  448. X    else if (*fmtptr == '#' || *fmtptr == '0')
  449. X    {
  450. X      if (*valptr != EOS || *fmtptr == '0')
  451. X      {
  452. X        *bufptr++ = (*valptr != EOS) ? *valptr++ : *fmtptr;
  453. X      }
  454. X    }
  455. X    else
  456. X    {
  457. X      *bufptr++ = *fmtptr;
  458. X    }
  459. X    fmtptr++;
  460. X  }
  461. X  *bufptr = EOS;
  462. X
  463. X  return (buf);
  464. X}
  465. X
  466. X/*****************************************************************************/
  467. X
  468. Xstatic char *
  469. Xfmt_exp(val, fmt)
  470. X  int val;        /* value of the exponent */
  471. X  char *fmt;        /* exponent part of the format */
  472. X{
  473. X  static char buf[MAXBUF];
  474. X  register char *bufptr = buf;
  475. X  char valbuf[64];
  476. X  bool negative = false;
  477. X  
  478. X  *bufptr++ = *fmt++;
  479. X  if (*fmt == '+')
  480. X    *bufptr++ = (val < 0) ? '-' : '+';
  481. X  else if (val < 0)
  482. X    *bufptr++ = '-';
  483. X  fmt++;
  484. X  *bufptr = EOS;
  485. X
  486. X  if (val < 0)
  487. X  {
  488. X    val = -val;
  489. X    negative = false;
  490. X  }
  491. X  (void) sprintf(valbuf, "%d", val);
  492. X  
  493. X  (void) strcat(buf, fmt_int(valbuf, fmt, false, negative));
  494. X  return (buf);
  495. X}
  496. X
  497. X/*****************************************************************************/
  498. X
  499. Xstatic void
  500. Xreverse(buf)
  501. X  register char *buf;
  502. X{
  503. X  register char *cp = buf + strlen(buf) - 1;
  504. X  register char tmp;
  505. X
  506. X  while (buf < cp)
  507. X  {
  508. X    tmp = *cp;
  509. X    *cp-- = *buf;
  510. X    *buf++ = tmp;
  511. X  }
  512. X}
  513. X
  514. X/*****************************************************************************/
  515. X/*  
  516. X * Tom Anderson    <toma@hpsad.hp.com>
  517. X * 10/14/90
  518. X *
  519. X * This routine takes a value and formats it using fixed, scientific,
  520. X * or engineering notation.  The format command 'f' determines which
  521. X * format is used.  The formats are:         example
  522. X *    0:   Fixed point (default)             0.00010
  523. X *    1:   Scientific                        1.00E-04
  524. X *    2:   Engineering                       100.00u
  525. X *
  526. X * The format command 'f' now uses three values.  The first two are the
  527. X * width and precision, and the last one is the format value 0, 1, or 2 as
  528. X * described above.  The format value is passed in the variable fmt.
  529. X *
  530. X * This formatted value is written into the passed buffer.  if the
  531. X * resulting string is too long to fit into the passed buffer, the
  532. X * function returns false.  Otherwise the function returns true.
  533. X *
  534. X * When a number is formatted as engineering and is outside of the range
  535. X * of typically used engineering exponents, the format reverts to
  536. X * scientific.
  537. X *
  538. X * To preserve compatability with old spreadsheet files, the third value
  539. X * may be missing, and the default will be fixed point (format 0).
  540. X *
  541. X * When an old style sheet is saved, the third value will be stored.
  542. X *
  543. X */
  544. X
  545. X/* defined in sc.h */
  546. X#ifndef REFMTFIX
  547. X#define REFMTFIX    0
  548. X#define REFMTFLT    1
  549. X#define REFMTENG    2
  550. X#define REFMTDATE    3
  551. X#endif
  552. X
  553. Xchar engmult[] = "afpnum kMGT";
  554. X
  555. Xbool
  556. Xengformat(fmt, width, lprecision, val, buf, buflen)
  557. Xint fmt; 
  558. Xint width; 
  559. Xint lprecision;
  560. Xdouble val;
  561. Xchar *buf;
  562. Xint buflen;
  563. X{
  564. X  int engind = 0;
  565. X  double engmant, pow(), engabs, engexp;
  566. X  if (buflen < width) return (false);
  567. X  if (fmt == REFMTFIX)
  568. X  (void) sprintf(buf,"%*.*f", width, lprecision, val);
  569. X  if (fmt == REFMTFLT)
  570. X  (void) sprintf(buf,"%*.*E", width, lprecision, val);
  571. X  if (fmt == REFMTENG)
  572. X  {
  573. X    if (val == 0e0)    /* Hack to get zeroes to line up in engr fmt */
  574. X    {
  575. X      (void) sprintf((buf-1),"%*.*f ", width, lprecision, val);
  576. X    }
  577. X    else
  578. X    {
  579. X      engabs=(val);
  580. X      if (engabs < 0e0) engabs= -engabs;
  581. X      if ((engabs >= 1e-18) && (engabs < 1e-15 )) engind=0;
  582. X      if ((engabs >= 1e-15) && (engabs < 1e-12 )) engind=1;
  583. X      if ((engabs >= 1e-12) && (engabs < 1e-9 )) engind=2;
  584. X      if ((engabs >= 1e-9) && (engabs < 1e-6 )) engind=3;
  585. X      if ((engabs >= 1e-6) && (engabs < 1e-3 )) engind=4;
  586. X      if ((engabs >= 1e-3) && (engabs < 1 )) engind=5;
  587. X      if ((engabs >= 1) && (engabs < 1e3 )) engind=6;
  588. X      if ((engabs >= 1e3) && (engabs < 1e6 )) engind=7;
  589. X      if ((engabs >= 1e6) && (engabs < 1e9 )) engind=8;
  590. X      if ((engabs >= 1e9) && (engabs < 1e12 )) engind=9;
  591. X      if ((engabs >= 1e12) && (engabs < 1e15 )) engind=10;
  592. X      if ((engabs <1e-18) || (engabs >=1e15))
  593. X      {
  594. X      /* Revert to floating point */
  595. X        (void) sprintf(buf,"%*.*E", width, lprecision, val);
  596. X      }
  597. X      else
  598. X      {
  599. X        engexp= (double) (engind-6)*3;
  600. X        engmant= val/pow(10.0e0,engexp);
  601. X        (void) sprintf(buf,"%*.*f%c", width-1,
  602. X                      lprecision, engmant, engmult[engind]);
  603. X      }
  604. X    }
  605. X  }
  606. X  if (fmt == REFMTDATE) {
  607. X    int i;
  608. X    char *time;
  609. X    long int secs;
  610. X
  611. X    if (buflen < 9) {
  612. X      for (i = 0; i < width; i++) buf[i] = '*';
  613. X      buf[i] = '\0';
  614. X    }
  615. X    else {
  616. X      secs = (time_t)val;
  617. X      time = ctime(&secs);
  618. X      buf[0] = time[8];
  619. X      buf[1] = time[9];
  620. X      buf[2] = ' ';
  621. X      buf[3] = time[4];
  622. X      buf[4] = time[5];
  623. X      buf[5] = time[6];
  624. X      buf[6] = ' ';
  625. X      buf[7] = time[22];
  626. X      buf[8] = time[23];
  627. X      for (i = 9; i < width; i++) buf[i] = ' ';
  628. X      buf[i] = '\0';
  629. X    }
  630. X  }
  631. X  return (true);
  632. X}
  633. END_OF_FILE
  634.   if test 15050 -ne `wc -c <'ss_12b/format.c'`; then
  635.     echo shar: \"'ss_12b/format.c'\" unpacked with wrong size!
  636.   fi
  637.   # end of 'ss_12b/format.c'
  638. fi
  639. if test -f 'ss_12b/menu_edit.c' -a "${1}" != "-c" ; then 
  640.   echo shar: Will not clobber existing file \"'ss_12b/menu_edit.c'\"
  641. else
  642.   echo shar: Extracting \"'ss_12b/menu_edit.c'\" \(7158 characters\)
  643.   sed "s/^X//" >'ss_12b/menu_edit.c' <<'END_OF_FILE'
  644. X/**********************************************************************
  645. X* %M%
  646. X* Art Mulder ( art@cs.ualberta.ca )
  647. X* University of Alberta, Department of Computing Science.
  648. X***********************************************************************
  649. X* Edit Menu Operations
  650. X***********************************************************************
  651. X**********************************************************************/
  652. X#ifndef lint
  653. X  static char Sccsid[] = "%W% %G%";
  654. X#endif
  655. X
  656. X/*
  657. X * Include files
  658. X */
  659. X#include <stdio.h>
  660. X#include <string.h>
  661. X#include "curses_stuff.h"
  662. X
  663. X#include "ss.h"
  664. X#include "getinput.h"
  665. X#include "disprange.h"
  666. X#include "menu_edit.h"
  667. X
  668. X/*    Internal Macros & Data Structures
  669. X *----------------------------------------------------------------------
  670. X */
  671. X
  672. X/*    External Global variables
  673. X *----------------------------------------------------------------------
  674. X */
  675. X
  676. X
  677. X/*    Externally Accessible Functions
  678. X ***********************************************************************
  679. X */
  680. X
  681. X/*
  682. X** NOTE: How about making some sort of internal Cell Buffer.  Then
  683. X** write Cut/Copy/Paste Functions to replace the current Copy/Erase
  684. X** functions.  FUTURE WORK, for now live with the kludge.
  685. X*/
  686. X
  687. Xvoid EditCopy()
  688. X/*----------------------------------------------------------------------
  689. X** Copy a range of cells.  Copy the current cell, if no range is
  690. X** currently defined.  Prompt the user to Enter a Destination Range.
  691. X*/
  692. X{
  693. X    static char saverange[10];        /* To save the first range */
  694. X    /* need to make special arrangements, because we are handling
  695. X     * more than one range.
  696. X     */
  697. X
  698. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  699. X
  700. X    
  701. X    /*
  702. X     * Prompt the user to enter a destination range
  703. X     */
  704. X    if (range[0] == NULL) {    /* Null range */
  705. X    static char *curcell;        /* to hold current cell */
  706. X    curcell = v_name(currow, curcol); /* Get current cell */
  707. X    Sprintf(saverange, "%s:%s", curcell, curcell);
  708. X         /* record the current cell as the starting range */
  709. X    
  710. X
  711. X    Sprintf(message, "** Copy the Current Cell to... (Enter a range)" );
  712. X
  713. X    } else {
  714. X    Sprintf(message, "** Copy the Cell Range %s to... (Enter a range)",
  715. X        range);
  716. X    strcpy(saverange, range); /* Save the starting range */
  717. X    }
  718. X    
  719. X    Message(message);
  720. X
  721. X/*
  722. X * BUG: No way out of this operation!  MUST enter a range
  723. X * and the copy WILL take place.
  724. X */
  725. X      
  726. X    range = RangeForceInput();    /* Get Destination range */
  727. X    if (range[0] == NULL)     /* Null range */
  728. X    range = r_name(currow, curcol, currow, curcol);
  729. X
  730. X    ClearMessage; 
  731. X    Sprintf(line,"copy [dest_range src_range] %s %s", range, saverange);
  732. X    PROCESS_line;
  733. X
  734. X} /* EditCopy() */
  735. X
  736. Xvoid EditErase()
  737. X/*----------------------------------------------------------------------
  738. X** Erase a range of cells.  Erase the current cell, if no range is
  739. X** currently defined.  DANGEROUS OPERATION: Prompt for confirmation.
  740. X*/
  741. X{
  742. X    range = RangeGet();         /* Get range, if any, "" otherwise. */
  743. X
  744. X    if (range[0] == NULL)       /* Null range */
  745. X        Sprintf(message, "** Erase the Current Cell?" );
  746. X    else
  747. X        Sprintf(message, "** Erase the Cell Range %s ?", range);
  748. X
  749. X    if (yn_ask(message) == 1) {
  750. X    Sprintf(line,"erase [range] %s", range);
  751. X    PROCESS_line;
  752. X    }
  753. X
  754. X} /* EditErase(); */
  755. X
  756. Xvoid EditLock()
  757. X/*----------------------------------------------------------------------
  758. X** Lock a range of cells.  Lock the current cell, if no range is
  759. X** currently defined.
  760. X*/
  761. X{
  762. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  763. X
  764. X    if (range[0] == NULL)    /* Null range */
  765. X    Sprintf(message, "** Lock the Current Cell?" );
  766. X    else
  767. X    Sprintf(message, "** Lock the Cell Range %s ?", range);
  768. X
  769. X    if (yn_ask(message) == 1) {
  770. X    Sprintf(line,"lock [range] %s", range);
  771. X    Message("** Locked");
  772. X    PROCESS_line;
  773. X    
  774. X    }
  775. X} /* EditLock(); */
  776. X
  777. Xvoid EditUnLock()
  778. X/*----------------------------------------------------------------------
  779. X** UnLock a range of cells.  UnLock the current cell, if no range is
  780. X** currently defined.
  781. X*/
  782. X{
  783. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  784. X
  785. X    Sprintf(line,"unlock [range] %s", range);
  786. X    PROCESS_line;
  787. X
  788. X} /* EditUnLock(); */
  789. X
  790. Xvoid EditFormat()
  791. X/*----------------------------------------------------------------------
  792. X** Format a range of cells.  Format the current cell, if no range is
  793. X** currently defined.
  794. X*/
  795. X{
  796. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  797. X
  798. X    /*
  799. X     * No Range is Defined, Format the current Cell
  800. X     */
  801. X    if (range[0] == NULL) {
  802. X        register struct ent *p = *ATBL(tbl, currow, curcol);
  803. X    static char *curcell;        /* for displaying current cell */
  804. X
  805. X    curcell = v_name(currow, curcol); /* Get current cell */
  806. X    
  807. X        /*
  808. X         * If the cell already has a Format, Display it for editing,
  809. X         * otherwise get into insert mode and read in a new format.
  810. X         */
  811. X        if (p && p->format) {    /* There IS an existing format  */
  812. X        Sprintf(message,
  813. X            "** Enter format for cell %s (Edit existing format)",
  814. X            curcell);
  815. X        Message(message);
  816. X        buff = gi_editline( p->format );
  817. X
  818. X        } else {        /* There IS NOT an existing format */
  819. X        Sprintf(message, "** Enter format for cell %s", curcell);
  820. X        Message(message);
  821. X        buff = gi_line();
  822. X    }
  823. X    Sprintf(line, "fmt [format] %s \"%s\"", curcell, buff);
  824. X
  825. X    /*
  826. X     * Else, there is a range defined, format the range.
  827. X     */
  828. X    } else {
  829. X    Sprintf(message, "** Enter format for the cell range %s", range);
  830. X    Message(message);
  831. X    buff = gi_line();
  832. X    Sprintf(line, "fmt [range \"format\"] %s \"%s\" ", range, buff);
  833. X    }
  834. X    ABORT_AND_RETURN_IF_BUFF_NULL;
  835. X    ClearMessage;    
  836. X    PROCESS_line;
  837. X
  838. X} /* EditFormat(); */
  839. X
  840. Xvoid EditFill()
  841. X/*----------------------------------------------------------------------
  842. X** Fill a range of cells.  DANGEROUS OPERATION: Prompt for confirmation.
  843. X*/
  844. X{
  845. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  846. X
  847. X    if (range[0] == NULL) {    /* Null range */
  848. X    Message("** No Range Defined, Fill aborted");
  849. X    return;
  850. X    }
  851. X    
  852. X    Message("** Fill %s.  Enter Starting Value & Increment (eg: \"5 2\")",
  853. X        range);
  854. X    buff = gi_line();
  855. X    ABORT_AND_RETURN_IF_BUFF_NULL;
  856. X    
  857. X    ClearMessage;
  858. X
  859. X    Sprintf(message, "** Fill the range %s ? (starting val., incr. = %s)",
  860. X        range, buff);
  861. X    if (yn_ask(message) == 1) {
  862. X    Sprintf(line,"fill [range start inc] %s %s", range, buff);
  863. X    PROCESS_line;
  864. X    }
  865. X} /* EditFill(); */
  866. X
  867. Xvoid EditValueize()
  868. X/*----------------------------------------------------------------------
  869. X** "Valueize" a range of cells.  Valueize means to convert all formulas
  870. X** to just plain numbers.  Valueize the current cell, if no range is
  871. X** currently defined.  DANGEROUS OPERATION: Prompt for confirmation.
  872. X*/
  873. X{
  874. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  875. X
  876. X    if (range[0] == NULL)    /* Null range */
  877. X    Sprintf(message, "** Valueize the Current Cell?" );
  878. X    else
  879. X    Sprintf(message, "** Valueize the Cell Range %s ?", range);
  880. X
  881. X    if (yn_ask(message) == 1) {
  882. X    Sprintf(line,"value [range] %s", range);
  883. X    PROCESS_line;
  884. X    }
  885. X
  886. X} /* EditValueize() */
  887. X
  888. X
  889. X/**********************************************************************
  890. X*       End
  891. X**********************************************************************/
  892. END_OF_FILE
  893.   if test 7158 -ne `wc -c <'ss_12b/menu_edit.c'`; then
  894.     echo shar: \"'ss_12b/menu_edit.c'\" unpacked with wrong size!
  895.   fi
  896.   # end of 'ss_12b/menu_edit.c'
  897. fi
  898. if test -f 'ss_12b/menu_file.c' -a "${1}" != "-c" ; then 
  899.   echo shar: Will not clobber existing file \"'ss_12b/menu_file.c'\"
  900. else
  901.   echo shar: Extracting \"'ss_12b/menu_file.c'\" \(4858 characters\)
  902.   sed "s/^X//" >'ss_12b/menu_file.c' <<'END_OF_FILE'
  903. X/**********************************************************************
  904. X* %M%
  905. X* Art Mulder ( art@cs.ualberta.ca )
  906. X* University of Alberta, Department of Computing Science.
  907. X***********************************************************************
  908. X* File Menu Operations
  909. X***********************************************************************
  910. X**********************************************************************/
  911. X#ifndef lint
  912. X  static char Sccsid[] = "%W% %G%";
  913. X#endif
  914. X
  915. X/*
  916. X * Include files
  917. X */
  918. X#include <stdio.h>
  919. X#include <string.h>
  920. X#include "curses_stuff.h"
  921. X
  922. X#include "ss.h"
  923. X#include "getinput.h"
  924. X#include "disprange.h"
  925. X#include "menu_file.h"
  926. X
  927. X/*    Internal Macros & Data Structures
  928. X *----------------------------------------------------------------------
  929. X */
  930. X
  931. X/*    External Global variables
  932. X *----------------------------------------------------------------------
  933. X */
  934. Xextern int running;        /* from main() */
  935. X
  936. X
  937. X/*    Externally Accessible Functions
  938. X ***********************************************************************
  939. X */
  940. X
  941. Xvoid FileLoad()
  942. X/*----------------------------------------------------------------------
  943. X** Load a spreadsheet into memory.
  944. X** -> NOTE: this overwrites the current spreadsheet in memory.
  945. X*/
  946. X{
  947. X    if (*curfile)
  948. X    Sprintf(message, "** Enter name of file to load (Default: \"%s\")",
  949. X        curfile);
  950. X    else
  951. X    Sprintf(message, "** Enter name of file to load");
  952. X
  953. X    Message(message);
  954. X    buff = gi_line();
  955. X    ABORT_AND_RETURN_IF_BUFF_NULL;
  956. X    
  957. X    Sprintf (line, "get [\"source\"] \"%s\"", buff);
  958. X    ClearMessage;
  959. X    PROCESS_line;
  960. X    
  961. X} /* fileLoad() */
  962. X
  963. Xvoid FileMerge()
  964. X/*----------------------------------------------------------------------
  965. X*/
  966. X{
  967. X     Sprintf(message, "** Enter name of file to merge in");
  968. X     Message(message);
  969. X     buff = gi_line();
  970. X     ABORT_AND_RETURN_IF_BUFF_NULL;
  971. X
  972. X     Sprintf (line, "merge [\"source\"] \"%s\"", buff);
  973. X     ClearMessage;
  974. X     PROCESS_line;
  975. X     
  976. X} /* FileMerge() */
  977. X
  978. Xint FileSave()
  979. X/*----------------------------------------------------------------------
  980. X** Save the complete spreadsheet to the current file
  981. X*/
  982. X{
  983. X    if (modflg && curfile[0]) {
  984. X    sprintf (line, "put [\"dest\" range] \"%s\" ", curfile);
  985. X    PROCESS_line;
  986. X
  987. X/**     if (writefile(curfile, 0, 0, maxrow, maxcol) < 0) {
  988. X    ClearPrompt;
  989. X    linelim = -1;      
  990. X    return (1);
  991. X    }
  992. X**/    
  993. X    } else if (modflg) { /* No filename yet established */
  994. X      FileSaveAs();
  995. X
  996. X    } else            /* the file is not modified */
  997. X    Message("** No changes needed to be saved");
  998. X    return(0);
  999. X} /* FileSave() */
  1000. X
  1001. X
  1002. Xvoid FileSaveAs()
  1003. X/*----------------------------------------------------------------------
  1004. X** Prompt for a filename & save to that file.  The user can also
  1005. X** optionally enter a range of  cells to be saved (default is all
  1006. X** cells.)
  1007. X*/
  1008. X{
  1009. X#ifdef __STDC__                /* ANSI C can handle this: */
  1010. X    char def_file[MAXSTR] = "";    /* default filename */
  1011. X#else                    /* Non-ANSI C can't */
  1012. X    char def_file[MAXSTR];
  1013. X    def_file[0] = '\0';
  1014. X#endif
  1015. X
  1016. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  1017. X    
  1018. X    if (*curfile)
  1019. X    Sprintf(def_file, "(Default: \"%s\")", curfile);
  1020. X
  1021. X    Sprintf(message, "** Enter filename in which to save %s %s",
  1022. X        range, def_file);
  1023. X
  1024. X    Message(message);
  1025. X    buff = gi_line();
  1026. X    ABORT_AND_RETURN_IF_BUFF_NULL;
  1027. X
  1028. X    Sprintf (line, "put [\"dest\" range] \"%s\" %s", buff, range);
  1029. X    PROCESS_line;
  1030. X
  1031. X} /* FileSaveAs() */
  1032. X
  1033. X
  1034. Xvoid FileWriteTxt()
  1035. X/*----------------------------------------------------------------------
  1036. X*/
  1037. X{
  1038. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  1039. X
  1040. X    Sprintf(message,
  1041. X        "** Write File, Text only: Enter filename in which to save %s",
  1042. X        range);
  1043. X
  1044. X    Message(message);
  1045. X    buff = gi_line();
  1046. X    ABORT_AND_RETURN_IF_BUFF_NULL;
  1047. X    
  1048. X    Sprintf (line, "write [\"dest\" range] \"%s\" %s", buff, range);
  1049. X    PROCESS_line;
  1050. X
  1051. X} /* FileWriteTxt() */
  1052. X
  1053. X
  1054. Xvoid FileTblSave(tbl_mode)
  1055. X/*----------------------------------------------------------------------
  1056. X** Save the spreadsheet in ``tbl'' mode.  Which tbl mode (tbl, tex, latex
  1057. X** slatex, framemaker) depends on the setting of the global variable
  1058. X** ``tbl_style'' which is set in the /Misc/Settings menu.
  1059. X** tbl_mode is a string representation of tbl_style.
  1060. X*/
  1061. X    char * tbl_mode;    
  1062. X{
  1063. X    range = RangeGet();        /* Get range, if any, "" otherwise. */
  1064. X
  1065. X    Sprintf(message, "** %s : Enter filename in which to save %s",
  1066. X        tbl_mode, range);
  1067. X
  1068. X    Message(message);
  1069. X    buff = gi_line();
  1070. X    ABORT_AND_RETURN_IF_BUFF_NULL;
  1071. X
  1072. X    Sprintf (line, "tbl [\"dest\" range] \"%s\" %s", buff, range);
  1073. X    PROCESS_line;
  1074. X
  1075. X} /* FileTblSave() */
  1076. X
  1077. Xvoid FileQuit()
  1078. X/*----------------------------------------------------------------------
  1079. X** Quit the program
  1080. X*/
  1081. X{
  1082. X     Message("** Quit");
  1083. X     running = 0;
  1084. X}
  1085. X
  1086. X
  1087. X/**********************************************************************
  1088. X*       End
  1089. X**********************************************************************/
  1090. END_OF_FILE
  1091.   if test 4858 -ne `wc -c <'ss_12b/menu_file.c'`; then
  1092.     echo shar: \"'ss_12b/menu_file.c'\" unpacked with wrong size!
  1093.   fi
  1094.   # end of 'ss_12b/menu_file.c'
  1095. fi
  1096. if test -f 'ss_12b/sc_stuff/vi.c' -a "${1}" != "-c" ; then 
  1097.   echo shar: Will not clobber existing file \"'ss_12b/sc_stuff/vi.c'\"
  1098. else
  1099.   echo shar: Extracting \"'ss_12b/sc_stuff/vi.c'\" \(13600 characters\)
  1100.   sed "s/^X//" >'ss_12b/sc_stuff/vi.c' <<'END_OF_FILE'
  1101. X/*    SC    A Spreadsheet Calculator
  1102. X *
  1103. X *    One line vi emulation
  1104. X *    $Revision: 6.21 $
  1105. X */
  1106. X
  1107. X#ifndef lint
  1108. X  static char Sccsid[] = "%W% %G%";
  1109. X#endif
  1110. X
  1111. X#include <sys/types.h>
  1112. X#ifdef BSD42
  1113. X#include <strings.h>
  1114. X#else
  1115. X#ifndef SYSIII
  1116. X#include <string.h>
  1117. X#endif
  1118. X#endif
  1119. X
  1120. X#include <signal.h>
  1121. X#include <curses.h>
  1122. X
  1123. Xextern    char    *strchr();
  1124. X
  1125. X#include <stdio.h>
  1126. X#include <ctype.h>
  1127. X#include "sc.h"
  1128. X
  1129. X#define istext(a) (isalnum(a) || ((a) == '_'))
  1130. X
  1131. Xstatic    void append_line();
  1132. Xstatic    void back_hist();
  1133. Xstatic    int  back_line();
  1134. Xstatic    int  back_word();
  1135. Xstatic    void back_space();
  1136. Xstatic    void change_cmd();
  1137. Xstatic    void col_0();
  1138. Xstatic    void cr_line();
  1139. Xstatic    void delete_cmd();
  1140. Xstatic    void del_chars();
  1141. Xstatic    void del_in_line();
  1142. Xstatic    void del_to_end();
  1143. Xstatic    void dotcmd();
  1144. Xstatic    int  find_char();
  1145. Xstatic    void for_hist();
  1146. Xstatic    int  for_line();
  1147. Xstatic    int  for_word();
  1148. Xstatic    void ins_in_line();
  1149. Xstatic    void last_col();
  1150. Xstatic    void rep_char();
  1151. Xstatic    void replace_in_line();
  1152. Xstatic    void replace_mode();
  1153. Xstatic    void restore_it();
  1154. Xstatic    void savedot();
  1155. Xstatic    void save_hist();
  1156. Xstatic    void search_again();
  1157. Xstatic    void search_hist();
  1158. Xstatic    void search_mode();
  1159. Xstatic    void stop_edit();
  1160. Xstatic    int  to_char();
  1161. Xstatic    void u_save();
  1162. X
  1163. Xextern int showrange;
  1164. Xextern char mode_ind;        /* Mode indicator */
  1165. X
  1166. X/* values for mode below */
  1167. X
  1168. X#define INSERT_MODE    0    /* Insert mode */
  1169. X#define EDIT_MODE       1    /* Edit mode */
  1170. X#define REP_MODE        2    /* Replace mode */
  1171. X#define SEARCH_MODE    3    /* Get arguments for '/' command */
  1172. X
  1173. X#define    DOTLEN        200
  1174. X
  1175. Xstatic int mode = INSERT_MODE;
  1176. Xstruct    hist {
  1177. X    unsigned    int    len;
  1178. X    char    *histline;
  1179. X} history[HISTLEN];
  1180. X
  1181. Xstatic int histp = -1;
  1182. Xstatic int lasthist = -1;
  1183. Xstatic int endhist = -1;
  1184. Xstatic char *last_search = NULL;
  1185. Xstatic char *undo_line = NULL;
  1186. Xstatic int undo_lim;
  1187. Xstatic char dotb[DOTLEN];
  1188. Xstatic int doti = 0;
  1189. Xstatic int do_dot = 0;
  1190. X
  1191. Xvoid
  1192. Xwrite_line(c)
  1193. Xint c;
  1194. X{
  1195. X    if (mode == EDIT_MODE) {
  1196. X    switch(c) {
  1197. X/**     case (ctl('h')):                linelim = back_line();  break; **/
  1198. X        case (ctl('h')): case DEL:      linelim = back_line();  break;
  1199. X               /** treat DEL like Backspace **/
  1200. X    case (ctl('m')):  cr_line();            break;
  1201. X    case ESC:    stop_edit();            break;
  1202. X    case '+':    for_hist();            break;
  1203. X    case '-':    back_hist();            break;
  1204. X    case '$':    last_col();            break;
  1205. X    case '.':    dotcmd();            break;
  1206. X    case '/':    search_mode();            break;
  1207. X    case '0':    col_0();            break;
  1208. X    case 'D':    u_save(c);del_to_end();        break;
  1209. X    case 'I':    u_save(c);col_0();insert_mode();break;
  1210. X    case 'R':    replace_mode();            break;
  1211. X    case 'X':    u_save(c); back_space();    break;
  1212. X    case 'a':    u_save(c); append_line();    break;
  1213. X    case 'A':    u_save(c);last_col();append_line();    break;
  1214. X    case 'b':    linelim = back_word();        break;
  1215. X    case 'c':    u_save(c); change_cmd();    break;
  1216. X    case 'd':    u_save(c); delete_cmd();    break;
  1217. X    case 'f':    linelim = find_char();        break;
  1218. X    case 'h':    linelim = back_line();        break;
  1219. X    case 'i':    u_save(c); insert_mode();    break;
  1220. X    case 'j':    for_hist();            break;
  1221. X    case 'k':    back_hist();            break;
  1222. X    case ' ':
  1223. X    case 'l':    linelim = for_line(0);        break;
  1224. X    case 'n':    search_again();            break;
  1225. X    case 'q':    stop_edit();            break;
  1226. X    case 'r':    u_save(c); rep_char();        break;
  1227. X    case 't':    linelim = to_char();        break;
  1228. X    case 'u':    restore_it();            break;
  1229. X    case 'w':    linelim = for_word(0);        break;
  1230. X    case 'x':    u_save(c); del_in_line();    break;
  1231. X    default:    break;
  1232. X    }
  1233. X    } else if (mode == INSERT_MODE) { 
  1234. X    savedot(c);
  1235. X    switch(c) {
  1236. X  /**   case (ctl('h')):                back_space();   break; **/
  1237. X        case (ctl('h')): case DEL:      back_space();   break;
  1238. X    case (ctl('m')):  cr_line();            break;
  1239. X    case ESC:    edit_mode();            break;
  1240. X    default:    ins_in_line(c);            break;
  1241. X    }
  1242. X    } else if (mode == SEARCH_MODE) {
  1243. X    switch(c) {
  1244. X  /**   case (ctl('h')):                back_space();   break; **/
  1245. X        case (ctl('h')): case DEL:      back_space();   break;
  1246. X    case (ctl('m')):  search_hist();            break;
  1247. X    case ESC:    edit_mode();            break;
  1248. X    default:    ins_in_line(c);            break;
  1249. X    }
  1250. X   } else if (mode == REP_MODE) {
  1251. X    savedot(c);
  1252. X    switch(c) {
  1253. X  /**   case (ctl('h')):                back_space();   break; **/
  1254. X        case (ctl('h')): case DEL:      back_space();   break;
  1255. X    case (ctl('m')):  cr_line();            break;
  1256. X    case ESC:    edit_mode();            break;
  1257. X    default:    replace_in_line(c);        break;
  1258. X    }
  1259. X    }
  1260. X}
  1261. X
  1262. Xvoid
  1263. Xedit_mode()
  1264. X{
  1265. X    mode = EDIT_MODE;
  1266. X    mode_ind = 'e';
  1267. X    histp = -1;
  1268. X    if (linelim < 0)    /* -1 says stop editing, ...so we still aren't */
  1269. X    return;
  1270. X    if (line[linelim] == '\0')
  1271. X    linelim = back_line();
  1272. X}
  1273. X
  1274. Xvoid
  1275. Xinsert_mode()
  1276. X{
  1277. X    mode_ind = 'i';
  1278. X    mode = INSERT_MODE;
  1279. X}
  1280. X
  1281. Xstatic    void
  1282. Xsearch_mode()
  1283. X{
  1284. X    line[0] = '/';
  1285. X    line[1] = '\0';
  1286. X    linelim = 1;
  1287. X    histp = -1;
  1288. X    mode_ind = '/';
  1289. X    mode = SEARCH_MODE;
  1290. X}
  1291. X
  1292. Xstatic    void
  1293. Xreplace_mode()
  1294. X{
  1295. X    mode_ind = 'R';
  1296. X    mode = REP_MODE;
  1297. X}
  1298. X
  1299. X/* dot command functions.  Saves info so we can redo on a '.' command */
  1300. X
  1301. Xstatic    void
  1302. Xsavedot(c)
  1303. Xint c;
  1304. X{
  1305. X    if (do_dot || (c == '\n'))
  1306. X    return;
  1307. X
  1308. X    if (doti < DOTLEN-1)
  1309. X    {
  1310. X    dotb[doti++] = c;
  1311. X    dotb[doti] = '\0';
  1312. X    }
  1313. X}
  1314. X
  1315. Xstatic int dotcalled = 0;
  1316. X
  1317. Xstatic    void
  1318. Xdotcmd()
  1319. X{
  1320. X    int c;
  1321. X
  1322. X    if (dotcalled)    /* stop recursive calling of dotcmd() */
  1323. X    return;
  1324. X    do_dot = 1;
  1325. X    doti = 0;
  1326. X    while(dotb[doti] != '\0') {
  1327. X    c = dotb[doti++];
  1328. X    dotcalled = 1;
  1329. X    write_line(c);
  1330. X    }
  1331. X    do_dot = 0;
  1332. X    doti = 0;
  1333. X    dotcalled = 0;
  1334. X}
  1335. X
  1336. Xint
  1337. Xvigetch()
  1338. X{
  1339. X    int c;
  1340. X
  1341. X    if(do_dot) {
  1342. X    if (dotb[doti] != '\0') {
  1343. X        return(dotb[doti++]);
  1344. X    } else {
  1345. X        do_dot = 0;
  1346. X        doti = 0;
  1347. X        return(nmgetch());
  1348. X    }
  1349. X    }
  1350. X    c = nmgetch();
  1351. X    savedot(c);
  1352. X    return(c);
  1353. X}
  1354. X
  1355. X/* saves the current line for possible use by an undo cmd */
  1356. Xstatic    void
  1357. Xu_save(c)
  1358. Xint c;
  1359. X{   static    unsigned    undolen = 0;
  1360. X
  1361. X    if (strlen(line)+1 > undolen)
  1362. X    {    undolen = strlen(line)+40;
  1363. X
  1364. X    undo_line = Realloc(undo_line, undolen);
  1365. X    }
  1366. X    (void) strcpy(undo_line, line);
  1367. X
  1368. X    undo_lim = linelim;
  1369. X
  1370. X    /* reset dot command if not processing it. */
  1371. X
  1372. X    if (!do_dot) {
  1373. X        doti = 0;
  1374. X    savedot(c);
  1375. X    }
  1376. X}
  1377. X
  1378. X/* Restores the current line saved by u_save() */
  1379. Xstatic    void
  1380. Xrestore_it()
  1381. X{
  1382. X    static    char *tempc = NULL;
  1383. X    static    unsigned templen = 0;
  1384. X    int        tempi;
  1385. X
  1386. X    if ((undo_line == NULL) || (*undo_line == '\0')) 
  1387. X    return;
  1388. X
  1389. X    if (strlen(line)+1 > templen)
  1390. X    {    templen = strlen(line)+40;
  1391. X    tempc = Realloc(tempc, templen);
  1392. X    }
  1393. X
  1394. X    strcpy(tempc, line);
  1395. X    tempi = linelim;
  1396. X    (void) strcpy(line, undo_line);
  1397. X    linelim = undo_lim;
  1398. X    strcpy(undo_line, tempc);
  1399. X    undo_lim = tempi;
  1400. X}
  1401. X
  1402. X/* This command stops the editing process. */
  1403. Xstatic    void
  1404. Xstop_edit()
  1405. X{
  1406. X/**    showrange = 0; **/
  1407. X    linelim = -1;
  1408. X    (void) move(1, 0);
  1409. X    (void) clrtoeol();
  1410. X}
  1411. X
  1412. X/*
  1413. X * Motion commands.  Forward motion commands take an argument
  1414. X * which, when set, cause the forward motion to continue onto
  1415. X * the null at the end of the line instead of stopping at the
  1416. X * the last character of the line.
  1417. X */
  1418. Xstatic    int
  1419. Xfor_line(stop_null)
  1420. Xint stop_null;
  1421. X{
  1422. X    if (linelim >= 0 && line[linelim] != '\0' && 
  1423. X                    (line[linelim+1] != '\0' || stop_null))
  1424. X    return(linelim+1);
  1425. X    else
  1426. X    return(linelim);
  1427. X}
  1428. X
  1429. Xstatic    int
  1430. Xfor_word(stop_null)
  1431. Xint stop_null;
  1432. X{
  1433. X    register int c;
  1434. X    register int cpos;
  1435. X
  1436. X    cpos = linelim;
  1437. X
  1438. X    if (line[cpos] == ' ') {
  1439. X    while (line[cpos] == ' ')
  1440. X        cpos++;
  1441. X    if (cpos > 0 && line[cpos] == '\0')
  1442. X        --cpos;
  1443. X    return(cpos);
  1444. X    }
  1445. X
  1446. X    if (istext(line[cpos])) {
  1447. X        while ((c = line[cpos]) && istext(c)) 
  1448. X        cpos++;
  1449. X    } else {
  1450. X    while ((c = line[cpos]) && !istext(c) && c != ' ')
  1451. X        cpos++;
  1452. X    }
  1453. X
  1454. X    while (line[cpos] == ' ')
  1455. X        cpos++;
  1456. X
  1457. X    if (cpos > 0 && line[cpos] == '\0' && !stop_null) 
  1458. X        --cpos;
  1459. X
  1460. X    return(cpos);
  1461. X}
  1462. X
  1463. Xstatic    int
  1464. Xback_line()
  1465. X{
  1466. X    if (linelim)
  1467. X        return(linelim-1);
  1468. X    else
  1469. X    return(0);
  1470. X}
  1471. X
  1472. Xstatic    int
  1473. Xback_word()
  1474. X{
  1475. X    register int c;
  1476. X    register int cpos;
  1477. X
  1478. X    cpos = linelim;
  1479. X
  1480. X    if (line[cpos] == ' ') {
  1481. X    /* Skip white space */
  1482. X        while (cpos > 0 && line[cpos] == ' ')
  1483. X        --cpos;
  1484. X    } else if (cpos > 0 && (line[cpos-1] == ' ' 
  1485. X                     || ( istext(line[cpos]) && !istext(line[cpos-1]))
  1486. X                     || (!istext(line[cpos]) &&  istext(line[cpos-1])) )) {
  1487. X    /* Started on the first char of a word - back up to prev. word */
  1488. X    --cpos;
  1489. X        while (cpos > 0 && line[cpos] == ' ')
  1490. X        --cpos;
  1491. X    }
  1492. X
  1493. X    /* Skip across the word - goes 1 too far */
  1494. X    if (istext(line[cpos])) {
  1495. X        while (cpos > 0 && (c = line[cpos]) && istext(c)) 
  1496. X        --cpos;
  1497. X    } else {
  1498. X    while (cpos > 0 && (c = line[cpos]) && !istext(c) && c != ' ')
  1499. X        --cpos;
  1500. X    }
  1501. X
  1502. X    /* We are done - fix up the one too far */
  1503. X    if (cpos > 0 && line[cpos] && line[cpos+1]) 
  1504. X    cpos++;
  1505. X
  1506. X    return(cpos);
  1507. X}
  1508. X
  1509. X/* Text manipulation commands */
  1510. X
  1511. Xstatic    void
  1512. Xdel_in_line()
  1513. X{
  1514. X    register int len, i;
  1515. X
  1516. X    if (linelim >= 0) {
  1517. X    len = strlen(line);
  1518. X    if (linelim == len && linelim > 0)
  1519. X        linelim--;
  1520. X    for (i = linelim; i < len; i++)
  1521. X        line[i] = line[i+1];
  1522. X    }
  1523. X    if (linelim > 0 && line[linelim] == '\0')
  1524. X    --linelim;
  1525. X}
  1526. X
  1527. Xstatic    void
  1528. Xins_in_line(c)
  1529. Xint c;
  1530. X{
  1531. X    register int i, len;
  1532. X
  1533. X    if (linelim < 0)
  1534. X    {    *line = '\0';
  1535. X    linelim = 0;
  1536. X    }
  1537. X    len = strlen(line);
  1538. X    for (i = len; i >= linelim; --i)
  1539. X    line[i+1] = line[i];
  1540. X    line[linelim++] = c;
  1541. X    line[len+1] = '\0';
  1542. X}
  1543. X
  1544. Xvoid
  1545. Xins_string(s)
  1546. Xchar *s;
  1547. X{
  1548. X    while (*s)
  1549. X    ins_in_line(*s++);
  1550. X}
  1551. X
  1552. Xstatic    void
  1553. Xappend_line()
  1554. X{
  1555. X    register int i;
  1556. X
  1557. X    i = linelim;
  1558. X    if (i >= 0 && line[i])
  1559. X    linelim++;
  1560. X    insert_mode();
  1561. X}
  1562. X
  1563. Xstatic    void
  1564. Xrep_char()
  1565. X{
  1566. X    int c;
  1567. X
  1568. X    if (linelim < 0)
  1569. X    {    linelim = 0;
  1570. X    *line = '\0';
  1571. X    }
  1572. X    c = vigetch();
  1573. X    if (line[linelim] != '\0') {
  1574. X        line[linelim] = c;
  1575. X    } else {
  1576. X    line[linelim] = c;
  1577. X    line[linelim+1] = '\0';
  1578. X    }
  1579. X}
  1580. X
  1581. Xstatic    void
  1582. Xreplace_in_line(c)
  1583. Xint    c;
  1584. X{
  1585. X    register int len;
  1586. X
  1587. X    if (linelim < 0)
  1588. X    {    linelim = 0;
  1589. X    *line = '\0';
  1590. X    }
  1591. X    len = strlen(line);
  1592. X    line[linelim++] = c;
  1593. X    if (linelim > len)
  1594. X    line[linelim] = '\0';
  1595. X}
  1596. X
  1597. Xstatic    void
  1598. Xback_space()
  1599. X{
  1600. X    if (linelim == 0)
  1601. X    return;
  1602. X
  1603. X    if (line[linelim] == '\0') {
  1604. X    linelim = back_line();
  1605. X    del_in_line();
  1606. X    linelim = strlen(line);
  1607. X    } else {
  1608. X    linelim = back_line();
  1609. X    del_in_line();
  1610. X    }
  1611. X}
  1612. X
  1613. Xint
  1614. Xget_motion()
  1615. X{
  1616. X    int c;
  1617. X
  1618. X    c = vigetch();
  1619. X    switch (c) {
  1620. X    case 'b':    return(back_word());
  1621. X    case 'f':    return(find_char()+1);
  1622. X    case 'h':    return(back_line());
  1623. X    case 'l':    return(for_line(1));
  1624. X    case 't':    return(to_char()+1);
  1625. X    case 'w':    return(for_word(1));
  1626. X    default:    return(linelim);
  1627. X    }
  1628. X}
  1629. X
  1630. Xstatic    void
  1631. Xdelete_cmd()
  1632. X{
  1633. X    int cpos;
  1634. X
  1635. X    cpos = get_motion();
  1636. X    del_chars(cpos, linelim);
  1637. X}
  1638. X
  1639. Xstatic    void
  1640. Xchange_cmd()
  1641. X{
  1642. X    delete_cmd();
  1643. X    insert_mode();
  1644. X}
  1645. X
  1646. Xstatic    void
  1647. Xdel_chars(first, last)
  1648. Xregister int first, last;
  1649. X{
  1650. X    int temp;
  1651. X
  1652. X    if (first == last)
  1653. X    return;
  1654. X
  1655. X    if (last < first) {
  1656. X    temp = last; last = first; first = temp;
  1657. X    }
  1658. X
  1659. X    linelim = first;
  1660. X    while(first < last) {
  1661. X    del_in_line();
  1662. X    --last;
  1663. X    }
  1664. X}
  1665. X
  1666. Xstatic    void
  1667. Xdel_to_end()
  1668. X{
  1669. X    if (linelim < 0)
  1670. X    return;
  1671. X    line[linelim] = '\0';
  1672. X    linelim = back_line();
  1673. X}
  1674. X
  1675. Xstatic    void
  1676. Xcr_line()
  1677. X{
  1678. X    insert_mode();
  1679. X    if (linelim != -1) {
  1680. X/**    showrange = 0; **/
  1681. X    save_hist();
  1682. X    linelim = 0;
  1683. X    (void) yyparse ();
  1684. X    linelim = -1;
  1685. X    }
  1686. X    else    /* '\n' alone will put you into insert mode */
  1687. X    {    *line = '\0';
  1688. X    linelim = 0;
  1689. X    }
  1690. X}
  1691. X
  1692. X/* History functions */
  1693. X
  1694. Xstatic    void
  1695. Xsave_hist()
  1696. X{
  1697. X    if (lasthist < 0)
  1698. X    {    lasthist = 0;
  1699. X    }
  1700. X    else
  1701. X    lasthist = (lasthist + 1) % HISTLEN;
  1702. X
  1703. X    if (lasthist > endhist)
  1704. X    endhist = lasthist;
  1705. X
  1706. X    if (history[lasthist].len < strlen(line)+1)
  1707. X    {    history[lasthist].len = strlen(line)+40;
  1708. X    history[lasthist].histline = Realloc(history[lasthist].histline,
  1709. X                          history[lasthist].len);
  1710. X    }
  1711. X    (void) strcpy(history[lasthist].histline, line);
  1712. X}
  1713. X
  1714. Xstatic    void
  1715. Xback_hist()
  1716. X{
  1717. X    if (histp == -1)
  1718. X    histp = lasthist;
  1719. X    else
  1720. X    if (histp == 0)
  1721. X    {    if (endhist != lasthist)
  1722. X        histp = endhist;
  1723. X    }
  1724. X    else
  1725. X    if (histp != ((lasthist + 1) % (endhist + 1)))
  1726. X    histp--;
  1727. X
  1728. X    if (lasthist < 0)
  1729. X    line[linelim = 0] = '\0';
  1730. X    else {
  1731. X        (void) strcpy(line, history[histp].histline);
  1732. X    linelim = 0;
  1733. X    }
  1734. X}
  1735. X
  1736. Xstatic    void
  1737. Xsearch_hist()
  1738. X{
  1739. X    static    unsigned lastsrchlen = 0;
  1740. X
  1741. X    if(linelim < 1) {
  1742. X    linelim = 0;
  1743. X    edit_mode();
  1744. X    return;
  1745. X    }
  1746. X
  1747. X    if (strlen(line)+1 > lastsrchlen)
  1748. X    {    lastsrchlen = strlen(line)+40;
  1749. X    last_search = Realloc(last_search, lastsrchlen);
  1750. X    }
  1751. X    (void)strcpy(last_search, line+1);
  1752. X    search_again();
  1753. X    mode = EDIT_MODE;
  1754. X}
  1755. X
  1756. Xstatic    void
  1757. Xsearch_again()
  1758. X{
  1759. X    int found_it;
  1760. X    int do_next;
  1761. X    int prev_histp;
  1762. X    char *look_here;
  1763. X
  1764. X    prev_histp = histp;
  1765. X    if ((last_search == NULL) || (*last_search == '\0'))
  1766. X    return;
  1767. X
  1768. X    do {
  1769. X    back_hist();
  1770. X    if (prev_histp == histp)
  1771. X        break;
  1772. X    prev_histp = histp;
  1773. X    look_here = line;
  1774. X    found_it = do_next = 0;
  1775. X    while ((look_here = strchr(look_here, last_search[0])) != NULL &&
  1776. X                        !found_it && !do_next) {
  1777. X
  1778. X        if (strncmp(look_here, last_search, strlen(last_search)) == 0)
  1779. X        found_it++;
  1780. X        else if (look_here < line + strlen(line) - 1)
  1781. X            look_here++;
  1782. X        else
  1783. X        do_next++;
  1784. X    }
  1785. X    } while (!found_it);
  1786. X}
  1787. X
  1788. Xstatic    void
  1789. Xfor_hist()
  1790. X{
  1791. X    if (histp == -1)
  1792. X    histp = lasthist;
  1793. X    else
  1794. X    if (histp != lasthist)
  1795. X    histp = (histp + 1) % (endhist + 1);
  1796. X
  1797. X    if (lasthist < 0)
  1798. X    line[linelim = 0] = '\0';
  1799. X    else {
  1800. X    (void) strcpy(line, history[histp].histline);
  1801. X    linelim = 0;
  1802. X    }
  1803. X}
  1804. X
  1805. Xstatic    void
  1806. Xcol_0()
  1807. X{
  1808. X    linelim = 0;
  1809. X}
  1810. X
  1811. Xstatic    void
  1812. Xlast_col()
  1813. X{
  1814. X    linelim = strlen(line);
  1815. X    if (linelim > 0)
  1816. X    --linelim;
  1817. X}
  1818. X
  1819. Xstatic    int
  1820. Xfind_char()
  1821. X{
  1822. X    register int c;
  1823. X    register int i;
  1824. X
  1825. X
  1826. X    c = vigetch();
  1827. X    i = linelim;
  1828. X    while(line[i] && line[i] != c)
  1829. X    i++;
  1830. X    if (!line[i])
  1831. X    i = linelim;
  1832. X    return(i);
  1833. X}
  1834. X
  1835. Xstatic    int
  1836. Xto_char()
  1837. X{
  1838. X    register int i;
  1839. X
  1840. X    i = find_char();
  1841. X    if (i > 0 && i != linelim)
  1842. X    --i;
  1843. X
  1844. X    return(i);
  1845. X}
  1846. END_OF_FILE
  1847.   if test 13600 -ne `wc -c <'ss_12b/sc_stuff/vi.c'`; then
  1848.     echo shar: \"'ss_12b/sc_stuff/vi.c'\" unpacked with wrong size!
  1849.   fi
  1850.   # end of 'ss_12b/sc_stuff/vi.c'
  1851. fi
  1852. if test -f 'ss_12b/ss.c' -a "${1}" != "-c" ; then 
  1853.   echo shar: Will not clobber existing file \"'ss_12b/ss.c'\"
  1854. else
  1855.   echo shar: Extracting \"'ss_12b/ss.c'\" \(15245 characters\)
  1856.   sed "s/^X//" >'ss_12b/ss.c' <<'END_OF_FILE'
  1857. X/**********************************************************************
  1858. X* %M%
  1859. X* ss     :    A SpreadSheet Program
  1860. X*
  1861. X* Art's Spreadsheet program.          Art Mulder ( art@cs.ualberta.ca )
  1862. X* University of Alberta, Department of Computing Science.
  1863. X***********************************************************************
  1864. X* Main Driver
  1865. X***********************************************************************
  1866. X* This program is based (Heavily!) on the well know Public Domain
  1867. X* spreadsheet program 'sc' Revision 6.19
  1868. X* May 12/92 -> hacked a bit to bring it up to Rev 6/21 of `sc'
  1869. X***********************************************************************
  1870. X* SS Notes & Author List:
  1871. X*    Feb 1992: sc 6.19 hacked into a new incarnation: 'ss'
  1872. X*    - currently maintained by Art Mulder ( art@cs.ualberta.ca )
  1873. X*
  1874. X* SC Notes & Author List:
  1875. X*      original by James Gosling, September 1982
  1876. X*      modifications by Mark Weiser and Bruce Israel, 
  1877. X*          University of Maryland
  1878. X*  
  1879. X*      More mods Robert Bond, 12/86
  1880. X*      More mods by Alan Silverstein, 3-4/88, see list of changes.
  1881. X*      Currently supported by sequent!sawmill!buhrt (Jeff Buhrt)
  1882. X*      $Revision: 6.19 $
  1883. X**********************************************************************/
  1884. X#ifndef lint
  1885. X  static char Sccsid[] = "%W% %G%";
  1886. X#endif
  1887. X
  1888. X/*
  1889. X * Include files
  1890. X */
  1891. X#include <stdio.h>
  1892. X#include <sys/types.h>
  1893. X#include <signal.h>
  1894. X#include "curses_stuff.h"
  1895. X#include <ctype.h>
  1896. X
  1897. X#ifdef BSD42
  1898. X# include <strings.h>
  1899. X#else
  1900. X# ifndef SYSIII
  1901. X#   include <string.h>
  1902. X# endif
  1903. X#endif
  1904. X
  1905. X#include "ss.h"
  1906. X#include "menu.h"
  1907. X#include "disprange.h"
  1908. X#include "getinput.h"
  1909. X
  1910. X
  1911. X/*      Global Variables
  1912. X *----------------------------------------------------------------------
  1913. X */
  1914. X
  1915. X/*
  1916. X * User I/O variables
  1917. X */
  1918. Xchar message[MAXSTR];        /* To hold Messages to the user */
  1919. Xchar *buff;            /* Pointer to User Input buffer - see
  1920. X                   the gi_..() functions  */
  1921. Xchar *range;            /* Ptr to a range string - see
  1922. X                   functions that deal with ranges */
  1923. X
  1924. X/*
  1925. X * General Spreadsheet Variables
  1926. X */
  1927. Xstruct ent ***tbl;        /* data table ref. in vmtbl.c and ATBL() */
  1928. X
  1929. X  int strow = 0, stcol = 0;
  1930. X  int currow = 0, curcol = 0;    /* Current location of cell cursor */
  1931. X  int savedrow, savedcol;
  1932. X  int maxrow, maxcol;
  1933. X  int maxrows, maxcols;        /* # cells currently allocated */
  1934. X
  1935. Xchar curfile[PATHLEN];        /* Filename of spreadsheet */
  1936. X
  1937. X/** UNEXPLORED STUFF FOLLOWS **/
  1938. X/*********************************************************************/
  1939. Xextern    void    startdisp(), stopdisp();
  1940. X
  1941. X#ifdef SYSV3
  1942. X  void exit();
  1943. X#endif
  1944. X
  1945. X#ifndef SAVENAME
  1946. X# define    SAVENAME "SC.SAVE" /* file name to use for emergency saves */
  1947. X#endif /* SAVENAME */
  1948. X
  1949. X
  1950. X/*
  1951. X * Globals defined in sc.h
  1952. X */
  1953. X
  1954. X  int FullUpdate = 0;
  1955. X  int ClearScreen = 0;    /* don't try to be smart (?? Art M.)*/
  1956. X  int *fwidth;
  1957. X  int *precision;
  1958. X  int *realfmt;
  1959. X  char *col_hidden;
  1960. X  char *row_hidden;
  1961. X  char line[FBUFLEN];        /* Most commands to manipulate the
  1962. X                   spreadsheet are stored in this
  1963. X                   variable, and then parsed by a main
  1964. X                   routine. */
  1965. X  int changed;
  1966. X  struct ent *to_fix;
  1967. X  int modflg;            /* Flag: spreadsheet modified */
  1968. X  char *mdir;
  1969. X  int showsc, showsr;    /* Starting cell for highlighted range */
  1970. X#ifdef RIGHT_CBUG
  1971. X  int    wasforw    = FALSE;
  1972. X#endif
  1973. X
  1974. X/*
  1975. X * Function Prototypes
  1976. X */
  1977. X  void    update();
  1978. X  void    repaint();
  1979. X
  1980. X
  1981. X  char    revmsg[80];
  1982. X
  1983. X  int  linelim = -1;
  1984. X
  1985. X  int  showtop   = 1;    /* Causes current cell value display in top line  */
  1986. X  int  showcell  = 1;    /* Causes current cell to be highlighted      */
  1987. X  int  showrange = 0;    /* Causes ranges to be highlighted          */
  1988. X  int  showneed  = 0;    /* Causes cells needing values to be highlighted  */
  1989. X  int  showexpr  = 0;    /* Causes cell exprs to be displayed, highlighted */
  1990. X
  1991. X  int  autocalc = 1 ;    /* 1 to calculate after each update */
  1992. X  int  autolabel = 1;   /* If room, causes label to be created after a define*/
  1993. X  int  calc_order = BYROWS;
  1994. X  int  tbl_style = 0;    /* headers for T command output */
  1995. X  int  rndinfinity = 0;
  1996. X  int  craction = 0;    /* 1 for down, 2 for right */
  1997. X  int  rowlimit = -1;
  1998. X  int  collimit = -1;
  1999. X#ifdef    SIGWINCH
  2000. X  int  hitwinch = 0;    /* got a SIGWINCH? */
  2001. X#endif
  2002. X
  2003. X  extern int lastmx, lastmy;    /* Screen address of the cursor */
  2004. X  extern int lastcol, lcols;    /* Spreadsheet Column the cursor was in last */
  2005. X
  2006. X/* a linked list of free [struct ent]'s, uses .next as the pointer */
  2007. X  struct ent *freeents = NULL;
  2008. X
  2009. X  extern    int    seenerr;
  2010. X  extern    char    *rev;
  2011. X
  2012. X#ifdef VMS
  2013. X  int VMS_read_raw = 0;
  2014. X#endif
  2015. X
  2016. Xchar    *progname;
  2017. X/*********************************************************************/
  2018. X/** UNEXPLORED STUFF ENDS **/
  2019. X
  2020. X/*
  2021. X * Global Variables 
  2022. X */
  2023. X    int running;    /* Flag for signal a 'quit' request from user */
  2024. X    int anychanged = FALSE; 
  2025. X
  2026. X/*      Internal Macros & Data Structures
  2027. X *----------------------------------------------------------------------
  2028. X */
  2029. X
  2030. Xint main (argc, argv)
  2031. X/*--------------------------------------------------------------------*/
  2032. X  int     argc;
  2033. X  char  **argv;
  2034. X{
  2035. X    int     inloop = 1;
  2036. X    register int   c;         /* Main input character */
  2037. X    char    *revi;
  2038. X/** int        anychanged = FALSE; **/
  2039. X
  2040. X/*
  2041. X * PROCESS COMMAND LINE OPTIONS
  2042. X *     Keep command line options around until the file is read so the
  2043. X *     command line overrides file options.
  2044. X */
  2045. X    int Mopt = 0;
  2046. X    int Nopt = 0;
  2047. X    int Copt = 0; 
  2048. X    int Ropt = 0;
  2049. X
  2050. X    int tempx, tempy;     /* Temp versions of curx, cury */
  2051. X
  2052. X#if defined(MSDOS)
  2053. X    if ((revi = strrchr(argv[0], '\\')) != NULL)
  2054. X#else
  2055. X# ifdef VMS
  2056. X    if ((revi = strrchr(argv[0], ']')) != NULL)
  2057. X# else
  2058. X    if ((revi = strrchr(argv[0], '/')) != NULL)
  2059. X# endif
  2060. X#endif
  2061. X    progname = revi+1;
  2062. X    else
  2063. X    progname = argv[0];
  2064. X
  2065. X    while (argc > 1 && argv[1][0] == '-') {
  2066. X    argv++;
  2067. X    argc--;
  2068. X        switch (argv[0][1]) {
  2069. X#if !defined(VMS) && !defined(MSDOS) && defined(CRYPT_PATH)
  2070. X        case 'x':
  2071. X            Crypt = 1;
  2072. X            break;
  2073. X#endif
  2074. X        case 'm':
  2075. X            Mopt = 1;
  2076. X            break;
  2077. X        case 'c':
  2078. X            Copt = 1;
  2079. X            break;
  2080. X        case 'r':
  2081. X            Ropt = 1;
  2082. X            break;
  2083. X        case 'C':
  2084. X            craction = CRCOLS;
  2085. X            break;
  2086. X        case 'R':
  2087. X            craction = CRROWS;
  2088. X            break;
  2089. X        default:
  2090. X            Fprintf(stderr,"%s: unrecognized option: \"%c\"\n",
  2091. X            progname,argv[0][1]);
  2092. X            exit(1);
  2093. X    }
  2094. X    }
  2095. X
  2096. X    *curfile ='\0';
  2097. X
  2098. X    startdisp();
  2099. X    signals();
  2100. X
  2101. X    /* setup the spreadsheet arrays, initscr() will get the screen size */
  2102. X    if (!growtbl(GROWNEW, 0, 0))
  2103. X    {    stopdisp();
  2104. X    exit(1);
  2105. X    }
  2106. X
  2107. X/*
  2108. X * Build revision message for later use:
  2109. X */
  2110. X    Strcpy (revmsg, progname);
  2111. X    for (revi = rev; (*revi++) != ':'; );    /* copy after colon */
  2112. X    Strcat (revmsg, revi);
  2113. X    revmsg [strlen (revmsg) - 2] = 0;        /* erase last character */
  2114. X
  2115. X/*  Strcat (revmsg, ":  Type '?' for help, '/' for main menu");  */
  2116. X    Strcat (revmsg, ":  Type '/' for the main menu."); 
  2117. X    
  2118. X/*
  2119. X * READ IN SPREADSHEET FILE
  2120. X */
  2121. X    if (argc > 1) {
  2122. X    Strcpy(curfile,argv[1]);
  2123. X    readfile (argv[1], 0);
  2124. X    }
  2125. X
  2126. X/*
  2127. X * APPLY COMMAND LINE OPTIONS
  2128. X *     Command line options override settings stored in spreadsheet
  2129. X *    file.  Therefore they are applied after the file is read.
  2130. X */
  2131. X    if (Mopt)
  2132. X    autocalc = 0;
  2133. X    if (Copt)
  2134. X    calc_order = BYCOLS;
  2135. X    if (Ropt)
  2136. X    calc_order = BYROWS;
  2137. X
  2138. X    modflg = 0;
  2139. X#ifdef VENIX
  2140. X    setbuf (stdin, NULL);
  2141. X#endif
  2142. X    FullUpdate++;
  2143. X
  2144. X/************
  2145. X* MAIN LOOP
  2146. X************/
  2147. X    while (inloop) { running = 1;
  2148. X    while (running) {
  2149. X
  2150. X/* 
  2151. X * RECALCULATE THE SPREADSHEET.
  2152. X */
  2153. X/**    if (edistate < 0 && linelim < 0 && autocalc && (changed || FullUpdate))
  2154. X**/
  2155. X    if (autocalc && (changed || FullUpdate)) {
  2156. X        EvalAll ();
  2157. X        if (changed)        /* if EvalAll changed or was before */
  2158. X        anychanged = TRUE;
  2159. X        changed = 0;
  2160. X
  2161. X    } else if (changed)        /* any cells change? */
  2162. X         anychanged = TRUE;
  2163. X
  2164. X#ifdef    SIGWINCH
  2165. X    /* got a SIGWINCH? */
  2166. X    if (hitwinch) {
  2167. X        hitwinch = 0;
  2168. X        stopdisp();
  2169. X        startdisp();
  2170. X        FullUpdate++;
  2171. X    }
  2172. X#endif
  2173. X    update(anychanged);
  2174. X    anychanged = FALSE;
  2175. X
  2176. X/*
  2177. X * GET MAIN ROOT-LEVEL COMMAND/INPUT
  2178. X */
  2179. X    c = nmgetch();            /* Get next input character */
  2180. X    getyx(stdscr, tempy, tempx);
  2181. X    ClearMessage;
  2182. X    Move(tempy, tempx);
  2183. X/*    (void) fflush (stdout);*/
  2184. X    seenerr = 0;
  2185. X    showneed = 0;    /* reset after each update */
  2186. X    showexpr = 0;
  2187. X
  2188. X     /* if ((c < ' ') || ( c == DEL )) { how about international here ? PB */
  2189. X#if pyr
  2190. X    if ( iscntrl(c) || (c >= 011 && c <= 015) ) {
  2191. X#else
  2192. X    if ( ( isascii(c) && iscntrl(c) ) || (c == 020 ) ) {
  2193. X#endif
  2194. X      /* iscntrl broken in OSx4.1 */
  2195. X        /*
  2196. X         * There seems to be some question about what to do w/ the
  2197. X         * iscntrl, some BSD systems are reportedly broken as well.
  2198. X         */
  2199. X            ProcessControlCommands(c);    /* 1) A Control character */
  2200. X
  2201. X    } else {     /* NOT a control character, just plain ascii.  */
  2202. X
  2203. X/*
  2204. X * Local Macro: Cannot change locked cells
  2205. X */
  2206. X#define ABORT_IF_LOCKED_CELL     {if (locked_cell(currow, curcol)) \
  2207. X                     { beep(); break; } }
  2208. X        
  2209. X        switch (c) {
  2210. X          case '/':        /* 2) Enter Command/Menu Mode */
  2211. X        MainMenu();    
  2212. X        break;
  2213. X
  2214. X          case '?':        /* 3) Invoke Help */
  2215. X/*           help(HELP); */
  2216. X        break;
  2217. X
  2218. X
  2219. X          /*
  2220. X           * 4) Numeric or Function Entry into cell.
  2221. X           *    The case of the '=' differs from the rest in that
  2222. X           *    we do not want the '=' put into the user's input
  2223. X           *    buffer.
  2224. X           */
  2225. X          case '=':        /* retained for 'sc' compatibility */
  2226. X          case '0': case '1': case '2': case '3': case '4':
  2227. X          case '5': case '6': case '7': case '8': case '9':
  2228. X          case '-': case '.': case '+':
  2229. X          case '@':        /* @ = begin a function */
  2230. X        ABORT_IF_LOCKED_CELL;
  2231. X        Message("%s (Value)", v_name(currow, curcol) );
  2232. X
  2233. X        if ( c != '=' )
  2234. X            nmungetch( c ); /* push c back onto input stream */
  2235. X        
  2236. X        buff = gi_line_cursor();
  2237. X        ABORT_AND_BREAK_IF_BUFF_NULL;
  2238. X        
  2239. X        Sprintf(line,"let %s = %s", v_name(currow, curcol), buff);
  2240. X        ClearMessage;
  2241. X        PROCESS_line;
  2242. X        break;
  2243. X
  2244. X          /*
  2245. X           * 5) Label/String Entry into cell.
  2246. X           */
  2247. X          case '"':        /* 5.a) Centered String */
  2248. X        ABORT_IF_LOCKED_CELL;
  2249. X        Message("%s (Label)", v_name(currow, curcol) );
  2250. X        buff = gi_line_cursor();
  2251. X        ABORT_AND_BREAK_IF_BUFF_NULL;
  2252. X        Sprintf (line, "label %s = \"%s\"",
  2253. X             v_name(currow, curcol), buff);
  2254. X        PROCESS_line;
  2255. X        break;
  2256. X          case '>':        /* 5.b) Right Justified String */
  2257. X        ABORT_IF_LOCKED_CELL;
  2258. X        Message("%s (Flush-Right Label)", v_name(currow, curcol) );
  2259. X        buff = gi_line_cursor();
  2260. X        ABORT_AND_BREAK_IF_BUFF_NULL;
  2261. X        Sprintf (line, "rightstring %s = \"%s\"",
  2262. X             v_name(currow, curcol), buff);
  2263. X        PROCESS_line;
  2264. X        break;
  2265. X
  2266. X          /* 
  2267. X           * The default is to assume that they are starting a
  2268. X           * left-justified string.  Make sure that the character
  2269. X           * they just entered gets included in the string value.
  2270. X           */
  2271. X          case '<':        /* 5.c Left Justified String */
  2272. X          default:
  2273. X        ABORT_IF_LOCKED_CELL;
  2274. X        Message("%s (Flush-Left Label)", v_name(currow, curcol) );
  2275. X
  2276. X        if ( c != '<' )
  2277. X            nmungetch( c ); /* push c back onto input stream */
  2278. X        
  2279. X        buff = gi_line_cursor();
  2280. X        ABORT_AND_BREAK_IF_BUFF_NULL;
  2281. X        
  2282. X        Sprintf (line, "leftstring %s = \"%s\"",
  2283. X             v_name(currow, curcol), buff);
  2284. X        PROCESS_line;
  2285. X        break;
  2286. X
  2287. X        }    /* End of Command Switch */
  2288. X    } /* End of Else */
  2289. X/*
  2290. X * NO MORE Command options.
  2291. X */
  2292. X    }        /* while (running) */
  2293. X    inloop = modcheck(" before exiting");
  2294. X    }        /*  while (inloop) */
  2295. X/******************
  2296. X* END OF MAIN LOOP
  2297. X******************/
  2298. X
  2299. X    stopdisp();
  2300. X#ifdef VMS    /* Until VMS "fixes" exit we should say 1 here */
  2301. X    exit(1);
  2302. X#else
  2303. X    exit(0);
  2304. X#endif
  2305. X    /*NOTREACHED*/
  2306. X
  2307. X} /* end Main() */
  2308. X
  2309. X/*********************************************************************/
  2310. X
  2311. X/* set the calculation order */
  2312. Xvoid setorder(i)
  2313. X    int i;
  2314. X{
  2315. X    if((i == BYROWS)||(i == BYCOLS))
  2316. X    calc_order = i;
  2317. X}
  2318. X
  2319. Xvoid setauto(i)
  2320. X    int i;
  2321. X{
  2322. X    autocalc = i;
  2323. X}
  2324. X
  2325. Xvoid signals()
  2326. X{
  2327. X    VOID_OR_INT doquit();
  2328. X    VOID_OR_INT time_out();
  2329. X    VOID_OR_INT dump_me();
  2330. X#ifdef    SIGWINCH
  2331. X    VOID_OR_INT winchg();
  2332. X#endif
  2333. X
  2334. X    Signal(SIGINT, SIG_IGN);
  2335. X#if !defined(MSDOS)
  2336. X    Signal(SIGQUIT, dump_me);
  2337. X    Signal(SIGPIPE, doquit);
  2338. X    Signal(SIGALRM, time_out);
  2339. X    Signal(SIGBUS, doquit);
  2340. X#endif
  2341. X    Signal(SIGTERM, doquit);
  2342. X    Signal(SIGFPE, doquit);
  2343. X#ifdef    SIGWINCH
  2344. X    Signal(SIGWINCH, winchg);
  2345. X#endif
  2346. X}
  2347. X
  2348. X#ifdef    SIGWINCH
  2349. X  VOID_OR_INT winchg()
  2350. X  {    hitwinch++;
  2351. X      Signal(SIGWINCH, winchg);
  2352. X  }
  2353. X#endif
  2354. X
  2355. XVOID_OR_INT doquit()
  2356. X{
  2357. X    diesave();
  2358. X    stopdisp();
  2359. X    exit(1);
  2360. X}
  2361. X
  2362. XVOID_OR_INT dump_me()
  2363. X{
  2364. X    diesave();
  2365. X    deraw();
  2366. X    abort();
  2367. X}
  2368. X
  2369. X/* try to save the current spreadsheet if we can */
  2370. Xvoid diesave()
  2371. X{   char    path[PATHLEN];
  2372. X
  2373. X    if (modcheck(" before Spreadsheet dies") == 1)
  2374. X    {    Sprintf(path, "~/%s", SAVENAME);
  2375. X    if (writefile(path, 0, 0, maxrow, maxcol) < 0)
  2376. X    {
  2377. X        Sprintf(path, "/tmp/%s", SAVENAME);
  2378. X        if (writefile(path, 0, 0, maxrow, maxcol) < 0)
  2379. X        Message("Couldn't save current spreadsheet, Sorry");
  2380. X    }
  2381. X    }
  2382. X}
  2383. X
  2384. X/*
  2385. X * modcheck()
  2386. X *    Check if Spreadsheet has been modified and ask to save
  2387. X */
  2388. Xint modcheck(endstr)
  2389. X  char *endstr;        /* message to user */
  2390. X{
  2391. X    if (modflg && curfile[0]) {
  2392. X    int    yn_ans;
  2393. X    char    lin[100];
  2394. X
  2395. X    Sprintf (lin,"File \"%s\" is modified, save%s? ",
  2396. X        curfile,endstr);
  2397. X    if ((yn_ans = yn_ask(lin)) < 0)
  2398. X        return(1);
  2399. X    else if (yn_ans == 1) {
  2400. X        if (writefile(curfile, 0, 0, maxrow, maxcol) < 0)
  2401. X         return (1);
  2402. X    }
  2403. X    } else if (modflg) {
  2404. X    int    yn_ans;
  2405. X
  2406. X    if ((yn_ans = yn_ask("Do you want a chance to save the data? ")) < 0)
  2407. X        return(1);
  2408. X    else
  2409. X        return(yn_ans);
  2410. X    }
  2411. X    return(0);
  2412. X} /* modcheck() */
  2413. X
  2414. X/* Returns 1 if cell is locked, 0 otherwise */
  2415. Xint locked_cell (r, c)
  2416. X    int r, c;
  2417. X{
  2418. X    struct ent *p = *ATBL(tbl, r, c);
  2419. X    if (p && (p->flags & is_locked)) {
  2420. X    Message("Cell %s%d is locked", coltoa(c), r) ;
  2421. X    return(1);
  2422. X    }
  2423. X    return(0);
  2424. X}
  2425. X
  2426. X/* Check if area contains locked cells */
  2427. Xint any_locked_cells(r1, c1, r2, c2)
  2428. X    int r1, c1, r2, c2 ;
  2429. X{
  2430. X    int r, c;
  2431. X    struct ent *p ;
  2432. X
  2433. X    for (r=r1; r<=r2; r++)
  2434. X    for (c=c1; c<=c2; c++) {
  2435. X        p = *ATBL(tbl, r, c);
  2436. X        if (p && (p->flags&is_locked))
  2437. X        return(1);
  2438. X    }
  2439. X    return(0);
  2440. X}
  2441. X
  2442. X/* 
  2443. X * return a pointer to a cell's [struct ent *], creating if needed 
  2444. X */
  2445. Xstruct ent * lookat(row,col)
  2446. X    int    row, col;
  2447. X{
  2448. X    register struct ent **pp;
  2449. X
  2450. X    checkbounds(&row, &col);
  2451. X    pp = ATBL(tbl, row, col);
  2452. X    if (*pp == (struct ent *)0) {
  2453. X        if (freeents != NULL)
  2454. X    {    *pp = freeents;
  2455. X        freeents = freeents->next;
  2456. X    }
  2457. X    else
  2458. X        *pp = (struct ent *) Malloc((unsigned)sizeof(struct ent));
  2459. X    if (row>maxrow) maxrow = row;
  2460. X    if (col>maxcol) maxcol = col;
  2461. X    (*pp)->label = (char *)0;
  2462. X    (*pp)->row = row;
  2463. X    (*pp)->col = col;
  2464. X    (*pp)->flags = 0;
  2465. X    (*pp)->expr = (struct enode *)0;
  2466. X    (*pp)->v = (double) 0.0;
  2467. X    (*pp)->format = (char *)0;
  2468. X    (*pp)->cellerror = CELLOK;
  2469. X    (*pp)->next = NULL;
  2470. X    }
  2471. X    return *pp;
  2472. X}
  2473. X
  2474. X/*
  2475. X * This structure is used to keep ent structs around before they
  2476. X * are deleted to allow the sync_refs routine a chance to fix the
  2477. X * variable references.
  2478. X * We also use it as a last-deleted buffer for the 'p' command.
  2479. X */
  2480. Xvoid free_ent(p)
  2481. X    register struct ent *p;
  2482. X{
  2483. X    p->next = to_fix;
  2484. X    to_fix = p;
  2485. X    p->flags |= is_deleted;
  2486. X    p->flags &= ~is_locked;
  2487. X}
  2488. X
  2489. X/* free deleted cells */
  2490. Xvoid flush_saved()
  2491. X{
  2492. X    register struct ent *p;
  2493. X    register struct ent *q;
  2494. X
  2495. X    if (!(p = to_fix))
  2496. X    return;
  2497. X    while (p) {
  2498. X    clearent(p);
  2499. X    q = p->next;
  2500. X    p->next = freeents;    /* put this ent on the front of freeents */
  2501. X    freeents = p;
  2502. X    p = q;
  2503. X    }
  2504. X    to_fix = NULL;
  2505. X}
  2506. X/**********************************************************************
  2507. X*    END
  2508. X**********************************************************************/
  2509. END_OF_FILE
  2510.   if test 15245 -ne `wc -c <'ss_12b/ss.c'`; then
  2511.     echo shar: \"'ss_12b/ss.c'\" unpacked with wrong size!
  2512.   fi
  2513.   # end of 'ss_12b/ss.c'
  2514. fi
  2515. echo shar: End of archive 8 \(of 11\).
  2516. cp /dev/null ark8isdone
  2517. MISSING=""
  2518. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2519.     if test ! -f ark${I}isdone ; then
  2520.     MISSING="${MISSING} ${I}"
  2521.     fi
  2522. done
  2523. if test "${MISSING}" = "" ; then
  2524.     echo You have unpacked all 11 archives.
  2525.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2526. else
  2527.     echo You still must unpack the following archives:
  2528.     echo "        " ${MISSING}
  2529. fi
  2530. exit 0
  2531. exit 0 # Just in case...
  2532.