home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / se / part03 / scratch.c next >
Encoding:
C/C++ Source or Header  |  1987-01-25  |  11.3 KB  |  603 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: scratch.c,v 1.2 86/07/17 17:21:38 arnold Exp $";
  3. #endif
  4.  
  5. /*
  6.  * $Log:    scratch.c,v $
  7.  * Revision 1.2  86/07/17  17:21:38  arnold
  8.  * Calls to error() changed to reflect whether or not to coredump.
  9.  * 
  10.  * Revision 1.1  86/05/06  13:38:04  osadr
  11.  * Initial revision
  12.  * 
  13.  * 
  14.  */
  15.  
  16. /*
  17. ** scratch.c
  18. **
  19. ** scratch file handling for se screen editor.
  20. **
  21. ** If OLD_SCRATCH is defined, then this file will contain the
  22. ** original scratch file handling, based on linked lists,
  23. ** from the ratfor version of Software Tools.  This method is
  24. ** real good at moving lines around, but is poor for finding lines.
  25. **
  26. ** If OLD_SCRATCH is not defined, which is the default, this file will use
  27. ** the line handling methodology presented in Software Tools In Pascal,
  28. ** *without* changing the way any of the routines are called.
  29. **
  30. ** Bascially, the lines are always kept in order in the Buf array.
  31. ** Thus, lines 1 through 5 are in Buf[1] through Buf[5]. blkmove() and
  32. ** reverse() do the work of moving lines around in the buffer. The alloc()
  33. ** routine, therefore, always allocates the first empty slot, which will be
  34. ** at Lastln + 1, if there is room.
  35. **
  36. ** Deleted lines are kept at the end of the buffer. Limbo points to the first
  37. ** line in the group of lines which were last deleted, or else Limbo == NOMORE.
  38. **
  39. ** It is a very good idea to read the chapters on editing in BOTH editions of
  40. ** Software Tools, before trying to muck with this. It also helps to be a
  41. ** little bit off the wall....
  42. **
  43. ** In fact, I would go as far as saying, "If you touch this, it will break.
  44. ** It is held together with chewing gum, scotch tape, and bobby pins."
  45. ** (Of course, you could always use OLD_SCRATCH, which definitely works.
  46. ** It just increases the size of the editor.)  So much for the old
  47. ** "Just replace the implementation of the underlying primitives..."
  48. */
  49.  
  50. #include "se.h"
  51. #include "extern.h"
  52.  
  53. /* alloc --- allocate space for a new pointer block */
  54.  
  55.  
  56. static LINEDESC *alloc (ptr)
  57. register LINEDESC **ptr;
  58. {
  59. #ifdef OLD_SCRATCH    /* old way */
  60.     if (Free == NOMORE)   /* no free list, expand into unallocated space */
  61.     {
  62.         if (Lastbf - Buf + BUFENT <= MAXBUF)   /* see if there's room */
  63.         {
  64.             *ptr = Lastbf;
  65.             Lastbf += BUFENT;
  66.         }
  67.         else
  68.             *ptr = NOMORE;        /* out of pointer space */
  69.     }
  70.     else    /* remove a block from free list */
  71.     {
  72.         *ptr = Free;
  73.         Free = Free->Prevline;
  74.     }
  75. #else    /* new way */
  76.     int limbo_index = Limbo - Buf;    /* use indices instead of pointers */
  77.         /* N.B.: this statement is meaningless if Limbo == NOMORE */
  78.         /* but if so, we don't use limbo_index anyway */
  79.  
  80.     if (Limbo == NOMORE)
  81.         if (Lastln < (MAXBUF - 1) - 1)    /* dumb zero based indexing! */
  82.             *ptr = &Buf[Lastln + 1];
  83.         else
  84.             *ptr = NOMORE;
  85.     else if (limbo_index - Lastln > 1)
  86.         *ptr = &Buf[Lastln + 1];
  87.     else
  88.         *ptr = NOMORE;
  89. #endif
  90.  
  91.     return (*ptr);
  92. }
  93.  
  94.  
  95. /* bump --- advance line number and corresponding index simultaneously */
  96.  
  97. bump (line, ix, way)
  98. int *line, way;
  99. LINEDESC **ix;
  100. {
  101.     if (way == FORWARD)    /* increment line number */
  102.     {
  103. #ifdef OLD_SCRATCH
  104.         *ix = (*ix)->Nextline;
  105.         if (*ix == Line0)
  106.             *line = 0;
  107.         else
  108.             (*line)++;
  109. #else
  110.         (*ix)++;
  111.         if (*ix == &Buf[Lastln+1])
  112.         {
  113.             *line = 0;
  114.             *ix = Line0;
  115.         }
  116.         else
  117.             (*line)++;
  118. #endif
  119.     }
  120.     else    /* decrement line number */
  121.     {
  122.         if (*ix == Line0)
  123.             *line = Lastln;
  124.         else
  125.             (*line)--;
  126. #ifdef OLD_SCRATCH
  127.         *ix = (*ix)->Prevline;
  128. #else
  129.         if (*ix == Line0)
  130.             *ix = &Buf[Lastln];
  131.         else
  132.             (*ix)--;
  133. #endif
  134.     }
  135. }
  136.  
  137.  
  138.  
  139. /* closef --- close a file */
  140.  
  141. static closef (fd)
  142. filedes fd;
  143. {
  144.     close (fd);
  145. }
  146.  
  147.  
  148.  
  149.  
  150. /* clrbuf --- purge scratch file */
  151.  
  152. clrbuf ()
  153. {
  154.  
  155.     if (Lastln > 0)
  156.         svdel (1, Lastln);
  157.  
  158.     closef (Scr);
  159.     unlink (Scrname);
  160. }
  161.  
  162.  
  163.  
  164. /* garbage_collect --- compress scratch file */
  165.  
  166. garbage_collect ()
  167. {
  168.     char new_name [MAXLINE];
  169.     register int i, new_scrend;
  170.     int new_fd;
  171.     register LINEDESC *p;
  172.  
  173.     makscr (&new_fd, new_name);
  174.     remark ("collecting garbage");
  175.     new_scrend = 0;
  176. #ifdef OLD_SCRATCH
  177.     for (p = Limbo, i = 1; i <= Limcnt; p = p->Nextline, i++)
  178. #else
  179.     for (p = Limbo, i = 1; i <= Limcnt; p++, i++)
  180. #endif
  181.     {
  182.         gtxt (p);
  183.         seekf ((long) new_scrend * 8, new_fd);
  184.         writef (Txt, (int) p->Lineleng, new_fd);
  185.         p->Seekaddr = new_scrend;
  186.         new_scrend += (p->Lineleng + 7) / 8;
  187.     }
  188. #ifdef OLD_SCRATCH
  189.     for (p = Line0, i = 0; i <= Lastln; p = p->Nextline, i++)
  190. #else
  191.     for (p = Line0, i = 0; i <= Lastln; p++, i++)
  192. #endif
  193.     {
  194.         gtxt (p);
  195.         seekf ((long) new_scrend * 8, new_fd);
  196.         writef (Txt, (int) p->Lineleng, new_fd);
  197.         p->Seekaddr = new_scrend;
  198.         new_scrend += (p->Lineleng + 7) / 8;
  199.     }
  200.  
  201.     closef (Scr);
  202.     unlink (Scrname);
  203.  
  204.     Scr = new_fd;
  205.     sprintf (Scrname, "%s", new_name);
  206.     Scrend = new_scrend;
  207.     Lost_lines = 0;
  208.  
  209.     remark ("");
  210. }
  211.  
  212.  
  213.  
  214. /* gettxt --- locate text for line, copy to txt */
  215.  
  216. LINEDESC *gettxt (line)
  217. int line;
  218. {
  219.     register LINEDESC *k;
  220.     LINEDESC *getind ();
  221.  
  222.     k = getind (line);
  223.     gtxt (k);
  224.  
  225.     return (k);
  226. }
  227.  
  228.  
  229.  
  230. /* gtxt --- retrieve a line from the scratch file */
  231.  
  232. gtxt (ptr)
  233. register LINEDESC *ptr;
  234. {
  235.     int readf ();
  236.  
  237.     seekf ((long) ptr->Seekaddr * 8, Scr); /* position to start of file */
  238.     /*
  239.      * rounded Seekaddr to 8 byte sections, giving larger
  240.      * buffer space for text (*8)
  241.      */
  242.  
  243.     return (readf (Txt, (int) ptr->Lineleng, Scr) - 1);
  244. }
  245.  
  246.  
  247.  
  248. /* inject --- insert a new line after curln */
  249.  
  250. inject (lin)
  251. register char lin [];
  252. {
  253.     register int i;
  254.     int maklin ();
  255.     register LINEDESC *k1, *k2;
  256.     LINEDESC *k3;
  257.     LINEDESC *getind ();
  258.  
  259.     for (i = 0; lin [i] != EOS; )
  260.     {
  261.         i = maklin (lin, i, &k3);       /* create a single line */
  262.         if (i == ERR)
  263.         {
  264.             Errcode = ECANTINJECT;
  265.             return (ERR);
  266.         }
  267. #ifdef OLD_SCRATCH
  268.         k1 = getind (Curln);            /* get pointer to curln */
  269.         k2 = k1-> Nextline;             /* get pointer to nextln */
  270.         relink (k1, k3, k3, k2);        /* set pointers of new line */
  271.         relink (k3, k2, k1, k3);        /* set pointers of prev, next */
  272.         svins (Curln, 1);
  273.         Lastln++;        /* update Lastln */
  274. #else
  275.         Lastln++;        /* update Lastln */
  276.         blkmove (Lastln, Lastln, Curln);
  277.         svins (Curln, 1);
  278. #endif
  279.         Curln++;        /* update Curln */
  280.     }
  281.     return (OK);
  282. }
  283.  
  284.  
  285.  
  286. /* maklin --- construct a new line, add to scratch file */
  287.  
  288. maklin (lin, i, newind)
  289. register char lin [];
  290. register int i;
  291. LINEDESC **newind;
  292. {
  293.  
  294.     char text [MAXLINE];
  295.     register int l, n;
  296.     LINEDESC *ptr;
  297.     LINEDESC *alloc ();
  298.  
  299.     if (alloc (&ptr) == NOMORE)     /* get space for pointer block */
  300.         return (ERR);
  301.  
  302.     for (n = i; lin [n] != EOS; n++)    /* find end of line */
  303.         if (lin [n] == '\n')
  304.         {
  305.             n++;
  306.             break;
  307.         }
  308.  
  309.     if (n - i >= MAXLINE )  /* can't handle more than MAXLINE chars/line */
  310.         n = i + MAXLINE - 1;
  311.     l = n - i + 1;          /* length of new line (including EOS) */
  312.  
  313.     move_ (&lin [i], text, l);      /* move new line into text */
  314.     text [l - 1] = EOS;             /* add EOS */
  315.  
  316.     ptr->Seekaddr = Scrend; /* will be added to end of scratch file */
  317.     ptr->Lineleng = l;      /* line length including EOS */
  318.     ptr->Globmark = NO;     /* not marked for Global command */
  319.     ptr->Markname = DEFAULTNAME;    /* give it default mark name */
  320.  
  321.     seekf ((long) Scrend * 8, Scr); /* go to end of scratch file */
  322.     writef (text, l, Scr);          /* write line on scratch file */
  323.     Scrend += (l + 7) / 8;          /* update end-of-file pointer */
  324.  
  325.     Buffer_changed = YES;
  326.  
  327.     *newind = ptr;                  /* return index of new line */
  328.     return (n);                     /* return next char of interest in lin */
  329. }
  330.  
  331.  
  332.  
  333. /* makscr --- create a new scratch file */
  334.  
  335. makscr (fd, str)
  336. register filedes *fd;
  337. register char str[];
  338. {
  339.     register int i;
  340.  
  341.     for (i = 0; i <= 9; i++)
  342.     {
  343.         sprintf (str, "/usr/tmp/se%d.%d", getpid(), i);
  344.         /* create str name in /usr/tmp */
  345.         if ((*fd = open (str, 0)) < 0)
  346.         {
  347.             /* if the file is not there, close it and create it */
  348.             close (*fd);
  349.             if ((*fd = creat (str, 0700)) > 0)
  350.             {
  351.                 close (*fd);
  352.                 if ((*fd = open (str, 2)) > 0)
  353.                     return;
  354.             }
  355.         }
  356.         else
  357.             close (*fd);
  358.  
  359.     }
  360.     error (YES, "can't create scratch file");
  361. }
  362.  
  363.  
  364.  
  365. /* nextln --- get line after "line" */
  366.  
  367. nextln (line)
  368. int line;
  369. {
  370.     register int ret;
  371.  
  372.     ret = line + 1;
  373.     if (ret > Lastln)
  374.         ret = 0;
  375.  
  376.     return (ret);
  377. }
  378.  
  379.  
  380.  
  381. /* prevln --- get line before "line" */
  382.  
  383. prevln (line)
  384. int line;
  385. {
  386.     register int ret;
  387.  
  388.     ret = line - 1;
  389.     if (ret < 0)
  390.         ret = Lastln;
  391.  
  392.     return (ret);
  393. }
  394.  
  395.  
  396.  
  397. /* readf --- read count words from fd into buf */
  398.  
  399. readf (buf, count, fd)
  400. char buf [];
  401. int  count, fd;
  402. {
  403.     register int ret;
  404.  
  405.     ret = read (fd, buf, count);
  406.     if (ret != count)
  407.         error (YES, "Fatal scratch file read error");
  408.  
  409.     return (ret);
  410. }
  411.  
  412.  
  413. #ifdef OLD_SCRATCH
  414. /* relink --- rewrite two half links */
  415.  
  416. relink (a, x, y, b)
  417. LINEDESC *a, *b, *x, *y;
  418. {
  419.     x->Prevline = a;
  420.     y->Nextline = b;
  421. }
  422. #endif
  423.  
  424.  
  425.  
  426. /* seekf --- position file open on fd to pos */
  427.  
  428. static seekf (pos, fd)
  429. long pos;
  430. filedes fd;
  431. {
  432.     register long ret;
  433.     long lseek ();
  434.  
  435.     ret = lseek (fd, pos, 0);               /* abs seek */
  436.     if (ret != pos)
  437.         error (YES, "Fatal scratch file seek error");
  438.     return (OK);
  439. }
  440.  
  441.  
  442.  
  443. /* mkbuf --- create scratch file, initialize line 0 */
  444.  
  445. mkbuf ()
  446. {
  447.     LINEDESC *p;
  448.  
  449.     makscr (&Scr, Scrname);    /* create a scratch file */
  450.     Scrend = 0;        /* initially empty */
  451.  
  452.     Curln = 0;
  453. #ifdef OLD_SCRATCH
  454.     Lastln = 0;
  455. #else
  456.     Lastln = -1;        /* alloc depends on this... */
  457. #endif
  458.  
  459. #ifdef OLD_SCRATCH
  460.     Lastbf = &Buf[0];       /* next word available for allocation ?? */
  461.     Free = NOMORE;          /* free list initially empty */
  462. #endif
  463.     Limbo = NOMORE;         /* no lines in limbo */
  464.     Limcnt = 0;
  465.     Lost_lines = 0;         /* no garbage in scratch file yet */
  466.  
  467.     maklin ("", 0, &p);     /* create an empty line */
  468. #ifdef OLD_SCRATCH
  469.     relink (p, p, p, p);    /* establish initial linked list */
  470. #endif
  471.     p->Markname = EOS;    /* give it an illegal mark name */
  472.     Line0 = p;              /* henceforth and forevermore */
  473.  
  474. #ifndef OLD_SCRATCH
  475.     Lastln = 0;
  476. #endif
  477. }
  478.  
  479.  
  480.  
  481. /* sp_inject --- special inject for reading files */
  482.  
  483. LINEDESC *sp_inject (lin, len, line)
  484. char lin[];
  485. int  len;
  486. LINEDESC *line;
  487. {
  488.     register LINEDESC *k, *ret;
  489.     LINEDESC *ptr;
  490.     LINEDESC *alloc ();
  491.  
  492.     ret = alloc (&ptr);
  493.     if (ptr == NOMORE)
  494.     {
  495.         Errcode = ECANTINJECT;
  496.         return (ret);
  497.     }
  498.  
  499.     ptr->Seekaddr = Scrend;
  500.     ptr->Lineleng = len + 1;
  501.     ptr->Globmark = NO;
  502.     ptr->Markname = DEFAULTNAME;
  503.  
  504.     seekf ((long) Scrend * 8, Scr);
  505.     writef (lin, len + 1, Scr);
  506.     Scrend += ((len + 1) + 7) / 8;          /* fudge for larger buffer */
  507.     Lastln++;
  508.  
  509.     Buffer_changed = YES;
  510.  
  511. #ifdef OLD_SCRATCH
  512.     k = line->Nextline;
  513.     relink (line, ptr, ptr, k);
  514.     relink (ptr, k, line, ptr);
  515. #else
  516.     /*
  517.      * this part dependant on the fact that we set
  518.      * Curln = line in the routine do_read.
  519.      */
  520.     blkmove (ptr - Buf, ptr - Buf, Curln);    /* need line no's */
  521.     Curln++;
  522. #endif
  523.  
  524.     return (ret);
  525. }
  526.  
  527.  
  528.  
  529. /* writef --- write count words from buf onto fd */
  530.  
  531. writef (buf, count, fd)
  532. char buf[];
  533. int  count;
  534. filedes fd;
  535. {
  536.     register int ret;
  537.  
  538.     ret = write (fd, buf, count);
  539.     if (ret != count)
  540.         error (YES, "Fatal scratch file write error");
  541.     return (ret);
  542. }
  543.  
  544.  
  545.  
  546. /* getind --- locate line index in buffer */
  547.  
  548. LINEDESC *getind (line)
  549. register int line;
  550. {
  551. #ifdef OLD_SCRATCH
  552.     register LINEDESC *k;
  553.  
  554.     k = Line0;
  555.     line++;
  556.     while (--line)
  557.         k = k->Nextline;
  558.  
  559.     return (k);
  560. #else
  561.     return (&Buf[line]);
  562. #endif
  563. }
  564.  
  565. #ifndef OLD_SCRATCH
  566.  
  567. /* blkmove -- use SWT in Pascal line handling */
  568.  
  569. blkmove (n1, n2, n3)    /* move block of lines n1..n2 to after n3 */
  570. int n1, n2, n3;
  571. {
  572.     if (n3 < n1 -1)
  573.     {
  574.         reverse (n3 + 1, n1 - 1);
  575.         reverse (n1, n2);
  576.         reverse (n3 + 1, n2);
  577.     }
  578.     else if (n3 > n2)
  579.     {
  580.         reverse (n1, n2);
  581.         reverse (n2 + 1, n3);
  582.         reverse (n1, n3);
  583.     }
  584. }
  585.  
  586. /* reverse -- reverse buf[n1]..buf[n2] */
  587.  
  588. reverse (n1, n2)
  589. register int n1, n2;
  590. {
  591.     LINEDESC temp;
  592.  
  593.     while (n1 < n2)
  594.     {
  595.         temp = Buf[n1];
  596.         Buf[n1] = Buf[n2];
  597.         Buf[n2] = temp;
  598.         n1++;
  599.         n2--;
  600.     }
  601. }
  602. #endif
  603.