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

  1. Newsgroups: comp.sources.misc
  2. From: art@cs.ualberta.ca (Art Mulder)
  3. Subject: v35i089:  ss - Simple Spreadsheet program, v1.2b, Part03/11
  4. Message-ID: <1993Feb22.152754.21383@sparky.imd.sterling.com>
  5. X-Md4-Signature: d87ea6db33a21d8285fc2907cde5f37a
  6. Date: Mon, 22 Feb 1993 15:27:54 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: art@cs.ualberta.ca (Art Mulder)
  10. Posting-number: Volume 35, Issue 89
  11. Archive-name: ss/part03
  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/cmds.c ss_12b/screen.c
  19. # Wrapped by kent@sparky on Sat Feb 20 16:01:01 1993
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 3 (of 11)."'
  23. if test -f 'ss_12b/cmds.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'ss_12b/cmds.c'\"
  25. else
  26.   echo shar: Extracting \"'ss_12b/cmds.c'\" \(42376 characters\)
  27.   sed "s/^X//" >'ss_12b/cmds.c' <<'END_OF_FILE'
  28. X/*    SC    A Spreadsheet Calculator
  29. X *        Command routines
  30. X *
  31. X *        original by James Gosling, September 1982
  32. X *        modifications by Mark Weiser and Bruce Israel,
  33. X *            University of Maryland
  34. X *
  35. X *              More mods Robert Bond, 12/86
  36. X *
  37. X *        $Revision: 6.19 $
  38. X */
  39. X /* patched in some of the sc Rev 6.21 stuff.  Art Mulder, 5/92 */
  40. X
  41. X#ifndef lint
  42. X  static char Sccsid[] = "%W% %G%";
  43. X#endif
  44. X
  45. X/*
  46. X * Include Files
  47. X */
  48. X#include <sys/types.h>
  49. X#if defined(BSD42) || defined(BSD43)
  50. X#  include <strings.h>
  51. X#else
  52. X#  ifndef SYSIII
  53. X#    include <string.h>
  54. X#  endif
  55. X#endif
  56. X
  57. X#include "curses_stuff.h"
  58. X
  59. X#if defined(BSD42) || defined(BSD43) || defined(VMS)
  60. X#  include <sys/file.h>
  61. X#else
  62. X#  include <fcntl.h>
  63. X#endif
  64. X
  65. X#include <signal.h>
  66. X#include <errno.h>
  67. X
  68. X#include "ss.h"
  69. X#include "keys.h"
  70. X
  71. X/*
  72. X * Function Prototypes
  73. X */
  74. X
  75. X#ifdef SYSV3
  76. Xextern void exit();
  77. X#else
  78. Xextern int exit();
  79. X#endif
  80. X
  81. Xvoid    openrow();
  82. Xvoid    syncref();
  83. Xvoid    unspecial();
  84. X
  85. Xextern    int    errno;
  86. X
  87. X/* a linked list of free [struct ent]'s, uses .next as the pointer */
  88. Xextern    struct ent *freeents;
  89. X
  90. X/* a linked list of free [struct enodes]'s, uses .e.o.left as the pointer */
  91. Xextern    struct enode *freeenodes;
  92. X
  93. X#define DEFCOLDELIM ':'
  94. X
  95. X/* copy the current row (currow) and place the cursor in the new row */
  96. Xvoid
  97. Xduprow()
  98. X{
  99. X    if (currow >= maxrows - 1 || maxrow >= maxrows - 1) {
  100. X    if (!growtbl(GROWROW, 0, 0))
  101. X        return;
  102. X    }
  103. X    modflg++;
  104. X    currow++;
  105. X    openrow (currow);
  106. X    for (curcol = 0; curcol <= maxcol; curcol++) {
  107. X    register struct ent *p = *ATBL(tbl, currow - 1, curcol);
  108. X    if (p) {
  109. X        register struct ent *n;
  110. X        n = lookat (currow, curcol);
  111. X        copyent ( n, p, 1, 0);
  112. X    }
  113. X    }
  114. X    for (curcol = 0; curcol <= maxcol; curcol++) {
  115. X    register struct ent *p = *ATBL(tbl, currow, curcol);
  116. X    if (p && (p -> flags & is_valid) && !p -> expr)
  117. X        break;
  118. X    }
  119. X    if (curcol > maxcol)
  120. X    curcol = 0;
  121. X}
  122. X
  123. X/* copy the current column (curcol) and place the cursor in the new column */
  124. Xvoid
  125. Xdupcol() 
  126. X{
  127. X    if (curcol >= maxcols - 1 || maxcol >= maxcols - 1) {
  128. X    if (!growtbl(GROWCOL, 0, 0))
  129. X        return;
  130. X    }
  131. X    modflg++;
  132. X    curcol++;
  133. X    opencol (curcol, 1);
  134. X    for (currow = 0; currow <= maxrow; currow++) {
  135. X    register struct ent *p = *ATBL(tbl, currow, curcol - 1);
  136. X    if (p) {
  137. X        register struct ent *n;
  138. X        n = lookat (currow, curcol);
  139. X        copyent ( n, p, 0, 1);
  140. X    }
  141. X    }
  142. X    for (currow = 0; currow <= maxrow; currow++) {
  143. X    register struct ent *p = *ATBL(tbl, currow, curcol);
  144. X    if (p && (p -> flags & is_valid) && !p -> expr)
  145. X        break;
  146. X    }
  147. X    if (currow > maxrow)
  148. X    currow = 0;
  149. X}
  150. X
  151. X/* insert 'arg' rows before currow */
  152. Xvoid
  153. Xinsertrow(arg)
  154. Xregister int arg;
  155. X{
  156. X    while (--arg>=0) openrow (currow);
  157. X}
  158. X
  159. Xvoid deleterow(startrow,endrow)
  160. X/*----------------------------------------------------------------------
  161. X** Delete the rows from 'startrow' to 'endrow'.  (startrow must be
  162. X** <= endrow.)
  163. X*/
  164. X    register int startrow,endrow;
  165. X{
  166. X    if (any_locked_cells(startrow, 0, endrow, maxcol))
  167. X    error("Locked cells encountered. Nothing changed");
  168. X    else {
  169. X        flush_saved();
  170. X        erase_area(startrow, 0, endrow, maxcol);
  171. X/*        currow += arg;
  172. X**        while (--arg>=0) closerow (--currow);
  173. X*/
  174. X        currow = startrow;
  175. X    while (startrow <= endrow) 
  176. X        closerow(endrow--);
  177. X        sync_refs();
  178. X    }
  179. X}
  180. X
  181. Xvoid
  182. Xerase_area(sr, sc, er, ec)
  183. Xint sr, sc, er, ec;
  184. X{
  185. X    register int r, c;
  186. X    register struct ent **pp;
  187. X
  188. X    if (sr > er) {
  189. X    r = sr; sr = er; er= r;    
  190. X    }
  191. X
  192. X    if (sc > ec) {
  193. X    c = sc; sc = ec; ec= c;    
  194. X    }
  195. X
  196. X    if (sr < 0)
  197. X    sr = 0; 
  198. X    if (sc < 0)
  199. X    sc = 0;
  200. X    checkbounds(&er, &ec);
  201. X
  202. X    for (r = sr; r <= er; r++) {
  203. X    for (c = sc; c <= ec; c++) {
  204. X        pp = ATBL(tbl, r, c);
  205. X        if (*pp && !((*pp)->flags&is_locked)) {
  206. X        free_ent(*pp);
  207. X        *pp = (struct ent *)0;
  208. X        }
  209. X    }
  210. X    }
  211. X}
  212. X
  213. X/*
  214. X * deletes the expression associated w/ a cell and turns it into a constant
  215. X * containing whatever was on the screen
  216. X */
  217. Xvoid
  218. Xvalueize_area(sr, sc, er, ec)
  219. Xint sr, sc, er, ec;
  220. X{
  221. X    register int r, c;
  222. X    register struct ent *p;
  223. X
  224. X    if (sr > er) {
  225. X    r = sr; sr = er; er= r;    
  226. X    }
  227. X
  228. X    if (sc > ec) {
  229. X    c = sc; sc = ec; ec= c;    
  230. X    }
  231. X
  232. X    if (sr < 0)
  233. X    sr = 0; 
  234. X    if (sc < 0)
  235. X    sc = 0;
  236. X    checkbounds(&er, &ec);
  237. X
  238. X    for (r = sr; r <= er; r++) {
  239. X    for (c = sc; c <= ec; c++) {
  240. X        p = *ATBL(tbl, r, c);
  241. X        if (p && p->flags&is_locked) {
  242. X        error(" Cell %s%d is locked", coltoa(c), r);
  243. X        continue;
  244. X        }
  245. X        if (p && p->expr) {
  246. X        efree(p->expr);
  247. X        p->expr = (struct enode *)0;
  248. X        p->flags &= ~is_strexpr;
  249. X        }
  250. X    }
  251. X    }
  252. X
  253. X}
  254. X
  255. Xvoid
  256. Xpullcells(to_insert)
  257. Xint to_insert;
  258. X{
  259. X    register struct ent *p, *n;
  260. X    register int deltar, deltac;
  261. X    int minrow, mincol;
  262. X    int mxrow, mxcol;
  263. X    int numrows, numcols;
  264. X
  265. X    if (! to_fix)
  266. X    {
  267. X    error ("No data to pull");
  268. X    return;
  269. X    }
  270. X
  271. X    minrow = maxrows; 
  272. X    mincol = maxcols;
  273. X    mxrow = 0;
  274. X    mxcol = 0;
  275. X
  276. X    for (p = to_fix; p; p = p->next) {
  277. X    if (p->row < minrow)
  278. X        minrow = p->row;
  279. X    if (p->row > mxrow)
  280. X        mxrow = p->row;
  281. X    if (p->col < mincol)
  282. X        mincol = p->col;
  283. X    if (p->col > mxcol)
  284. X        mxcol = p->col;
  285. X    }
  286. X
  287. X    numrows = mxrow - minrow + 1;
  288. X    numcols = mxcol - mincol + 1;
  289. X    deltar = currow - minrow;
  290. X    deltac = curcol - mincol;
  291. X
  292. X    if (to_insert == 'r') {
  293. X    insertrow(numrows);
  294. X    deltac = 0;
  295. X    } else if (to_insert == 'c') {
  296. X    opencol(curcol, numcols);
  297. X    deltar = 0;
  298. X    }
  299. X
  300. X    FullUpdate++;
  301. X    modflg++;
  302. X
  303. X    for (p = to_fix; p; p = p->next) {
  304. X    n = lookat (p->row + deltar, p->col + deltac);
  305. X    clearent(n);
  306. X    copyent( n, p, deltar, deltac);
  307. X    n -> flags = p -> flags & ~is_deleted;
  308. X    }
  309. X}
  310. X
  311. X/* 
  312. X** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  313. X** Art Mulder Modified:  See "rowcolumn.c"
  314. X** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  315. X**
  316. X** void
  317. X** colshow_op()
  318. X** {
  319. X**     register int i,j;
  320. X**     for (i=0; i<maxcols; i++)
  321. X**     if (col_hidden[i]) 
  322. X**         break;
  323. X**     for(j=i; j<maxcols; j++)
  324. X**     if (!col_hidden[j])
  325. X**         break;
  326. X**     j--;
  327. X**     if (i>=maxcols)
  328. X**     error ("No hidden columns to show");
  329. X**     else {
  330. X**     Sprintf(line,"show %s:", coltoa(i));
  331. X**     Sprintf(line + strlen(line),"%s",coltoa(j));
  332. X**     linelim = strlen (line);
  333. X**     }
  334. X** }
  335. X** 
  336. X** void
  337. X** rowshow_op()
  338. X** {
  339. X**     register int i,j;
  340. X**     for (i=0; i<maxrows; i++)
  341. X**     if (row_hidden[i]) 
  342. X**         break;
  343. X**     for(j=i; j<maxrows; j++)
  344. X**     if (!row_hidden[j]) {
  345. X**         break;
  346. X**     }
  347. X**     j--;
  348. X** 
  349. X**     if (i>=maxrows)
  350. X**     error ("No hidden rows to show");
  351. X**     else {
  352. X**     Sprintf(line,"show %d:%d", i, j);
  353. X**         linelim = strlen (line);
  354. X**     }
  355. X** }
  356. X*/ 
  357. X
  358. X/*
  359. X * Given a row/column command letter, emit a small menu, then read a qualifier
  360. X * character for a row/column command and convert it to 'r' (row), 'c'
  361. X * (column), or 0 (unknown).  If ch is 'p', an extra qualifier 'm' is allowed.
  362. X */
  363. X
  364. X/* 
  365. X** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  366. X** Art Mulder Modified:  No Longer Used.  Jan 25/93
  367. X** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
  368. X** int
  369. X** get_rcqual (ch)
  370. X**     int ch;
  371. X** {
  372. X**     error ("%sow/column:  r: row  c: column%s",
  373. X**         (ch == 'i') ? "Insert r" :
  374. X**         (ch == 'a') ? "Append r" :
  375. X**         (ch == 'd') ? "Delete r" :
  376. X**         (ch == 'p') ? "Pull r" :
  377. X**         (ch == 'v') ? "Values r" :
  378. X**         (ch == 'z') ? "Zap r" :
  379. X**         (ch == 's') ? "Show r" : "R",
  380. X** 
  381. X**         (ch == 'p') ? "  m: merge" : "");
  382. X** 
  383. X**     switch (nmgetch())
  384. X**     {
  385. X**     case 'r':
  386. X**     case 'l':
  387. X**     case 'h':
  388. X**     case ctl('f'):
  389. X**     case ctl('b'):    return ('r');
  390. X** 
  391. X**     case 'c':
  392. X**     case 'j':
  393. X**     case 'k':
  394. X**     case ctl('p'):
  395. X**     case ctl('n'):    return ('c');
  396. X** 
  397. X**     case 'm':    return ((ch == 'p') ? 'm' : 0);
  398. X** 
  399. X**     case ESC:
  400. X**     case ctl('g'):    return (ESC);
  401. X** 
  402. X**     default:    return (0);
  403. X**     }
  404. X** 
  405. X** }
  406. X*/ 
  407. X
  408. Xvoid
  409. Xopenrow (rs)
  410. Xint    rs;
  411. X{
  412. X    register    r, c;
  413. X    struct ent    **tmprow, **pp;
  414. X
  415. X    if (rs > maxrow) maxrow = rs;
  416. X    if (maxrow >= maxrows - 1 || rs > maxrows - 1) {
  417. X    if (!growtbl(GROWROW, rs, 0))
  418. X        return;
  419. X    }
  420. X    /*
  421. X     * save the last active row+1, shift the rows downward, put the last
  422. X     * row in place of the first
  423. X     */
  424. X    tmprow = tbl[++maxrow];
  425. X    for (r = maxrow; r > rs; r--) {
  426. X    row_hidden[r] = row_hidden[r-1];
  427. X    tbl[r] = tbl[r-1];
  428. X    pp = ATBL(tbl, r, 0);
  429. X    for (c = 0; c < maxcols; c++, pp++)
  430. X        if (*pp)
  431. X            (*pp)->row = r;
  432. X    }
  433. X    tbl[r] = tmprow;    /* the last row was never used.... */
  434. X    FullUpdate++;
  435. X    modflg++;
  436. X}
  437. X
  438. X/* delete row r */
  439. Xvoid
  440. Xcloserow (r)
  441. Xregister r;
  442. X{
  443. X    register struct ent **pp;
  444. X    register c;
  445. X    struct ent    **tmprow;
  446. X
  447. X    if (r > maxrow) return;
  448. X
  449. X    /* save the row and empty it out */
  450. X    tmprow = tbl[r];
  451. X    pp = ATBL(tbl, r, 0);
  452. X    for (c=maxcol+1; --c>=0; pp++) {
  453. X    if (*pp)
  454. X    {    free_ent(*pp);
  455. X        *pp = (struct ent *)0;
  456. X    }
  457. X    }
  458. X
  459. X    /* move the rows, put the deleted, but now empty, row at the end */
  460. X    for (; r < maxrows - 1; r++) {
  461. X    row_hidden[r] = row_hidden[r+1];
  462. X    tbl[r] = tbl[r+1];
  463. X    pp = ATBL(tbl, r, 0);
  464. X    for (c = 0; c < maxcols; c++, pp++)
  465. X        if (*pp)
  466. X            (*pp)->row = r;
  467. X    }
  468. X    tbl[r] = tmprow;
  469. X
  470. X    maxrow--;
  471. X    FullUpdate++;
  472. X    modflg++;
  473. X}
  474. X
  475. Xvoid
  476. Xopencol (cs, numcol)
  477. Xint    cs;
  478. Xint    numcol;
  479. X{
  480. X    register r;
  481. X    register struct ent **pp;
  482. X    register c;
  483. X    register lim = maxcol-cs+1;
  484. X    int i;
  485. X
  486. X    if (cs > maxcol)
  487. X    maxcol = cs;
  488. X    maxcol += numcol;
  489. X
  490. X    if ((maxcol >= maxcols - 1) && !growtbl(GROWCOL, 0, maxcol))
  491. X        return;
  492. X
  493. X    for (i = maxcol; i > cs; i--) {
  494. X    fwidth[i] = fwidth[i-numcol];
  495. X    precision[i] = precision[i-numcol];
  496. X    realfmt[i] = realfmt[i-numcol];
  497. X    col_hidden[i] = col_hidden[i-numcol];
  498. X    }
  499. X    for (c = cs; c - cs < numcol; c++)
  500. X    {    fwidth[c] = DEFWIDTH;
  501. X    precision[c] =  DEFPREC;
  502. X    realfmt[c] = DEFREFMT;
  503. X    }
  504. X    
  505. X    for (r=0; r<=maxrow; r++) {
  506. X    pp = ATBL(tbl, r, maxcol);
  507. X    for (c=lim; --c>=0; pp--)
  508. X        if (pp[0] = pp[-numcol])
  509. X        pp[0]->col += numcol;
  510. X
  511. X    pp = ATBL(tbl, r, cs);
  512. X    for (c = cs; c - cs < numcol; c++, pp++)
  513. X        *pp = (struct ent *)0;
  514. X    }
  515. X    FullUpdate++;
  516. X    modflg++;
  517. X}
  518. X
  519. X/** void closecol (cs, numcol) **/
  520. Xvoid closecol (startcol, endcol)
  521. X/*----------------------------------------------------------------------
  522. X** Delete the cols from 'startcol' to 'endcol'.  (startcol must be
  523. X** <= endcol.)
  524. X*/
  525. X    int startcol,endcol;
  526. X{
  527. X    int cs = startcol;                /** Old var's **/
  528. X    int numcol = (endcol - startcol + 1);    /** Old var's **/
  529. X
  530. X    register r;
  531. X    register struct ent **pp;
  532. X    register struct ent *q;
  533. X    register c;
  534. X    register lim = maxcol-cs;
  535. X    int i;
  536. X    char buf[50];
  537. X
  538. X
  539. X/* Check for errors */
  540. X    if (endcol > maxcol) {
  541. X    error("Ending Column exceeds Max column, No Change.");
  542. X    return;
  543. X    }
  544. X    if (any_locked_cells(0, startcol, maxrow, endcol)) {
  545. X    error("Locked cells encountered. Nothing changed");
  546. X    return;
  547. X    }
  548. X
  549. X/* Clear the columns */
  550. X    flush_saved();
  551. X    erase_area(0, startcol, maxrow, endcol);
  552. X    sync_refs();
  553. X
  554. X/* clear then copy the block left */
  555. X    lim = maxcols - numcol - 1;         /* ?? */
  556. X    for (r=0; r<=maxrow; r++) {
  557. X    for (c = startcol; c <= endcol; c++)
  558. X        if (q = *ATBL(tbl, r, c))
  559. X            free_ent(q);
  560. X
  561. X/** NOT sure how this works **/
  562. X    pp = ATBL(tbl, r, startcol);
  563. X    for (c=startcol; c <= lim; c++, pp++)
  564. X    {   if (c > lim)
  565. X        *pp = (struct ent *)0;
  566. X        else
  567. X        if (pp[0] = pp[numcol])
  568. X        pp[0]->col -= numcol;
  569. X    }
  570. X
  571. X    c = numcol;
  572. X    for (; --c >= 0; pp++)        
  573. X        *pp = (struct ent *)0;
  574. X    }
  575. X
  576. X    for (i = cs; i < maxcols - numcol - 1; i++) {
  577. X    fwidth[i] = fwidth[i+numcol];
  578. X    precision[i] = precision[i+numcol];
  579. X    realfmt[i] = realfmt[i+numcol];
  580. X    col_hidden[i] = col_hidden[i+numcol];
  581. X    }
  582. X    for (; i < maxcols - 1; i++) {
  583. X    fwidth[i] = DEFWIDTH;
  584. X    precision[i] = DEFPREC;
  585. X    realfmt[i] = DEFREFMT;
  586. X    col_hidden[i] = FALSE;
  587. X    }
  588. X
  589. X    maxcol -= numcol;
  590. X    curcol = startcol;
  591. X    FullUpdate++;
  592. X    modflg++;
  593. X}
  594. X
  595. Xvoid
  596. Xdoend(rowinc, colinc)
  597. Xint rowinc, colinc;
  598. X{
  599. X    register struct ent *p;
  600. X    int r, c;
  601. X
  602. X    if (VALID_CELL(p, currow, curcol)) {
  603. X    r = currow + rowinc;
  604. X    c = curcol + colinc;
  605. X    if (r >= 0 && r < maxrows && 
  606. X        c >= 0 && c < maxcols &&
  607. X        !VALID_CELL(p, r, c)) {
  608. X        currow = r;
  609. X        curcol = c;
  610. X    }
  611. X    }
  612. X
  613. X    if (!VALID_CELL(p, currow, curcol)) {
  614. X        switch (rowinc) {
  615. X        case -1:
  616. X        while (!VALID_CELL(p, currow, curcol) && currow > 0)
  617. X        currow--;
  618. X        break;
  619. X        case  1:
  620. X        while (!VALID_CELL(p, currow, curcol) && currow < maxrows-1)
  621. X        currow++;
  622. X        break;
  623. X        case  0:
  624. X            switch (colinc) {
  625. X         case -1:
  626. X            while (!VALID_CELL(p, currow, curcol) && curcol > 0)
  627. X            curcol--;
  628. X            break;
  629. X         case  1:
  630. X            while (!VALID_CELL(p, currow, curcol) && curcol < maxcols-1)
  631. X            curcol++;
  632. X            break;
  633. X        }
  634. X            break;
  635. X        }
  636. X
  637. X    error ("");    /* clear line */
  638. X    return;
  639. X    }
  640. X
  641. X    switch (rowinc) {
  642. X    case -1:
  643. X    while (VALID_CELL(p, currow, curcol) && currow > 0)
  644. X        currow--;
  645. X    break;
  646. X    case  1:
  647. X    while (VALID_CELL(p, currow, curcol) && currow < maxrows-1)
  648. X        currow++;
  649. X    break;
  650. X    case  0:
  651. X    switch (colinc) {
  652. X    case -1:
  653. X        while (VALID_CELL(p, currow, curcol) && curcol > 0)
  654. X        curcol--;
  655. X        break;
  656. X    case  1:
  657. X        while (VALID_CELL(p, currow, curcol) && curcol < maxcols-1)
  658. X        curcol++;
  659. X        break;
  660. X    }
  661. X    break;
  662. X    }
  663. X    if (!VALID_CELL(p, currow, curcol)) {
  664. X        currow -= rowinc;
  665. X        curcol -= colinc;
  666. X    }
  667. X}
  668. X
  669. X/* Modified 9/17/90 THA to handle more formats */
  670. Xvoid
  671. Xdoformat(c1,c2,w,p,r)
  672. Xint c1,c2,w,p,r;
  673. X{
  674. X    register int i;
  675. X    int crows = 0;
  676. X    int ccols = c2;
  677. X
  678. X    if (c1 >= maxcols && !growtbl(GROWCOL, 0, c1)) c1 = maxcols-1 ;
  679. X    if (c2 >= maxcols && !growtbl(GROWCOL, 0, c2)) c2 = maxcols-1 ;
  680. X
  681. X    if (w > COLS - RESCOL - 2) {
  682. X    error("Format too large - Maximum = %d", COLS - RESCOL - 2);
  683. X    w = COLS-RESCOL-2;
  684. X    }
  685. X
  686. X    if (p > w) {
  687. X    error("Precision too large");
  688. X    p = w;
  689. X    }
  690. X
  691. X    checkbounds(&crows, &ccols);
  692. X    if (ccols < c2) {
  693. X    error("Format statement failed to create implied column %d", c2);
  694. X    return;
  695. X    }
  696. X
  697. X    for(i = c1; i<=c2; i++)
  698. X        fwidth[i] = w, precision[i] = p, realfmt[i] = r;
  699. X
  700. X    FullUpdate++;
  701. X    modflg++;
  702. X}
  703. X
  704. Xvoid
  705. Xprint_options(f)
  706. XFILE *f;
  707. X{
  708. X    if(
  709. X       autocalc &&
  710. X       propagation == 10 &&
  711. X       calc_order == BYROWS &&
  712. X       prescale == 1.0 &&
  713. X       !extfunc &&
  714. X       showcell &&
  715. X       showtop &&
  716. X       tbl_style == 0 &&
  717. X       craction == 0 &&
  718. X       rowlimit == -1 &&
  719. X       collimit == -1
  720. X      )
  721. X        return;        /* No reason to do this */
  722. X
  723. X    Fprintf(f, "set");
  724. X    if(!autocalc) 
  725. X    Fprintf(f," !autocalc");
  726. X    if(propagation != 10)
  727. X    Fprintf(f, " iterations = %d", propagation);
  728. X    if(calc_order != BYROWS )
  729. X    Fprintf(f, " bycols");
  730. X    if (prescale != 1.0)
  731. X    Fprintf(f, " prescale");
  732. X    if (extfunc)
  733. X    Fprintf(f, " extfun");
  734. X    if (!showcell)
  735. X    Fprintf(f, " !cellcur");
  736. X    if (!showtop)
  737. X    Fprintf(f, " !toprow");
  738. X    if (tbl_style)
  739. X    Fprintf(f, " tblstyle = %s", tbl_style == TBL ? "tbl" :
  740. X                    tbl_style == LATEX   ? "latex"   :
  741. X                    tbl_style == SLATEX  ? "slatex"  :
  742. X                    tbl_style == TEX     ? "tex"     : 
  743. X                    tbl_style == FRAME   ? "frame"   : "0" );
  744. X    if (craction)
  745. X    Fprintf(f, " craction = %d", craction);
  746. X    if (rowlimit >= 0)
  747. X    Fprintf(f, " rowlimit = %d", rowlimit);
  748. X    if (collimit >= 0)
  749. X    Fprintf(f, " collimit = %d", collimit);
  750. X    Fprintf(f, "\n");
  751. X}
  752. X
  753. Xvoid
  754. Xprintfile (fname, r0, c0, rn, cn)
  755. Xchar *fname;
  756. Xint r0, c0, rn, cn;
  757. X{
  758. X    FILE *f;
  759. X    static char *pline = NULL;        /* only malloc once, malloc is slow */
  760. X    static unsigned fbufs_allocated = 0;
  761. X    int plinelim;
  762. X    int pid;
  763. X    int fieldlen, nextcol;
  764. X    register row, col;
  765. X    register struct ent **pp;
  766. X
  767. X    if ((strcmp(fname, curfile) == 0) &&
  768. X    !yn_ask("Confirm that you want to destroy the data base: (y,n)")) {
  769. X    return;
  770. X    }
  771. X
  772. X    if (!pline && (pline = Malloc((unsigned)(FBUFLEN *
  773. X                    ++fbufs_allocated))) == (char *)NULL)
  774. X    {   error("Malloc failed in printfile()");
  775. X        return;
  776. X    }
  777. X
  778. X    if ((f = openout(fname, &pid)) == (FILE *)0)
  779. X    {    error ("Can't create file \"%s\"", fname);
  780. X    return;
  781. X    }
  782. X    for (row=r0;row<=rn; row++) {
  783. X    register c = 0;
  784. X
  785. X    if (row_hidden[row])
  786. X        continue;
  787. X
  788. X    pline[plinelim=0] = '\0';
  789. X    for (pp = ATBL(tbl, row, col=c0); col<=cn;
  790. X            pp += nextcol-col, col = nextcol, c += fieldlen) {
  791. X
  792. X        nextcol = col+1;
  793. X        if (col_hidden[col]) {
  794. X        fieldlen = 0;
  795. X        continue;
  796. X        }
  797. X
  798. X        fieldlen = fwidth[col];
  799. X        if (*pp) {
  800. X        char *s;
  801. X
  802. X        /* 
  803. X         * dynamically allocate pline, making sure we are not 
  804. X         * attempting to write 'out of bounds'.
  805. X         */
  806. X        while(c > (fbufs_allocated * FBUFLEN)) {
  807. X          if((pline = Realloc((char *)pline, 
  808. X                (unsigned)(FBUFLEN * ++fbufs_allocated)) )
  809. X             == NULL) {
  810. X            error ("Realloc failed in printfile()");
  811. X            return;
  812. X          }
  813. X        }          
  814. X        while (plinelim<c) pline[plinelim++] = ' ';
  815. X        plinelim = c;
  816. X        if ((*pp)->flags&is_valid) {
  817. X            while(plinelim + fwidth[col] > 
  818. X              (fbufs_allocated * FBUFLEN)) {
  819. X              if((pline = ((char *)Realloc((char *)pline, 
  820. X                    (unsigned)(FBUFLEN * ++fbufs_allocated))))
  821. X             == NULL) {
  822. X            error ("Realloc failed in printfile()");
  823. X            return;
  824. X              }
  825. X            }
  826. X            if ((*pp)->cellerror)
  827. X            Sprintf (pline+plinelim, "%*s",
  828. X                fwidth[col],
  829. X            ((*pp)->cellerror == CELLERROR ? "ERROR" : "INVALID"));
  830. X            else
  831. X            {
  832. X              if ((*pp)->format) {
  833. X                   char field[FBUFLEN];
  834. X            format ((*pp)->format, (*pp)->v, field,
  835. X                       sizeof(field));
  836. X            Sprintf (pline+plinelim, "%*s", fwidth[col],
  837. X                    field);
  838. X              } else {
  839. X                   char field[FBUFLEN];
  840. X            (void) engformat(realfmt[col], fwidth[col],
  841. X                                             precision[col], (*pp) -> v,
  842. X                                             field, sizeof(field));
  843. X            Sprintf (pline+plinelim, "%*s", fwidth[col],
  844. X                       field);
  845. X              }
  846. X            }
  847. X            plinelim += strlen (pline+plinelim);
  848. X        }
  849. X        if (s = (*pp)->label) {
  850. X            int slen;
  851. X            char *start, *last;
  852. X            register char *fp;
  853. X            struct ent *nc;
  854. X
  855. X            /*
  856. X             * Figure out if the label slops over to a blank field. A
  857. X             * string started with backslah is defining repition char
  858. X             */
  859. X            slen = strlen(s);
  860. X            if ( *s == '\\' && *(s+1)!= '\0' )
  861. X            slen = fwidth[col];
  862. X            while (slen > fieldlen && nextcol <= cn &&
  863. X                !((nc = lookat(row,nextcol))->flags & is_valid) &&
  864. X                !(nc->label)) {
  865. X            
  866. X                    if (!col_hidden[nextcol])
  867. X                 fieldlen += fwidth[nextcol];
  868. X
  869. X            nextcol++;
  870. X            }
  871. X            if (slen > fieldlen)
  872. X            slen = fieldlen;
  873. X            
  874. X            while(c + fieldlen + 2 > (fbufs_allocated * FBUFLEN)) {
  875. X              if((pline = ((char *)Realloc((char *)pline, 
  876. X                    (unsigned)(FBUFLEN * ++fbufs_allocated))))
  877. X             == NULL) {
  878. X            error ("Realloc failed in printfile()");
  879. X            return;
  880. X              }
  881. X            }          
  882. X
  883. X            /* Now justify and print */
  884. X            start = (*pp)->flags & is_leftflush ? pline + c
  885. X                    : pline + c + fieldlen - slen;
  886. X            if( (*pp)->flags & is_label )
  887. X            start = pline + (c + ((fwidth[col]>slen)?(fwidth[col]-slen)/2:0));
  888. X            last = pline + c + fieldlen;
  889. X            fp = plinelim < c ? pline + plinelim : pline + c;
  890. X            while (fp < start)
  891. X            *fp++ = ' ';
  892. X            if( *s == '\\' && *(s+1)!= '\0' ) {
  893. X            char *strt;
  894. X            strt = ++s;
  895. X
  896. X            while(slen--) {
  897. X                *fp++ = *s++; if( *s == '\0' ) s = strt;
  898. X            }
  899. X            }
  900. X            else
  901. X            while (slen--)
  902. X            *fp++ = *s++;
  903. X
  904. X            if (!((*pp)->flags & is_valid) || fieldlen != fwidth[col])
  905. X            while(fp < last)
  906. X                *fp++ = ' ';
  907. X            if (plinelim < fp - pline)
  908. X            plinelim = fp - pline;
  909. X        }
  910. X        }
  911. X    }
  912. X    pline[plinelim++] = '\n';
  913. X    pline[plinelim] = '\0';
  914. X    Fputs (pline, f);
  915. X    }
  916. X
  917. X    closeout(f, pid);
  918. X}
  919. X
  920. Xvoid
  921. Xtblprintfile (fname, r0, c0, rn, cn)
  922. Xchar *fname;
  923. Xint r0, c0, rn, cn;
  924. X{
  925. X    FILE *f;
  926. X    int pid;
  927. X    register row, col;
  928. X    register struct ent **pp;
  929. X    char coldelim = DEFCOLDELIM;
  930. X
  931. X    if ((strcmp(fname, curfile) == 0) &&
  932. X    !yn_ask("Confirm that you want to destroy the data base: (y,n)"))
  933. X        return;
  934. X
  935. X    if ((f = openout(fname, &pid)) == (FILE *)0)
  936. X    {    error ("Can't create file \"%s\"", fname);
  937. X    return;
  938. X    }
  939. X
  940. X    if ( tbl_style == TBL ) {
  941. X    fprintf(f,".\\\" ** %s spreadsheet output \n.TS\n",progname);
  942. X    fprintf(f,"tab(%c);\n",coldelim);
  943. X    for (col=c0;col<=cn; col++) fprintf(f," n");
  944. X    fprintf(f, ".\n");
  945. X    }
  946. X    else if ( tbl_style == LATEX ) {
  947. X    fprintf(f,"%% ** %s spreadsheet output\n\\begin{tabular}{",progname);
  948. X    for (col=c0;col<=cn; col++) fprintf(f,"c");
  949. X    fprintf(f, "}\n");
  950. X    coldelim = '&';
  951. X    }
  952. X    else if ( tbl_style == SLATEX ) {
  953. X    fprintf(f,"%% ** %s spreadsheet output\n!begin<tabular><",progname);
  954. X    for (col=c0;col<=cn; col++) fprintf(f,"c");
  955. X    fprintf(f, ">\n");
  956. X    coldelim = '&';
  957. X    }
  958. X    else if ( tbl_style == TEX ) {
  959. X    fprintf(f,"{\t%% ** %s spreadsheet output\n\\settabs %d \\columns\n",
  960. X        progname, cn-c0+1);
  961. X    coldelim = '&';
  962. X    }
  963. X    else if ( tbl_style == FRAME ) {
  964. X      fprintf(f,
  965. X    "<MIFFile 3.00> # generated by the sc spreadsheet calculator\n ");
  966. X      fprintf(f,"<Tbls\n");
  967. X      fprintf(f," <Tbl \n");
  968. X      fprintf(f,"  <TblID 1> # This table's ID is 1\n");
  969. X      fprintf(f,"  <TblFormat \n");
  970. X      fprintf(f,"   <TblTag `Format A'> # Table Format Catalog\n");
  971. X      fprintf(f,"  > # end of TblFormat\n");
  972. X      fprintf(f,"  <TblNumColumns %d> # Has %d columns\n",cn-c0+1,cn-c0+1);
  973. X      fprintf(f,"  <TblTitleContent\n");
  974. X      fprintf(f,"   <Para\n");
  975. X      fprintf(f,"    <PgfTag `TableTitle'> # Forces lookup in Paragraph Format Catalog\n");
  976. X      fprintf(f,"    <ParaLine\n");
  977. X      fprintf(f,"     <String `%s'>\n",fname);
  978. X      fprintf(f,"    > # end of ParaLine\n");
  979. X      fprintf(f,"   > # end of Para\n");
  980. X      fprintf(f,"  > # end of TblTitleContent\n");
  981. X      fprintf(f,"  <TblH # The heading\n");
  982. X      fprintf(f,"   <Row # The heading row\n");
  983. X      for (col=c0; col <= cn; col++) {
  984. X          fprintf(f,"    <Cell <CellContent <Para # Cell in column \n");
  985. X          fprintf(f,
  986. X        "       <PgfTag `CellHeading'> # in Paragraph Format Catal og\n");
  987. X          fprintf(f,"       <ParaLine <String `%c'>>\n",'A'+col);
  988. X          fprintf(f,"    >>> # end of Cell\n");
  989. X      }
  990. X      fprintf(f,"   > # end of Row\n");
  991. X      fprintf(f,"  > # end of TblH\n");
  992. X      fprintf(f,"  <TblBody # The body\n");
  993. X    }    /* tbl_style == Frame */
  994. X
  995. X
  996. X    for (row=r0; row<=rn; row++) {
  997. X    if ( tbl_style == TEX )
  998. X        Fprintf (f, "\\+");
  999. X        else if ( tbl_style == FRAME ) {
  1000. X            fprintf(f,"   <Row # The next body row\n");
  1001. X        }
  1002. X
  1003. X    for (pp = ATBL(tbl, row, col=c0); col<=cn; col++, pp++) {
  1004. X            if ( tbl_style == FRAME ) {
  1005. X          fprintf(f,"    <Cell <CellContent <Para\n");
  1006. X          fprintf(f,
  1007. X        "       <PgfTag `CellBody'> # in Paragraph Format Cata log\n");
  1008. X          fprintf(f,"       <ParaLine <String `");
  1009. X        }
  1010. X        if (*pp) {
  1011. X        char *s;
  1012. X        if ((*pp)->flags&is_valid) {
  1013. X            if ((*pp)->cellerror) {
  1014. X            Fprintf (f, "%*s",
  1015. X                    fwidth[col],
  1016. X            ((*pp)->cellerror == CELLERROR ? "ERROR" : "INVALID"));
  1017. X            }
  1018. X            else
  1019. X            if ((*pp)->format) {
  1020. X                char field[FBUFLEN];
  1021. X            
  1022. X            (void) format ((*pp)->format, (*pp)->v, field,
  1023. X                       sizeof(field));
  1024. X            unspecial (f, field, coldelim);
  1025. X            } else {
  1026. X                char field[FBUFLEN];
  1027. X                        (void) engformat(realfmt[col], fwidth[col],
  1028. X                                             precision[col], (*pp) -> v,
  1029. X                                             field, sizeof(field));
  1030. X            unspecial (f, field, coldelim);
  1031. X            }
  1032. X        }
  1033. X        if (s = (*pp)->label) {
  1034. X                unspecial (f, s, coldelim);
  1035. X        }
  1036. X        }
  1037. X            if (tbl_style == FRAME) {
  1038. X                fprintf(f, "'>>\n");
  1039. X                fprintf(f,"    >>> # end of Cell\n");
  1040. X            }
  1041. X        if ( col < cn )
  1042. X        if (tbl_style != FRAME)
  1043. X            Fprintf(f,"%c", coldelim);
  1044. X    }
  1045. X    if ( tbl_style == LATEX ) {
  1046. X        if ( row < rn ) Fprintf (f, "\\\\");
  1047. X    }
  1048. X    else if ( tbl_style == SLATEX ) {
  1049. X        if ( row < rn ) Fprintf (f, "!!");
  1050. X    }
  1051. X    else if ( tbl_style == TEX ) {
  1052. X        Fprintf (f, "\\cr");
  1053. X    }
  1054. X    else if ( tbl_style == FRAME ) {
  1055. X            fprintf(f,"   > # end of Row\n");
  1056. X        }
  1057. X    Fprintf (f,"\n");
  1058. X    }
  1059. X
  1060. X    if ( tbl_style == TBL )
  1061. X      Fprintf (f,
  1062. X    ".TE\n.\\\" ** end of %s spreadsheet output\n", progname);
  1063. X    else if ( tbl_style == LATEX )
  1064. X      Fprintf (f,
  1065. X    "\\end{tabular}\n%% ** end of %s spreadsheet output\n", progname);
  1066. X    else if ( tbl_style == SLATEX )
  1067. X      Fprintf (f,
  1068. X    "!end<tabular>\n%% ** end of %s spreadsheet output\n", progname);
  1069. X    else if ( tbl_style == TEX )
  1070. X      Fprintf (f,"}\n%% ** end of %s spreadsheet output\n", progname);
  1071. X    else if ( tbl_style == FRAME ) {
  1072. X      fprintf(f,"  > # end of TblBody\n");
  1073. X      fprintf(f," ># end of Tbl\n");
  1074. X      fprintf(f,"> # end of Tbls\n");
  1075. X      fprintf(f,"<TextFlow <Para \n");
  1076. X      fprintf(f,"  <PgfTag Body> \n");
  1077. X      fprintf(f,"  <ParaLine <ATbl 1>> # Reference to table ID 1\n");
  1078. X      fprintf(f,">>\n");
  1079. X    }
  1080. X
  1081. X    closeout(f, pid);
  1082. X}
  1083. X
  1084. X/* unspecial (backquote) things that are special chars in a table */
  1085. Xvoid
  1086. Xunspecial(f, str, delim)
  1087. XFILE    *f;
  1088. Xchar    *str;
  1089. Xint    delim;
  1090. X{
  1091. X    if( *str == '\\' ) str++; /* delete wheeling string operator, OK? */
  1092. X    while (*str)
  1093. X    {    if (((tbl_style == LATEX) || (tbl_style == SLATEX) ||
  1094. X            (tbl_style == TEX)) &&
  1095. X            ((*str == delim) || (*str == '$') || (*str == '#') ||
  1096. X            (*str == '%') || (*str == '{') || (*str == '}') ||
  1097. X            (*str == '[') || (*str == ']') || (*str == '&')))
  1098. X            putc('\\', f);
  1099. X        putc(*str, f);
  1100. X        str++;
  1101. X    }
  1102. X}
  1103. X
  1104. Xstruct enode *
  1105. Xcopye (e, Rdelta, Cdelta)
  1106. Xregister struct enode *e;
  1107. Xint Rdelta, Cdelta;
  1108. X{
  1109. X    register struct enode *ret;
  1110. X
  1111. X    if (e == (struct enode *)0) {
  1112. X        ret = (struct enode *)0;
  1113. X    } else if (e->op & REDUCE) {
  1114. X    int newrow, newcol;
  1115. X    if (freeenodes)
  1116. X    {    ret = freeenodes;
  1117. X        freeenodes = ret->e.o.left;
  1118. X    }
  1119. X    else
  1120. X        ret = (struct enode *) Malloc((unsigned) sizeof (struct enode));
  1121. X    ret->op = e->op;
  1122. X    newrow=e->e.r.left.vf & FIX_ROW ? e->e.r.left.vp->row :
  1123. X                      e->e.r.left.vp->row+Rdelta;
  1124. X    newcol=e->e.r.left.vf & FIX_COL ? e->e.r.left.vp->col :
  1125. X                      e->e.r.left.vp->col+Cdelta;
  1126. X    ret->e.r.left.vp = lookat (newrow, newcol);
  1127. X    ret->e.r.left.vf = e->e.r.left.vf;
  1128. X    newrow=e->e.r.right.vf & FIX_ROW ? e->e.r.right.vp->row :
  1129. X                       e->e.r.right.vp->row+Rdelta;
  1130. X    newcol=e->e.r.right.vf & FIX_COL ? e->e.r.right.vp->col :
  1131. X                       e->e.r.right.vp->col+Cdelta;
  1132. X    ret->e.r.right.vp = lookat (newrow, newcol);
  1133. X    ret->e.r.right.vf = e->e.r.right.vf;
  1134. X    } else {
  1135. X    if (freeenodes)
  1136. X    {    ret = freeenodes;
  1137. X        freeenodes = ret->e.o.left;
  1138. X    }
  1139. X    else
  1140. X        ret = (struct enode *) Malloc((unsigned) sizeof (struct enode));
  1141. X    ret->op = e->op;
  1142. X    switch (ret->op) {
  1143. X    case 'v':
  1144. X        {
  1145. X            int newrow, newcol;
  1146. X            newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row :
  1147. X                         e->e.v.vp->row+Rdelta;
  1148. X            newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col :
  1149. X                         e->e.v.vp->col+Cdelta;
  1150. X            ret->e.v.vp = lookat (newrow, newcol);
  1151. X            ret->e.v.vf = e->e.v.vf;
  1152. X            break;
  1153. X        }
  1154. X    case 'k':
  1155. X        ret->e.k = e->e.k;
  1156. X        break;
  1157. X    case 'f':
  1158. X        ret->e.o.right = copye (e->e.o.right,0,0);
  1159. X        ret->e.o.left = (struct enode *)0;
  1160. X         break;
  1161. X    case '$':
  1162. X        ret->e.s = Malloc((unsigned) strlen(e->e.s)+1);
  1163. X        Strcpy(ret->e.s, e->e.s);
  1164. X        break;
  1165. X    default:
  1166. X        ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  1167. X        ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  1168. X        break;
  1169. X    }
  1170. X    }
  1171. X    return ret;
  1172. X}
  1173. X
  1174. X/*
  1175. X * sync_refs and syncref are used to remove references to
  1176. X * deleted struct ents.  Note that the deleted structure must still
  1177. X * be hanging around before the call, but not referenced by an entry
  1178. X * in tbl.  Thus the free_ent calls in sc.c
  1179. X */
  1180. Xvoid
  1181. Xsync_refs ()
  1182. X{
  1183. X    register i,j;
  1184. X    register struct ent *p;
  1185. X    sync_ranges();
  1186. X    for (i=0; i<=maxrow; i++)
  1187. X    for (j=0; j<=maxcol; j++)
  1188. X        if ((p = *ATBL(tbl, i, j)) && p->expr)
  1189. X        syncref(p->expr);
  1190. X}
  1191. X
  1192. Xvoid
  1193. Xsyncref(e)
  1194. Xregister struct enode *e;
  1195. X{
  1196. X    if (e == (struct enode *)0)
  1197. X    return;
  1198. X    else if (e->op & REDUCE) {
  1199. X     e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col);
  1200. X     e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col);
  1201. X    } else {
  1202. X    switch (e->op) {
  1203. X    case 'v':
  1204. X        e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col);
  1205. X        break;
  1206. X    case 'k':
  1207. X        break;
  1208. X    case '$':
  1209. X        break;
  1210. X    default:
  1211. X        syncref(e->e.o.right);
  1212. X        syncref(e->e.o.left);
  1213. X        break;
  1214. X    }
  1215. X    }
  1216. X}
  1217. X
  1218. Xvoid hiderow(startrow,endrow)
  1219. X/*----------------------------------------------------------------------
  1220. X** Mark the rows from 'startrow' to 'endrow' (inclusive) as hidden.
  1221. X*/
  1222. X    register int startrow,endrow;
  1223. X{
  1224. X    currow = startrow;
  1225. X
  1226. X    if (startrow < 0 || startrow > endrow) {
  1227. X    error ("Invalid range");
  1228. X    return;
  1229. X    }
  1230. X    if (endrow >= maxrows-1) {
  1231. X    if (!growtbl(GROWROW, (endrow - startrow +1), 0)) {
  1232. X        error("You can't hide the last row");
  1233. X        return;
  1234. X    }
  1235. X    }
  1236. X    FullUpdate++;
  1237. X    modflg++;
  1238. X    while (startrow <= endrow)
  1239. X    row_hidden[startrow++] = 1;
  1240. X}
  1241. X
  1242. Xvoid hidecol(startcol,endcol)
  1243. X/*----------------------------------------------------------------------
  1244. X** Mark the cols from 'startcol' to 'endcol' (inclusive) as hidden.
  1245. X*/
  1246. X    register int startcol,endcol;
  1247. X{
  1248. X    curcol = startcol;
  1249. X
  1250. X    if (startcol < 0 || startcol > endcol) {
  1251. X    error ("Invalid range");
  1252. X    return;
  1253. X    }
  1254. X    if (endcol >= maxcols-1) {
  1255. X    if ((endcol >= ABSMAXCOLS) ||
  1256. X            !growtbl(GROWCOL, 0, (endcol-startcol +1))) {
  1257. X        error("You can't hide the last col");
  1258. X        return;
  1259. X    }
  1260. X    }
  1261. X    FullUpdate++;
  1262. X    modflg++;
  1263. X    while (startcol <= endcol)
  1264. X    col_hidden[startcol++] = TRUE;
  1265. X}
  1266. X
  1267. X/* mark a row as not-hidden */
  1268. Xvoid
  1269. Xshowrow(r1, r2)
  1270. Xint r1, r2;
  1271. X{
  1272. X    if (r1 < 0 || r1 > r2) {
  1273. X    error ("Invalid range");
  1274. X    return;
  1275. X    }
  1276. X    if (r2 > maxrows-1) {
  1277. X    r2 = maxrows-1;
  1278. X    }
  1279. X    FullUpdate++;
  1280. X    modflg++;
  1281. X    while (r1 <= r2)
  1282. X    row_hidden[r1++] = 0;
  1283. X}
  1284. X
  1285. X/* mark a column as not-hidden */
  1286. Xvoid
  1287. Xshowcol(c1, c2)
  1288. Xint c1, c2;
  1289. X{
  1290. X    if (c1 < 0 || c1 > c2) {
  1291. X    error ("Invalid range");
  1292. X    return;
  1293. X    }
  1294. X    if (c2 > maxcols-1) {
  1295. X    c2 = maxcols-1;
  1296. X    }
  1297. X    FullUpdate++;
  1298. X    modflg++;
  1299. X    while (c1 <= c2)
  1300. X    col_hidden[c1++] = FALSE;
  1301. X}
  1302. X
  1303. X/* Open the output file, setting up a pipe if needed */
  1304. XFILE *
  1305. Xopenout(fname, rpid)
  1306. Xchar *fname;
  1307. Xint *rpid;
  1308. X{
  1309. X    int pipefd[2];
  1310. X    int pid;
  1311. X    FILE *f;
  1312. X    char *efname;
  1313. X
  1314. X    while (*fname && (*fname == ' '))  /* Skip leading blanks */
  1315. X    fname++;
  1316. X
  1317. X    if (*fname != '|') {        /* Open file if not pipe */
  1318. X    *rpid = 0;
  1319. X    
  1320. X    efname = findhome(fname);
  1321. X#ifdef DOBACKUPS
  1322. X    if (!backup_file(efname) &&
  1323. X        (yn_ask("Could not create backup copy, Save anyhow?: (y,n)") != 1))
  1324. X        return(0);
  1325. X#endif
  1326. X    return(fopen(efname, "w"));
  1327. X    }
  1328. X
  1329. X#if defined(MSDOS)
  1330. X    error("Piping not available under MS-DOS\n");
  1331. X    return(0);
  1332. X#else
  1333. X    fname++;                /* Skip | */
  1334. X    if ( pipe (pipefd) < 0) {
  1335. X    error("Can't make pipe to child");
  1336. X    *rpid = 0;
  1337. X    return(0);
  1338. X    }
  1339. X
  1340. X    deraw();
  1341. X#ifdef VMS
  1342. X    fprintf(stderr, "No child tasks available yet under VMS--sorry\n");
  1343. X#else /* not VMS */
  1344. X
  1345. X    if ((pid=fork()) == 0)              /* if child  */
  1346. X    {
  1347. X    Close (0);              /* close stdin */
  1348. X    Close (pipefd[1]);
  1349. X    Dup (pipefd[0]);          /* connect to pipe input */
  1350. X    Signal (SIGINT, SIG_DFL);      /* reset */
  1351. X    Execl ("/bin/sh", "sh", "-c", fname, 0);
  1352. X    exit (-127);
  1353. X    }
  1354. X    else                  /* else parent */
  1355. X    {
  1356. X    *rpid = pid;
  1357. X    if ((f = fdopen (pipefd[1], "w")) == (FILE *)0)
  1358. X    {
  1359. X        Kill (pid, -9);
  1360. X        error ("Can't fdopen output");
  1361. X        Close (pipefd[1]);
  1362. X        *rpid = 0;
  1363. X        return(0);
  1364. X    }
  1365. X    }
  1366. X#endif /* VMS */
  1367. X    return(f);
  1368. X#endif /* MSDOS */
  1369. X}
  1370. X
  1371. X/* close a file opened by openout(), if process wait for return */
  1372. Xvoid
  1373. Xcloseout(f, pid)
  1374. XFILE *f;
  1375. Xint pid;
  1376. X{
  1377. X    int temp;
  1378. X
  1379. X    Fclose (f);
  1380. X#if !defined(MSDOS)
  1381. X    if (pid) {
  1382. X         while (pid != wait(&temp)) /**/;
  1383. X     Printf("Press RETURN to continue ");
  1384. X     Fflush(stdout);
  1385. X     (void) nmgetch();
  1386. X     goraw();
  1387. X    }
  1388. X#endif /* MSDOS */
  1389. X}
  1390. X
  1391. Xvoid
  1392. Xcopyent(n,p,dr,dc)
  1393. X        register struct ent *n, *p;
  1394. X        int dr, dc;
  1395. X{
  1396. X    if(!n||!p){error("internal error");return;}
  1397. X    n -> v = p -> v;
  1398. X    n -> flags = p -> flags;
  1399. X    n -> expr = copye (p -> expr, dr, dc);
  1400. X    n -> label = (char *)0;
  1401. X    if (p -> label) {
  1402. X    n -> label = Malloc((unsigned) (strlen (p -> label) + 1));
  1403. X    Strcpy (n -> label, p -> label);
  1404. X    }
  1405. X    n -> format = 0;
  1406. X    if (p -> format) {
  1407. X        n -> format = Malloc((unsigned) (strlen (p -> format) + 1));
  1408. X    Strcpy (n -> format, p -> format);
  1409. X    }
  1410. X}
  1411. X
  1412. Xvoid
  1413. Xwrite_fd (f, r0, c0, rn, cn)
  1414. Xregister FILE *f;
  1415. Xint r0, c0, rn, cn;
  1416. X{
  1417. X    register struct ent **pp;
  1418. X    register r, c;
  1419. X    extern char *v_name();
  1420. X
  1421. X    Fprintf (f, "# This data file was generated by the Spreadsheet ");
  1422. X    Fprintf (f, "Calculator.\n");
  1423. X    Fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
  1424. X    print_options(f);
  1425. X    for (c=0; c<maxcols; c++)
  1426. X    if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC || realfmt[c] != DEFREFMT )
  1427. X        Fprintf (f, "format %s %d %d %d\n",coltoa(c),fwidth[c],precision[c],realfmt[c]);
  1428. X    for (c=c0; c<cn; c++) {
  1429. X        if (col_hidden[c]) {
  1430. X            Fprintf(f, "hide %s\n", coltoa(c));
  1431. X        }
  1432. X    }
  1433. X    for (r=r0; r<=rn; r++) {
  1434. X    if (row_hidden[r]) {
  1435. X        Fprintf(f, "hide %d\n", r);
  1436. X    }
  1437. X    }
  1438. X
  1439. X    write_range(f);
  1440. X
  1441. X    if (mdir) 
  1442. X        Fprintf(f, "mdir \"%s\"\n", mdir);
  1443. X    for (r=r0; r<=rn; r++) {
  1444. X    pp = ATBL(tbl, r, c0);
  1445. X    for (c=c0; c<=cn; c++, pp++)
  1446. X        if (*pp) {
  1447. X        if ((*pp)->label) {
  1448. X            edits(r,c);
  1449. X            Fprintf(f, "%s\n",line);
  1450. X        }
  1451. X        if ((*pp)->flags&is_valid) {
  1452. X            editv (r, c);
  1453. X            Fprintf (f, "%s\n",line);
  1454. X        }
  1455. X        if ((*pp)->format) {
  1456. X            editfmt (r, c);
  1457. X            Fprintf (f, "%s\n",line);
  1458. X        }
  1459. X        if ((*pp)->flags&is_locked)
  1460. X            Fprintf(f, "lock %s%d\n", coltoa((*pp)->col),
  1461. X                             (*pp)->row) ;
  1462. X        }
  1463. X    }
  1464. X    if (rndinfinity)
  1465. X    fprintf(f, "set rndinfinity\n");
  1466. X    fprintf(f, "goto %s\n", v_name( currow, curcol ) );
  1467. X}
  1468. X
  1469. Xint
  1470. Xwritefile (fname, r0, c0, rn, cn)
  1471. Xchar *fname;
  1472. Xint r0, c0, rn, cn;
  1473. X{
  1474. X    register FILE *f;
  1475. X    char save[PATHLEN];
  1476. X    int pid;
  1477. X
  1478. X#if !defined(VMS) && !defined(MSDOS) && defined(CRYPT_PATH)
  1479. X    if (Crypt) {
  1480. X    return (cwritefile(fname, r0, c0, rn, cn));
  1481. X    }
  1482. X#endif /* VMS */
  1483. X
  1484. X    if (*fname == '\0') fname = curfile;
  1485. X
  1486. X    Strcpy(save,fname);
  1487. X
  1488. X    if ((f= openout(fname, &pid)) == (FILE *)0)
  1489. X    {    error ("Can't create file \"%s\"", fname);
  1490. X    return (-1);
  1491. X    }
  1492. X
  1493. X    write_fd(f, r0, c0, rn, cn);
  1494. X    
  1495. X    closeout(f, pid);
  1496. X
  1497. X    if (!pid) {
  1498. X        Strcpy(curfile, save);
  1499. X        modflg = 0;
  1500. X        error("File \"%s\" written.",curfile);
  1501. X    }
  1502. X
  1503. X    return (0);
  1504. X}
  1505. X
  1506. Xvoid
  1507. Xreadfile (fname,eraseflg)
  1508. Xchar *fname;
  1509. Xint eraseflg;
  1510. X{
  1511. X    register FILE *f;
  1512. X    char save[PATHLEN];
  1513. X    int tempautolabel;
  1514. X
  1515. X    tempautolabel = autolabel;        /* turn off auto label when */
  1516. X    autolabel = 0;            /* when reading a file  */
  1517. X
  1518. X    if (*fname == '*' && mdir) { 
  1519. X       Strcpy(save, mdir);
  1520. X       *fname = '/';
  1521. X       Strcat(save, fname);
  1522. X    } else {
  1523. X        if (*fname == '\0')
  1524. X        fname = curfile;
  1525. X        Strcpy(save,fname);
  1526. X    }
  1527. X
  1528. X#if !defined(VMS) && !defined(MSDOS) && defined(CRYPT_PATH)
  1529. X    if (Crypt)  {
  1530. X    creadfile(save, eraseflg);
  1531. X    return;
  1532. X    }
  1533. X#endif /* VMS */
  1534. X
  1535. X    if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
  1536. X
  1537. X    if ((f = fopen(findhome(save), "r")) == (FILE *)0)
  1538. X    {    error ("Can't read file \"%s\"", save);
  1539. X    return;
  1540. X    }
  1541. X
  1542. X    if (eraseflg) erasedb ();
  1543. X
  1544. X    loading++;
  1545. X    while (fgets(line, sizeof(line), f)) {
  1546. X    linelim = 0;
  1547. X    if (line[0] != '#') Yyparse ();
  1548. X    }
  1549. X    --loading;
  1550. X    Fclose (f);
  1551. X    linelim = -1;
  1552. X    modflg++;
  1553. X    if (eraseflg) {
  1554. X    Strcpy(curfile,save);
  1555. X    modflg = 0;
  1556. X    }
  1557. X    autolabel = tempautolabel;
  1558. X    EvalAll();
  1559. X}
  1560. X
  1561. X/* erase the database (tbl, etc.) */
  1562. Xvoid
  1563. Xerasedb ()
  1564. X{
  1565. X    register r, c;
  1566. X    for (c = 0; c<=maxcol; c++) {
  1567. X    fwidth[c] = DEFWIDTH;
  1568. X    precision[c] = DEFPREC;
  1569. X    realfmt[c] = DEFREFMT;
  1570. X    }
  1571. X
  1572. X    for (r = 0; r<=maxrow; r++) {
  1573. X    register struct ent **pp = ATBL(tbl, r, 0);
  1574. X    for (c=0; c++<=maxcol; pp++)
  1575. X        if (*pp) {
  1576. X        if ((*pp)->expr)  efree ((*pp) -> expr);
  1577. X        if ((*pp)->label) Free ((char *)((*pp) -> label));
  1578. X        (*pp)->next = freeents;    /* save [struct ent] for reuse */
  1579. X        freeents = *pp;
  1580. X        *pp = (struct ent *)0;
  1581. X        }
  1582. X    }
  1583. X    maxrow = 0;
  1584. X    maxcol = 0;
  1585. X    clean_range();
  1586. X    FullUpdate++;
  1587. X}
  1588. X
  1589. X/* moves curcol back one displayed column */
  1590. Xvoid
  1591. Xbackcol(arg)
  1592. X    int arg;
  1593. X{
  1594. X    while (--arg>=0) {
  1595. X    if (curcol)
  1596. X        curcol--;
  1597. X    else
  1598. X        {error ("At column A"); break;}
  1599. X    while(col_hidden[curcol] && curcol)
  1600. X        curcol--;
  1601. X    }
  1602. X}
  1603. X
  1604. X/* moves curcol forward one displayed column */
  1605. Xvoid
  1606. Xforwcol(arg)
  1607. X    int arg;
  1608. X{
  1609. X    while (--arg>=0) {
  1610. X    if (curcol < maxcols - 1)
  1611. X        curcol++;
  1612. X    else
  1613. X    if (!growtbl(GROWCOL, 0, arg))    /* get as much as needed */
  1614. X        break;
  1615. X    else
  1616. X        curcol++;
  1617. X    while(col_hidden[curcol]&&(curcol<maxcols-1))
  1618. X        curcol++;
  1619. X    }
  1620. X}
  1621. X
  1622. X/* moves currow forward one displayed row */
  1623. Xvoid
  1624. Xforwrow(arg)
  1625. X    int arg;
  1626. X{
  1627. X    while (--arg>=0) {
  1628. X    if (currow < maxrows - 1)
  1629. X        currow++;
  1630. X    else
  1631. X    if (!growtbl(GROWROW, arg, 0))    /* get as much as needed */
  1632. X        break;
  1633. X    else
  1634. X        currow++;
  1635. X    while (row_hidden[currow]&&(currow<maxrows-1))
  1636. X        currow++;
  1637. X    }
  1638. X}
  1639. X
  1640. X/* moves currow backward one displayed row */
  1641. Xvoid
  1642. Xbackrow(arg)
  1643. X    int arg;
  1644. X{
  1645. X    while (--arg>=0) {
  1646. X    if (currow)
  1647. X        currow--;
  1648. X    else
  1649. X        {error ("At row zero"); break;}
  1650. X    while (row_hidden[currow] && currow)
  1651. X        currow--;
  1652. X    }
  1653. X}
  1654. X
  1655. X
  1656. X/*
  1657. X * Show a cell's label string or expression value.  May overwrite value if
  1658. X * there is one already displayed in the cell.  Created from old code in
  1659. X * update(), copied with minimal changes.
  1660. X */
  1661. X
  1662. Xvoid
  1663. Xshowstring (string, dirflush, hasvalue, row, col, nextcolp, mxcol, fieldlenp, r, c)
  1664. X    char *string;    /* to display */
  1665. X    int dirflush;    /* or rightflush or centered */
  1666. X    int hasvalue;    /* is there a numeric value? */
  1667. X    int row, col;    /* spreadsheet location */
  1668. X    int *nextcolp;    /* value returned through it */
  1669. X    int mxcol;        /* last column displayed? */
  1670. X    int *fieldlenp;    /* value returned through it */
  1671. X    int r, c;        /* screen row and column */
  1672. X{
  1673. X    register int nextcol  = *nextcolp;
  1674. X    register int fieldlen = *fieldlenp;
  1675. X
  1676. X    char field[FBUFLEN];
  1677. X    int  slen;
  1678. X    char *start, *last;
  1679. X    register char *fp;
  1680. X    struct ent *nc;
  1681. X
  1682. X    /* This figures out if the label is allowed to
  1683. X       slop over into the next blank field */
  1684. X
  1685. X    slen = strlen (string);
  1686. X    if( *string == '\\' && *(string+1)!= '\0' )
  1687. X    slen = fwidth[col];
  1688. X    while ((slen > fieldlen) && (nextcol <= mxcol) &&
  1689. X       !((nc = lookat (row, nextcol)) -> flags & is_valid) &&
  1690. X       !(nc->label)) {
  1691. X
  1692. X    if (! col_hidden [nextcol])
  1693. X        fieldlen += fwidth [nextcol];
  1694. X
  1695. X    nextcol++;
  1696. X    }
  1697. X    if (slen > fieldlen)
  1698. X    slen = fieldlen;
  1699. X
  1700. X    /* Now justify and print */
  1701. X    start = (dirflush&is_leftflush) ? field : field + fieldlen - slen;
  1702. X    if( dirflush & is_label )
  1703. X    start = field + ((slen<fwidth[col])?(fieldlen-slen)/2:0);
  1704. X    last = field+fieldlen;
  1705. X    fp = field;
  1706. X    while (fp < start)
  1707. X    *fp++ = ' ';
  1708. X    if( *string == '\\'  && *(string+1)!= '\0') {
  1709. X    char *strt;
  1710. X    strt = ++string;
  1711. X
  1712. X    while(slen--) {
  1713. X        *fp++ = *string++;
  1714. X        if( *string == '\0' )
  1715. X            string = strt;
  1716. X    }
  1717. X    }
  1718. X    else
  1719. X    while (slen--)
  1720. X    *fp++ = *string++;
  1721. X
  1722. X    if ((! hasvalue) || fieldlen != fwidth[col]) 
  1723. X    while (fp < last)
  1724. X        *fp++ = ' ';
  1725. X    *fp = '\0';
  1726. X#ifdef VMS
  1727. X    mvaddstr(r, c, field);    /* this is a macro */
  1728. X#else
  1729. X    (void) mvaddstr(r, c, field);
  1730. X#endif
  1731. X
  1732. X    *nextcolp  = nextcol;
  1733. X    *fieldlenp = fieldlen;
  1734. X}
  1735. X
  1736. Xint
  1737. Xetype(e)
  1738. Xregister struct enode *e;
  1739. X{
  1740. X    if (e == (struct enode *)0)
  1741. X    return NUM;
  1742. X    switch (e->op) {
  1743. X    case UPPER: case LOWER: case CAPITAL:
  1744. X    case O_SCONST: case '#': case DATE: case FMT: case STINDEX:
  1745. X    case EXT: case SVAL: case SUBSTR:
  1746. X        return (STR);
  1747. X
  1748. X    case '?':
  1749. X    case IF:
  1750. X        return(etype(e->e.o.right->e.o.left));
  1751. X
  1752. X    case 'f':
  1753. X        return(etype(e->e.o.right));
  1754. X
  1755. X    case O_VAR: {
  1756. X    register struct ent *p;
  1757. X    p = e->e.v.vp;
  1758. X    if (p->expr) 
  1759. X        return(p->flags & is_strexpr ? STR : NUM);
  1760. X    else if (p->label)
  1761. X        return(STR);
  1762. X    else
  1763. X        return(NUM);
  1764. X    }
  1765. X
  1766. X    default:
  1767. X    return(NUM);
  1768. X    }
  1769. X}
  1770. X
  1771. X/* return 1 if yes given, 0 otherwise */
  1772. Xint
  1773. Xyn_ask(msg)
  1774. Xchar    *msg;
  1775. X{    char ch;
  1776. X
  1777. X    Move (0, 0);
  1778. X    Clrtoeol ();
  1779. X    Addstr (msg);
  1780. X    ch = nmgetch();
  1781. X    if ( ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' ) {
  1782. X        if (ch == ctl('g') || ch == ESC)
  1783. X            return(-1);
  1784. X        error("y or n response required");
  1785. X        return (-1);
  1786. X    }
  1787. X    if (ch == 'y' || ch == 'Y')
  1788. X        return(1);
  1789. X    else
  1790. X        return(0);
  1791. X}
  1792. X
  1793. X/* expand a ~ in a path to your home directory */
  1794. X#if !defined(MSDOS) && !defined(VMS)
  1795. X#include <pwd.h>
  1796. X#endif
  1797. Xchar    *
  1798. Xfindhome(path)
  1799. Xchar    *path;
  1800. X{
  1801. X    static    char    *HomeDir = NULL;
  1802. X    extern    char    *getenv();
  1803. X
  1804. X    if (*path == '~')
  1805. X    {    char    *pathptr;
  1806. X        char    tmppath[PATHLEN];
  1807. X
  1808. X        if (HomeDir == NULL)
  1809. X        {    HomeDir = getenv("HOME");
  1810. X            if (HomeDir == NULL)
  1811. X                HomeDir = "/";
  1812. X        }
  1813. X        pathptr = path + 1;
  1814. X        if ((*pathptr == '/') || (*pathptr == '\0'))
  1815. X        {    strcpy(tmppath, HomeDir);
  1816. X        }
  1817. X#if !defined(MSDOS) && !defined(VMS)
  1818. X        else
  1819. X        {    struct    passwd *pwent;
  1820. X            extern    struct    passwd *getpwnam();
  1821. X            char    *namep;
  1822. X            char    name[50];
  1823. X
  1824. X            namep = name;
  1825. X            while ((*pathptr != '\0') && (*pathptr != '/'))
  1826. X                *(namep++) = *(pathptr++);
  1827. X            *namep = '\0';
  1828. X            if ((pwent = getpwnam(name)) == NULL)
  1829. X            {    Sprintf(path, "Can't find user %s", name);
  1830. X                return(NULL);
  1831. X            }
  1832. X            strcpy(tmppath, pwent->pw_dir);
  1833. X        }
  1834. X#endif
  1835. X        strcat(tmppath, pathptr);
  1836. X        strcpy(path, tmppath);
  1837. X    }
  1838. X    return(path);
  1839. X}
  1840. X
  1841. X#ifdef DOBACKUPS
  1842. X#include <sys/stat.h>
  1843. X
  1844. X/*
  1845. X * make a backup copy of a file, use the same mode and name in the format
  1846. X * [path/]#file~
  1847. X * return 1 if we were successful, 0 otherwise
  1848. X */
  1849. Xint
  1850. Xbackup_file(path)
  1851. Xchar    *path;
  1852. X{
  1853. X    struct    stat    statbuf;
  1854. X    char    fname[PATHLEN];
  1855. X    char    tpath[PATHLEN];
  1856. X#ifdef sequent
  1857. X    static    char    *buf = NULL;
  1858. X    static    unsigned buflen = 0;
  1859. X#else
  1860. X    char    buf[BUFSIZ];
  1861. X#endif
  1862. X    char    *tpp;
  1863. X    int    infd, outfd;
  1864. X    int    count;
  1865. X
  1866. X    /* tpath will be the [path/]file ---> [path/]#file~ */
  1867. X    strcpy(tpath, path);
  1868. X    if ((tpp = strrchr(tpath, '/')) == NULL)
  1869. X        tpp = tpath;
  1870. X    else
  1871. X        tpp++;
  1872. X    strcpy(fname, tpp);
  1873. X    Sprintf(tpp, "#%s~", fname);
  1874. X
  1875. X    if (stat(path, &statbuf) == 0)
  1876. X    {
  1877. X        /* if we know the optimum block size, use it */
  1878. X#ifdef sequent
  1879. X        if ((statbuf.st_blksize > buflen) || (buf == NULL))
  1880. X        {    buflen = statbuf.st_blksize;
  1881. X            if ((buf = Realloc(buf, buflen)) == (char *)0)
  1882. X            {    buflen = 0;
  1883. X                return(0);
  1884. X            }
  1885. X        }
  1886. X#endif
  1887. X
  1888. X        if ((infd = open(path, O_RDONLY, 0)) < 0)
  1889. X            return(0);
  1890. X
  1891. X        if ((outfd = open(tpath, O_TRUNC|O_WRONLY|O_CREAT,
  1892. X                    statbuf.st_mode)) < 0)
  1893. X            return(0);
  1894. X
  1895. X#ifdef sequent
  1896. X        while((count = read(infd, buf, statbuf.st_blksize)) > 0)
  1897. X#else
  1898. X        while((count = read(infd, buf, sizeof(buf))) > 0)
  1899. X#endif
  1900. X        {    if (write(outfd, buf, count) != count)
  1901. X            {    count = -1;
  1902. X                break;
  1903. X            }
  1904. X        }
  1905. X        close(infd);
  1906. X        close(outfd);
  1907. X
  1908. X        return((count < 0) ? 0 : 1);
  1909. X    }
  1910. X    else
  1911. X    if (errno == ENOENT)
  1912. X        return(1);
  1913. X    return(0);
  1914. X}
  1915. X#endif
  1916. X
  1917. Xstatic int day_month_starts[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
  1918. X
  1919. Xdouble convert_date(d, m, y)
  1920. Xint d;
  1921. Xint m;
  1922. Xint y;
  1923. X{
  1924. X  /* Convert to years since 1970. (or 2000, fix by 2070) */
  1925. X  if (y > 1970) y -= 1970;    /* Full year given */
  1926. X  else if (y >= 70) y -= 70;    /* Years since 1900 */
  1927. X  else y += 30;            /* Years since 2000 */
  1928. X  /* Use quarter days to compensate for leap years. */
  1929. X  return (double)((y * (365 * 4 + 1) + day_month_starts[m-1] * 4 + d * 4 - 2) *
  1930. X          6 * 60 * 60);
  1931. X}
  1932. X
  1933. END_OF_FILE
  1934.   if test 42376 -ne `wc -c <'ss_12b/cmds.c'`; then
  1935.     echo shar: \"'ss_12b/cmds.c'\" unpacked with wrong size!
  1936.   fi
  1937.   # end of 'ss_12b/cmds.c'
  1938. fi
  1939. if test -f 'ss_12b/screen.c' -a "${1}" != "-c" ; then 
  1940.   echo shar: Will not clobber existing file \"'ss_12b/screen.c'\"
  1941. else
  1942.   echo shar: Extracting \"'ss_12b/screen.c'\" \(14726 characters\)
  1943.   sed "s/^X//" >'ss_12b/screen.c' <<'END_OF_FILE'
  1944. X/*    SC    A Spreadsheet Calculator
  1945. X *        Curses based Screen driver
  1946. X *
  1947. X *        original by James Gosling, September 1982
  1948. X *        modifications by Mark Weiser and Bruce Israel,
  1949. X *            University of Maryland
  1950. X *
  1951. X *              More mods Robert Bond, 12/86
  1952. X *        More mods by Alan Silverstein, 3-4/88, see list of changes.
  1953. X *        Currently supported by sequent!sawmill!buhrt (Jeff Buhrt)
  1954. X *        $Revision: 6.21 $
  1955. X *
  1956. X */
  1957. X
  1958. X#ifndef lint
  1959. X  static char Sccsid[] = "%W% %G%";
  1960. X#endif
  1961. X
  1962. X#include "curses_stuff.h"
  1963. X#include "ss.h"
  1964. X
  1965. X#ifdef VMS
  1966. Xextern int VMS_read_raw;   /*sigh*/
  1967. X    VMS_read_raw = 1;
  1968. X#endif
  1969. X
  1970. X#ifdef BROKENCURSES
  1971. X        /* nl/nonl bug fix */
  1972. X#undef nl
  1973. X#undef nonl
  1974. X#define nl()     (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty))
  1975. X#define nonl()     (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty))
  1976. X#endif
  1977. X
  1978. Xvoid    repaint();
  1979. X
  1980. Xchar    under_cursor = ' '; /* Data under the < cursor */
  1981. Xchar    mode_ind = '.';
  1982. Xextern    char    revmsg[];
  1983. X
  1984. Xint    rows, lcols;
  1985. Xint    lastmx, lastmy;    /* Screen address of the cursor */
  1986. Xint    lastcol;    /* Spreadsheet Column the cursor was in last */
  1987. Xextern    int *fwidth;
  1988. Xextern    int showrange;    /* Causes ranges to be highlighted    */
  1989. Xextern    int showneed;    /* Causes cells needing values to be highlighted */
  1990. Xextern    int showexpr;    /* Causes cell exprs to be displayed, highlighted */
  1991. X#ifdef RIGHT_CBUG
  1992. Xextern    int wasforw;    /* Causes screen to be redisplay if on lastcol */
  1993. X#endif
  1994. X
  1995. X/*
  1996. X * update() does general screen update
  1997. X *
  1998. X * standout last time in update()?
  1999. X *    At this point we will let curses do work
  2000. X */
  2001. Xint    standlast    = FALSE;
  2002. X
  2003. Xvoid
  2004. Xupdate (anychanged)
  2005. Xint    anychanged;    /* did any cell really change in value? */
  2006. X{
  2007. X    register    row, col;
  2008. X    register struct ent **pp;
  2009. X    int    mxrow, mxcol;
  2010. X    int    minsr = 0, minsc = 0, maxsr = 0, maxsc = 0;
  2011. X    register r;
  2012. X    register i;
  2013. X    static    int    lastcurcol = -1, lastcurrow = -1;
  2014. X
  2015. X    /*
  2016. X     * place the cursor on the screen, set col, curcol, stcol, lastcol as
  2017. X     * needed
  2018. X     */
  2019. X    if ((curcol != lastcurcol) || FullUpdate)
  2020. X    {
  2021. X    while (col_hidden[curcol])   /* You can't hide the last row or col */
  2022. X        curcol++;
  2023. X
  2024. X    /* First see if the last display still covers curcol */
  2025. X    if (stcol <= curcol) { 
  2026. X        for (i = stcol, lcols = 0, col = RESCOL;
  2027. X               (col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
  2028. X            lcols++;
  2029. X
  2030. X            if (col_hidden[i])
  2031. X                continue;
  2032. X            col += fwidth[i];
  2033. X        }
  2034. X    }
  2035. X    while (stcol + lcols - 1 < curcol || curcol < stcol) {
  2036. X        FullUpdate++;
  2037. X        if (stcol - 1 == curcol) {    /* How about back one? */
  2038. X            stcol--;
  2039. X        } else if (stcol + lcols == curcol) {   /* Forward one? */
  2040. X            stcol++;
  2041. X        } else {
  2042. X            /* Try to put the cursor in the center of the screen */
  2043. X            col = (COLS - RESCOL - fwidth[curcol]) / 2 + RESCOL; 
  2044. X            stcol = curcol;
  2045. X            for (i=curcol-1; i >= 0 && col-fwidth[i] > RESCOL; i--)
  2046. X            {    stcol--;
  2047. X                if (col_hidden[i])
  2048. X                    continue;
  2049. X                col -= fwidth[i];
  2050. X            }
  2051. X        }
  2052. X        /* Now pick up the counts again */
  2053. X        for (i = stcol, lcols = 0,col = RESCOL;
  2054. X            (col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
  2055. X            lcols++;
  2056. X            if (col_hidden[i])
  2057. X                continue;
  2058. X            col += fwidth[i];
  2059. X        }
  2060. X    }
  2061. X    lastcurcol = curcol;
  2062. X    }
  2063. X
  2064. X    /* Now - same process on the rows as the columns */
  2065. X    if ((currow != lastcurrow) || FullUpdate)
  2066. X    {
  2067. X    while (row_hidden[currow])   /* You can't hide the last row or col */
  2068. X        currow++;
  2069. X    if (strow <= currow) { 
  2070. X        for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++)
  2071. X        {    rows++;
  2072. X            if (row_hidden[i])
  2073. X                continue;
  2074. X            row++;
  2075. X        }
  2076. X    }
  2077. X
  2078. X    while (strow + rows - 1 < currow || currow < strow) {
  2079. X        FullUpdate++;
  2080. X        if (strow - 1 == currow) {    /* How about up one? */
  2081. X            strow--;
  2082. X        } else if (strow + rows == currow) {   /* Down one? */
  2083. X            strow++;
  2084. X        } else {
  2085. X            /* Try to put the cursor in the center of the screen */
  2086. X            row = (LINES - RESROW) / 2 + RESROW; 
  2087. X            strow = currow;
  2088. X            for (i=currow-1; i >= 0 && row-1 > RESROW; i--) {
  2089. X                strow--;
  2090. X                if (row_hidden[i])
  2091. X                    continue;
  2092. X                row--;
  2093. X            }
  2094. X        }
  2095. X        /* Now pick up the counts again */
  2096. X        for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
  2097. X            rows++;
  2098. X            if (row_hidden[i])
  2099. X                continue;
  2100. X            row++;
  2101. X        }
  2102. X    }
  2103. X    lastcurrow = currow;
  2104. X    }
  2105. X    mxcol = stcol + lcols - 1;
  2106. X    mxrow = strow + rows - 1;
  2107. X
  2108. X    /* Get rid of cursor standout on the cell at previous cursor position */
  2109. X    if (!FullUpdate)
  2110. X    {    if (showcell)
  2111. X        repaint(lastmx, lastmy, fwidth[lastcol]);
  2112. X
  2113. X    (void) move(lastmy, lastmx+fwidth[lastcol]);
  2114. X
  2115. X    if ((inch() & A_CHARTEXT ) == '<')
  2116. X        (void) addch(under_cursor);
  2117. X    }
  2118. X
  2119. X    /* where is the the cursor now? */
  2120. X    lastmy =  RESROW;
  2121. X    for (row = strow; row < currow; row++)
  2122. X    if (!row_hidden[row])
  2123. X        lastmy++;
  2124. X
  2125. X    lastmx = RESCOL;
  2126. X    for (col = stcol; col < curcol; col++)
  2127. X    if (!col_hidden[col])
  2128. X        lastmx += fwidth[col];
  2129. X    lastcol = curcol;
  2130. X
  2131. X    if (FullUpdate || standlast) {
  2132. X    (void) move(2, 0);
  2133. X    (void) clrtobot();
  2134. X    (void) standout();
  2135. X
  2136. X    for (row=RESROW, i=strow; i <= mxrow; i++) {
  2137. X        if (row_hidden[i]) 
  2138. X        continue;
  2139. X        (void) move(row,0);
  2140. X        if (maxrows < 1000)
  2141. X        (void) printw("%-*d", RESCOL-1, i);
  2142. X        else
  2143. X        (void) printw("%-*d", RESCOL, i);
  2144. X        row++;
  2145. X    }
  2146. X#ifdef RIGHT_CBUG
  2147. X    if(wasforw) {
  2148. X        clearok(stdscr, TRUE);
  2149. X        wasforw = 0;
  2150. X    }
  2151. X#endif
  2152. X    (void) move(2,0);
  2153. X    (void) printw("%*s", RESCOL, " ");
  2154. X
  2155. X    for (col=RESCOL, i = stcol; i <= mxcol; i++) {
  2156. X        register int k;
  2157. X        if (col_hidden[i])
  2158. X        continue;
  2159. X        (void) move(2, col);
  2160. X        k = fwidth[i]/2;
  2161. X        if (k == 0)
  2162. X        (void) printw("%1s", coltoa(i));
  2163. X        else
  2164. X            (void) printw("%*s%-*s", k, " ", fwidth[i]-k, coltoa(i));
  2165. X        col += fwidth[i];
  2166. X    }
  2167. X    (void) standend();
  2168. X    }
  2169. X
  2170. X    if (showrange) {
  2171. X    minsr = showsr < currow ? showsr : currow;
  2172. X    minsc = showsc < curcol ? showsc : curcol;
  2173. X    maxsr = showsr > currow ? showsr : currow;
  2174. X    maxsc = showsc > curcol ? showsc : curcol;
  2175. X
  2176. X    if (showtop) {
  2177. X        (void) move(1,0);
  2178. X        (void) clrtoeol();
  2179. X        (void) printw("Default range:  %s",
  2180. X                r_name(minsr, minsc, maxsr, maxsc));
  2181. X    }
  2182. X    }
  2183. X
  2184. X
  2185. X    /* Repaint the visible screen */
  2186. X    if (showrange || anychanged || FullUpdate || standlast)
  2187. X    {
  2188. X    /* may be reset in loop, if not next time we will do a FullUpdate */
  2189. X      if (standlast)
  2190. X      {    FullUpdate = TRUE;
  2191. X    standlast = FALSE;
  2192. X      }
  2193. X
  2194. X      for (row = strow, r = RESROW; row <= mxrow; row++) {
  2195. X    register c = RESCOL;
  2196. X    int do_stand = 0;
  2197. X    int fieldlen;
  2198. X    int nextcol;
  2199. X
  2200. X    if (row_hidden[row])
  2201. X        continue;
  2202. X    for (pp = ATBL(tbl, row, col = stcol); col <= mxcol;
  2203. X             pp += nextcol - col,  col = nextcol, c += fieldlen) {
  2204. X
  2205. X        nextcol = col+1;
  2206. X        if (col_hidden[col]) {
  2207. X        fieldlen = 0;
  2208. X        continue;
  2209. X        }
  2210. X
  2211. X        fieldlen = fwidth[col];
  2212. X
  2213. X        /*
  2214. X         * Set standout if:
  2215. X         *
  2216. X         * - showing ranges, and not showing cells which need to be filled
  2217. X         *     in, and not showing cell expressions, and in a range, OR
  2218. X         *
  2219. X         * - if showing cells which need to be filled in and this one is
  2220. X         *     of that type (has a value and doesn't have an expression,
  2221. X         *     or it is a string expression), OR
  2222. X         *
  2223. X         * - if showing cells which have expressions and this one does.
  2224. X         */
  2225. X        if ((showrange && (! showneed) && (! showexpr)
  2226. X               && (row >= minsr) && (row <= maxsr)
  2227. X               && (col >= minsc) && (col <= maxsc))
  2228. X            || (showneed && (*pp) && ((*pp) -> flags & is_valid) &&
  2229. X              (((*pp) -> flags & is_strexpr) || !((*pp) -> expr)))
  2230. X            || (showexpr && (*pp) && ((*pp) -> expr)))
  2231. X        {
  2232. X        (void) move(r, c);
  2233. X        (void) standout();
  2234. X        standlast++;
  2235. X        if (!*pp)    /* no cell, but standing out */
  2236. X        {    (void) printw("%*s", fwidth[col], " ");
  2237. X            (void) standend();
  2238. X            continue;
  2239. X        }
  2240. X        else
  2241. X            do_stand = 1;
  2242. X        }
  2243. X        else
  2244. X        do_stand = 0;
  2245. X
  2246. X        if ((*pp) && (((*pp) -> flags & is_changed || FullUpdate) || do_stand)) {
  2247. X        if (do_stand) {
  2248. X            (*pp) -> flags |= is_changed; 
  2249. X        } else {
  2250. X            (void) move(r, c);
  2251. X            (*pp) -> flags &= ~is_changed;
  2252. X        }
  2253. X
  2254. X        /*
  2255. X         * Show expression; takes priority over other displays:
  2256. X         */
  2257. X
  2258. X        if ((*pp)->cellerror)
  2259. X            (void) printw("%*.*s", fwidth[col], fwidth[col],
  2260. X              (*pp)->cellerror == CELLERROR ? "ERROR" : "INVALID");
  2261. X        else
  2262. X        if (showexpr && ((*pp) -> expr)) {
  2263. X            linelim = 0;
  2264. X            editexp(row, col);        /* set line to expr */
  2265. X            linelim = -1;
  2266. X            showstring(line, /* leftflush = */ 1, /* hasvalue = */ 0,
  2267. X                row, col, & nextcol, mxcol, & fieldlen, r, c);
  2268. X        } else {
  2269. X            /*
  2270. X             * Show cell's numeric value:
  2271. X                     */
  2272. X
  2273. X            if ((*pp) -> flags & is_valid) {
  2274. X            char field[FBUFLEN];
  2275. X
  2276. X            if ((*pp) -> format) {
  2277. X                (void) format((*pp) -> format, (*pp) -> v,
  2278. X                         field, sizeof(field));
  2279. X            } else {
  2280. X                (void) engformat(realfmt[col], fwidth[col], 
  2281. X                                             precision[col], (*pp) -> v, 
  2282. X                                             field, sizeof(field));
  2283. X            }
  2284. X            if (strlen(field) > fwidth[col]) {
  2285. X                for(i = 0; i<fwidth[col]; i++)
  2286. X                    (void)addch('*');
  2287. X            } else {
  2288. X                for(i = 0; i < fwidth[col] - strlen(field);i++)
  2289. X                    (void)addch(' ');
  2290. X                (void)addstr(field);
  2291. X            }
  2292. X            }
  2293. X
  2294. X            /*
  2295. X             * Show cell's label string:
  2296. X             */
  2297. X
  2298. X            if ((*pp) -> label) {
  2299. X            showstring((*pp) -> label,
  2300. X                    (*pp) -> flags & (is_leftflush|is_label),
  2301. X                    (*pp) -> flags & is_valid,
  2302. X                    row, col, & nextcol, mxcol,
  2303. X                    & fieldlen, r, c);
  2304. X            }
  2305. X            else    /* repaint a blank cell: */
  2306. X            if ((do_stand || !FullUpdate) &&
  2307. X                ((*pp)->flags & is_changed) &&
  2308. X                !((*pp)->flags & is_valid) && !(*pp)->label) {
  2309. X            (void) printw("%*s", fwidth[col], " ");
  2310. X            }
  2311. X        } /* else */
  2312. X
  2313. X        if (do_stand) {
  2314. X            (void) standend();
  2315. X            do_stand = 0;
  2316. X        }
  2317. X        }
  2318. X    }
  2319. X    r++;
  2320. X      }
  2321. X    }
  2322. X
  2323. X    /* place 'cursor marker' */
  2324. X    if (showcell && (! showneed) && (! showexpr)) {
  2325. X    (void) move(lastmy, lastmx);
  2326. X        (void) standout();
  2327. X        repaint(lastmx, lastmy, fwidth[lastcol]);
  2328. X        (void) standend();
  2329. X    }
  2330. X    (void) move(lastmy, lastmx+fwidth[lastcol]);
  2331. X    under_cursor = (inch() & A_CHARTEXT);
  2332. X    (void) addch('<');
  2333. X
  2334. X    (void) move(0, 0);
  2335. X    (void) clrtoeol();
  2336. X    if (linelim >= 0) {
  2337. X    (void) addch(mode_ind);
  2338. X    (void) addstr("> ");
  2339. X    (void) addstr(line);
  2340. X    (void) move((linelim + 3) / COLS, (linelim+3) % COLS);
  2341. X    } else {
  2342. X    if (showtop) {            /* show top line */
  2343. X        register struct ent *p1;
  2344. X
  2345. X        int printed = 0;        /* printed something? */
  2346. X
  2347. X        /* show the current cell's format */
  2348. X        (void) printw("%s%d ", coltoa(curcol), currow);
  2349. X        if ((p1 = *ATBL(tbl, currow, curcol)) && p1->format)
  2350. X        printw("(%s) ", p1->format);
  2351. X        else
  2352. X        printw("(%d %d %d) ", fwidth[curcol], precision[curcol],
  2353. X                realfmt[curcol]);
  2354. X
  2355. X        if (p1) {
  2356. X        if (p1 -> expr) {
  2357. X            /* has expr of some type */
  2358. X            linelim = 0;
  2359. X            editexp(currow, curcol);    /* set line to expr */
  2360. X            linelim = -1;
  2361. X        }
  2362. X
  2363. X        /*
  2364. X         * Display string part of cell:
  2365. X         */
  2366. X
  2367. X        if ((p1 -> expr) && (p1 -> flags & is_strexpr)) {
  2368. X             if( (p1-> flags & is_label) )
  2369. X            (void) addstr("|{");
  2370. X            else
  2371. X            (void) addstr((p1 -> flags & is_leftflush) ? "<{" : ">{");
  2372. X            (void) addstr(line);
  2373. X            (void) addstr("} ");    /* and this '}' is for vi % */
  2374. X            printed = 1;
  2375. X
  2376. X        } else if (p1 -> label) {
  2377. X            /* has constant label only */
  2378. X            if( (p1-> flags & is_label) )
  2379. X            (void) addstr("|\"");
  2380. X            else
  2381. X            (void) addstr ((p1 -> flags & is_leftflush) ? "<\"" : ">\"");
  2382. X            (void) addstr (p1 -> label);
  2383. X            (void) addstr ("\" ");
  2384. X            printed = 1;
  2385. X        }
  2386. X
  2387. X        /*
  2388. X         * Display value part of cell:
  2389. X         */
  2390. X
  2391. X        if (p1 -> flags & is_valid) {
  2392. X            /* has value or num expr */
  2393. X            if ((! (p1 -> expr)) || (p1 -> flags & is_strexpr))
  2394. X            (void) sprintf (line, "%.15g", p1 -> v);
  2395. X
  2396. X            (void) addch ('[');
  2397. X            (void) addstr (line);
  2398. X            (void) addch (']');
  2399. X            *line = '\0'; /* this is the input buffer ! */
  2400. X            printed = 1;
  2401. X        }
  2402. X        }
  2403. X        if (! printed)
  2404. X        (void) addstr ("[]");
  2405. X        /* Display if cell is locked */
  2406. X        if (p1 && p1->flags&is_locked)
  2407. X        (void) addstr(" locked");
  2408. X    }
  2409. X    (void) move(lastmy, lastmx+fwidth[lastcol]);
  2410. X    }
  2411. X
  2412. X    if (revmsg[0]) {
  2413. X    (void) move(0, 0);
  2414. X    (void) clrtoeol ();    /* get rid of topline display */
  2415. X    (void) printw(revmsg);
  2416. X    *revmsg = '\0';        /* don't show it again */
  2417. X    (void) move (lastmy, lastmx + fwidth[lastcol]);
  2418. X    }
  2419. X
  2420. X    FullUpdate = FALSE;
  2421. X}
  2422. X
  2423. X/* redraw what is under the cursor from curses' idea of the screen */
  2424. Xvoid
  2425. Xrepaint(x, y, len)
  2426. Xint x, y, len;
  2427. X{
  2428. X    int c;
  2429. X
  2430. X    while(len-- > 0) {
  2431. X    (void) move(y, x);
  2432. X    c = inch() & A_CHARTEXT;
  2433. X    (void) addch(c);
  2434. X    x++;
  2435. X    }
  2436. X}
  2437. X
  2438. Xint seenerr;
  2439. X
  2440. X/* error routine for yacc (gram.y) */
  2441. Xvoid
  2442. Xyyerror(err)
  2443. Xchar *err; {
  2444. X    if (seenerr) return;
  2445. X    seenerr++;
  2446. X    (void) move(1,0);
  2447. X    (void) clrtoeol();
  2448. X    (void) printw("%s: %.*s<=%s",err,linelim,line,line+linelim);
  2449. X}
  2450. X
  2451. X#ifdef XENIX2_3
  2452. Xstruct termio tmio;
  2453. X#endif
  2454. X
  2455. Xvoid
  2456. Xstartdisp()
  2457. X{
  2458. X#if sun
  2459. X    int     fd;
  2460. X    fd = dup(0);
  2461. X#endif
  2462. X#ifdef TIOCGSIZE
  2463. X    {    struct ttysize size;
  2464. X    if (ioctl(0, TIOCGSIZE, &size) == 0)
  2465. X    { 
  2466. X        LINES = size.ts_lines;
  2467. X        COLS = size.ts_cols;
  2468. X    }
  2469. X    }
  2470. X#endif
  2471. X
  2472. X#ifdef XENIX2_3
  2473. X    (void) ioctl (fileno (stdin), TCGETA, & tmio);
  2474. X#endif
  2475. X    (void) initscr();
  2476. X#if sun
  2477. X    close(0);
  2478. X    dup(fd);
  2479. X    close(fd);
  2480. X#endif
  2481. X    (void) clear();
  2482. X#ifdef VMS
  2483. X    VMS_read_raw = 1;
  2484. X#else
  2485. X    cbreak();
  2486. X    nonl();
  2487. X    noecho ();
  2488. X#endif
  2489. X    initkbd();
  2490. X    scrollok(stdscr, 1);
  2491. X
  2492. X#if defined(SYSV3) && !defined(NOIDLOK)
  2493. X# ifndef IDLOKBAD
  2494. X    /*
  2495. X     * turn hardware insert/delete on, if possible.
  2496. X     * turn on scrolling for systems with SYSVr3.{1,2} (SYSVr3.0 has this set
  2497. X     * as the default)
  2498. X     */
  2499. X     idlok(stdscr,TRUE);
  2500. X# else    /*
  2501. X     * This seems to fix (with an empty spreadsheet):
  2502. X     *    a) Redrawing the bottom half of the screen when you
  2503. X     *        move between row 9 <-> 10
  2504. X     *    b) the highlighted row labels being trash when you
  2505. X     *        move between row 9 <-> 10
  2506. X     *    c) On an xterm on Esix Rev. D+ from eating lines
  2507. X     *     -goto (or move) a few lines (or more) past the bottom
  2508. X     *     of the screen, goto (or move) to the top line on the
  2509. X     *     screen, move upward and the current line is deleted, the
  2510. X     *     others move up even when they should not, check by
  2511. X     *     noticing the rows become 2, 3, 40, 41, 42... (etc).
  2512. X     */
  2513. X     idlok(stdscr,FALSE);
  2514. X# endif
  2515. X#endif
  2516. X
  2517. X    FullUpdate++;
  2518. X}
  2519. X
  2520. Xvoid
  2521. Xstopdisp()
  2522. X{
  2523. X    deraw();
  2524. X    resetkbd();
  2525. X    endwin();
  2526. X#ifdef XENIX2_3
  2527. X    (void) ioctl (fileno (stdin), TCSETAW, & tmio);
  2528. X#endif
  2529. X}
  2530. X
  2531. X/* init curses */
  2532. X#ifdef VMS
  2533. X
  2534. Xgoraw()
  2535. X{
  2536. X    VMS_read_raw = 1;
  2537. X    FullUpdate++;
  2538. X}
  2539. X
  2540. Xderaw()
  2541. X{
  2542. X    (void) move (LINES - 1, 0);
  2543. X    (void) clrtoeol();
  2544. X    (void) refresh();
  2545. X    VMS_read_raw = 0;
  2546. X}
  2547. X
  2548. X#else /* VMS */
  2549. Xvoid
  2550. Xgoraw()
  2551. X{
  2552. X#if SYSV2 || SYSV3
  2553. X    fixterm();
  2554. X#else /* SYSV2 || SYSV3 */
  2555. X    cbreak();
  2556. X    nonl();
  2557. X    noecho ();
  2558. X#endif /* SYSV2 || SYSV3 */
  2559. X    kbd_again();
  2560. X    (void) clear();
  2561. X    FullUpdate++;
  2562. X}
  2563. X
  2564. X/* clean up curses */
  2565. Xvoid
  2566. Xderaw()
  2567. X{
  2568. X    (void) move (LINES - 1, 0);
  2569. X    (void) clrtoeol();
  2570. X    (void) refresh();
  2571. X#if SYSV2 || SYSV3
  2572. X    resetterm();
  2573. X#else
  2574. X    nocbreak();
  2575. X    nl();
  2576. X    echo();
  2577. X#endif
  2578. X    resetkbd();
  2579. X}
  2580. X
  2581. X#endif /* VMS */
  2582. END_OF_FILE
  2583.   if test 14726 -ne `wc -c <'ss_12b/screen.c'`; then
  2584.     echo shar: \"'ss_12b/screen.c'\" unpacked with wrong size!
  2585.   fi
  2586.   # end of 'ss_12b/screen.c'
  2587. fi
  2588. echo shar: End of archive 3 \(of 11\).
  2589. cp /dev/null ark3isdone
  2590. MISSING=""
  2591. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2592.     if test ! -f ark${I}isdone ; then
  2593.     MISSING="${MISSING} ${I}"
  2594.     fi
  2595. done
  2596. if test "${MISSING}" = "" ; then
  2597.     echo You have unpacked all 11 archives.
  2598.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2599. else
  2600.     echo You still must unpack the following archives:
  2601.     echo "        " ${MISSING}
  2602. fi
  2603. exit 0
  2604. exit 0 # Just in case...
  2605.