home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / amiga / ed-0.1-src.lha / ed-0.1 / undo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  3.9 KB  |  156 lines

  1. /* undo.c: This file contains the undo routines for the ed line editor */
  2. /* ed line editor.
  3.    Copyright (C) 1993 Andrew Moore, Talke Studio
  4.    All Rights Reserved
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.    General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #ifndef lint
  22. static char *rcsid = "@(#)$Id: undo.c,v 1.3 1994/01/22 01:20:10 alm Exp $";
  23. #endif /* not lint */
  24.  
  25. #include "ed.h"
  26.  
  27.  
  28. #define USIZE 100        /* undo stack size */
  29. undo_t *ustack = NULL;        /* undo stack */
  30. long usize = 0;            /* stack size variable */
  31. long u_p = 0;            /* undo stack pointer */
  32.  
  33. /* push_undo_stack: return pointer to intialized undo node */
  34. undo_t *
  35. push_undo_stack (type, from, to)
  36.      int type;
  37.      long from;
  38.      long to;
  39. {
  40.   undo_t *t;
  41.  
  42.   if ((t = ustack) == NULL &&
  43.    (t = ustack = (undo_t *) malloc ((usize = USIZE) * sizeof (undo_t))) == NULL)
  44.     {
  45.       fprintf (stderr, "%s\n", strerror (errno));
  46.       sprintf (errmsg, "out of memory");
  47.       return NULL;
  48.     }
  49.   else if (u_p >= usize &&
  50.       (t = (undo_t *) realloc (ustack, (usize += USIZE) * sizeof (undo_t))) == NULL)
  51.     {
  52.       /* out of memory - release undo stack */
  53.       fprintf (stderr, "%s\n", strerror (errno));
  54.       sprintf (errmsg, "out of memory");
  55.       clear_undo_stack ();
  56.       free (ustack);
  57.       ustack = NULL;
  58.       usize = 0;
  59.       return NULL;
  60.     }
  61.   ustack = t;
  62.   ustack[u_p].type = type;
  63.   ustack[u_p].t = get_addressed_line_node (to);
  64.   ustack[u_p].h = get_addressed_line_node (from);
  65.   return ustack + u_p++;
  66. }
  67.  
  68.  
  69. /* USWAP: swap undo nodes */
  70. #define USWAP(x, y) \
  71.   do                                    \
  72.     {                                    \
  73.       undo_t utmp;                            \
  74.       utmp = (x), (x) = (y), (y) = utmp;                \
  75.     }                                    \
  76.   while (0)
  77.  
  78.  
  79. long u_current_addr = -1;    /* if >= 0, undo enabled */
  80. long u_addr_last = -1;        /* if >= 0, undo enabled */
  81.  
  82. /* pop_undo_stack: undo last change to the editor buffer */
  83. int
  84. pop_undo_stack ()
  85. {
  86.   long n;
  87.   long o_current_addr = current_addr;
  88.   long o_addr_last = addr_last;
  89.  
  90.   if (u_current_addr == -1 || u_addr_last == -1)
  91.     {
  92.       sprintf (errmsg, "nothing to undo");
  93.       return ERR;
  94.     }
  95.   else if (u_p)
  96.     modified = 1;
  97.   get_addressed_line_node (0);    /* this get_addressed_line_node last! */
  98.   SPL1 ();
  99.   for (n = u_p; n-- > 0;)
  100.     {
  101.       switch (ustack[n].type)
  102.     {
  103.     case UADD:
  104.       REQUE (ustack[n].h->q_back, ustack[n].t->q_forw);
  105.       break;
  106.     case UDEL:
  107.       REQUE (ustack[n].h->q_back, ustack[n].h);
  108.       REQUE (ustack[n].t, ustack[n].t->q_forw);
  109.       break;
  110.     case UMOV:
  111.     case VMOV:
  112.       REQUE (ustack[n - 1].h, ustack[n].h->q_forw);
  113.       REQUE (ustack[n].t->q_back, ustack[n - 1].t);
  114.       REQUE (ustack[n].h, ustack[n].t);
  115.       n--;
  116.       break;
  117.     default:
  118.       /*NOTREACHED */
  119.       ;
  120.     }
  121.       ustack[n].type ^= 1;
  122.     }
  123.   /* reverse undo stack order */
  124.   for (n = u_p; n-- > (u_p + 1) / 2;)
  125.     USWAP (ustack[n], ustack[u_p - 1 - n]);
  126.   if (isglobal)
  127.     clear_active_list ();
  128.   current_addr = u_current_addr, u_current_addr = o_current_addr;
  129.   addr_last = u_addr_last, u_addr_last = o_addr_last;
  130.   SPL0 ();
  131.   return 0;
  132. }
  133.  
  134.  
  135. /* clear_undo_stack: clear the undo stack */
  136. void
  137. clear_undo_stack ()
  138. {
  139.   line_t *lp, *ep, *tl;
  140.  
  141.   while (u_p--)
  142.     if (ustack[u_p].type == UDEL)
  143.       {
  144.     ep = ustack[u_p].t->q_forw;
  145.     for (lp = ustack[u_p].h; lp != ep; lp = tl)
  146.       {
  147.         unmark_line_node (lp);
  148.         tl = lp->q_forw;
  149.         free (lp);
  150.       }
  151.       }
  152.   u_p = 0;
  153.   u_current_addr = current_addr;
  154.   u_addr_last = addr_last;
  155. }
  156.