home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / se / part2 / scratch.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  11.0 KB  |  588 lines

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