Due to the deletion of the gcc support from libc we need again the
[unix-history] / bin / ed / undo.c
CommitLineData
84ee7b23
AM
1/* undo.c: This file contains the undo routines for the ed line editor */
2/*-
3 * Copyright (c) 1993 Andrew Moore, Talke Studio.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#ifndef lint
29static char *rcsid = "@(#)$Id: undo.c,v 1.2 1993/12/14 16:19:56 alm Exp $";
30#endif /* not lint */
31
32#include "ed.h"
33
34
35#define USIZE 100 /* undo stack size */
36undo_t *ustack = NULL; /* undo stack */
37long usize = 0; /* stack size variable */
38long u_p = 0; /* undo stack pointer */
39
40/* push_undo_stack: return pointer to intialized undo node */
41undo_t *
42push_undo_stack(type, from, to)
43 int type;
44 long from;
45 long to;
46{
47 undo_t *t;
48
49#if defined(sun) || defined(NO_REALLOC_NULL)
50 if (ustack == NULL &&
51 (ustack = (undo_t *) malloc((usize = USIZE) * sizeof(undo_t))) == NULL) {
52 fprintf(stderr, "%s\n", strerror(errno));
53 sprintf(errmsg, "out of memory");
54 return NULL;
55 }
56#endif
57 t = ustack;
58 if (u_p < usize ||
59 (t = (undo_t *) realloc(ustack, (usize += USIZE) * sizeof(undo_t))) != NULL) {
60 ustack = t;
61 ustack[u_p].type = type;
62 ustack[u_p].t = get_addressed_line_node(to);
63 ustack[u_p].h = get_addressed_line_node(from);
64 return ustack + u_p++;
65 }
66 /* out of memory - release undo stack */
67 fprintf(stderr, "%s\n", strerror(errno));
68 sprintf(errmsg, "out of memory");
69 clear_undo_stack();
70 free(ustack);
71 ustack = NULL;
72 usize = 0;
73 return NULL;
74}
75
76
77/* USWAP: swap undo nodes */
78#define USWAP(x,y) { \
79 undo_t utmp; \
80 utmp = x, x = y, y = utmp; \
81}
82
83
84long u_current_addr = -1; /* if >= 0, undo enabled */
85long u_addr_last = -1; /* if >= 0, undo enabled */
86
87/* pop_undo_stack: undo last change to the editor buffer */
88int
89pop_undo_stack()
90{
91 long n;
92 long o_current_addr = current_addr;
93 long o_addr_last = addr_last;
94
95 if (u_current_addr == -1 || u_addr_last == -1) {
96 sprintf(errmsg, "nothing to undo");
97 return ERR;
98 } else if (u_p)
99 modified = 1;
100 get_addressed_line_node(0); /* this get_addressed_line_node last! */
101 SPL1();
102 for (n = u_p; n-- > 0;) {
103 switch(ustack[n].type) {
104 case UADD:
105 REQUE(ustack[n].h->q_back, ustack[n].t->q_forw);
106 break;
107 case UDEL:
108 REQUE(ustack[n].h->q_back, ustack[n].h);
109 REQUE(ustack[n].t, ustack[n].t->q_forw);
110 break;
111 case UMOV:
112 case VMOV:
113 REQUE(ustack[n - 1].h, ustack[n].h->q_forw);
114 REQUE(ustack[n].t->q_back, ustack[n - 1].t);
115 REQUE(ustack[n].h, ustack[n].t);
116 n--;
117 break;
118 default:
119 /*NOTREACHED*/
120 ;
121 }
122 ustack[n].type ^= 1;
123 }
124 /* reverse undo stack order */
125 for (n = u_p; n-- > (u_p + 1)/ 2;)
126 USWAP(ustack[n], ustack[u_p - 1 - n]);
127 if (isglobal)
128 clear_active_list();
129 current_addr = u_current_addr, u_current_addr = o_current_addr;
130 addr_last = u_addr_last, u_addr_last = o_addr_last;
131 SPL0();
132 return 0;
133}
134
135
136/* clear_undo_stack: clear the undo stack */
137void
138clear_undo_stack()
139{
140 line_t *lp, *ep, *tl;
141
142 while (u_p--)
143 if (ustack[u_p].type == UDEL) {
144 ep = ustack[u_p].t->q_forw;
145 for (lp = ustack[u_p].h; lp != ep; lp = tl) {
146 unmark_line_node(lp);
147 tl = lp->q_forw;
148 free(lp);
149 }
150 }
151 u_p = 0;
152 u_current_addr = current_addr;
153 u_addr_last = addr_last;
154}