1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rodney Ruddock of the University of Guelph.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char sccsid[] = "@(#)u.c 8.1 (Berkeley) 05/31/93";
13 #endif /* not lint */
14
15 #include <sys/types.h>
16
17 #include <regex.h>
18 #include <setjmp.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #ifdef DBI
24 #include <db.h>
25 #endif
26
27 #include "ed.h"
28 #include "extern.h"
29
30 struct d_layer *old_d_stk=NULL;
31
32
33 /*
34 * This restores the buffer to the state it was in just before the
35 * last buffer modifying command - the global commands (with command
36 * list) are looked at as one buffer modifying command. Note: this
37 * just manipulates the undo stack (u_stk); x-ref u_add_stk(),
38 * u_clr_stk(), d_add(), and d_do().
39 */
40 void
u(inputt,errnum)41 u(inputt, errnum)
42 FILE *inputt;
43 int *errnum;
44 {
45 if (rol(inputt, errnum))
46 return;
47 undo(); /* call even when u_stk==nil */
48 *errnum = 1;
49 }
50
51
52 /* This function does the "real work" of the undo.
53 * It is separated out from u() so that the SIGHUP handling
54 * routine can call it without dealing with rol(), in turn so that
55 * the buffer is in a "good" state when saved to the 'ed.hup' file.
56 */
57 void
undo()58 undo()
59 {
60 LINE *l_current, *l_bottom, *l_top;
61 struct u_layer *l_old_u_stk, *l_temp;
62 struct d_layer *l_d_temp;
63
64 sigspecial++;
65 /* This is done because undo can be undone. */
66 l_current = u_current;
67 l_top = u_top;
68 l_bottom = u_bottom;
69
70 u_current = current;
71 u_top = top;
72 u_bottom = bottom;
73
74 l_d_temp = old_d_stk;
75 old_d_stk = d_stk;
76 d_stk = l_d_temp;
77
78 l_old_u_stk = u_stk;
79 u_stk = NULL;
80
81 while (l_old_u_stk != NULL) {
82 u_add_stk(l_old_u_stk->cell);
83 (*(l_old_u_stk->cell)) = (l_old_u_stk->val);
84 l_temp = l_old_u_stk;
85 l_old_u_stk = l_old_u_stk->below;
86 free(l_temp);
87 }
88
89 current = l_current;
90 top = l_top;
91 bottom = l_bottom;
92 sigspecial--;
93 if (sigint_flag && (!sigspecial))
94 SIGINT_ACTION;
95 }
96
97
98 /*
99 * This function should be called before u_add_stk is in each command
100 * function, _except_ when the global flag is high (>0) -- otherwise,
101 * we couldn't undo all of the global commands, only the last iteration
102 * of the last command -- and the u command.
103 * This is where we begin to dispose of ed's undo knowledge of a line.
104 * The call to d_do() gets rid of the rest.
105 */
106 void
u_clr_stk()107 u_clr_stk()
108 {
109 register struct u_layer *l_temp;
110
111 u_current = current;
112 u_top = top;
113 u_bottom = bottom;
114
115 sigspecial++;
116 /* Only if there is something to delete in the buffer. */
117 if ((u_stk) && (d_stk))
118 d_do();
119
120 while (u_stk != NULL) {
121 l_temp = u_stk;
122 u_stk = u_stk->below;
123 free(l_temp);
124 }
125 u_stk = NULL; /* Just to sure. */
126 old_d_stk = NULL; /* so something in use isn't freed! */
127 sigspecial--;
128 if (sigint_flag && (!sigspecial))
129 SIGINT_ACTION;
130 }
131
132 /*
133 * Place the addresses of and the pointer values of the LINE structures
134 * that are being changed on the undo stack. This is a quick, simple,
135 * and effective way to preserve what could be be brought back on request
136 * without keeping a copy of every bleep'n thing.
137 */
138 void
u_add_stk(in)139 u_add_stk(in)
140 LINE **in;
141 {
142 register struct u_layer *l_now;
143
144 if (in == NULL)
145 return;
146 l_now = malloc(sizeof(struct u_layer));
147 if (l_now == NULL) {
148 strcpy(help_msg, "undo: out of memory error");
149 return;
150 }
151 sigspecial++;
152 if (u_stk == NULL)
153 (l_now->below) = NULL;
154 else
155 (l_now->below) = u_stk;
156 u_stk = l_now;
157 (u_stk->cell) = in;
158 (u_stk->val) = (*(u_stk->cell));
159 sigspecial--;
160 if (sigint_flag && (!sigspecial))
161 SIGINT_ACTION;
162 }
163
164
165 /* This 'u' function is just for when 's' notices that a series
166 * of adjacent lines are changing. It reduces the undo stack height
167 * and lowers the number of (costly) malloc's with reuse. For
168 * the environmentally aware the third 'R' is with the 'g' code.
169 */
170
171 void
u_pop_n_swap(in)172 u_pop_n_swap(in)
173 LINE **in;
174 {
175 sigspecial++;
176 /* put the old value back */
177 (*(u_stk->cell)) = (u_stk->val);
178 /* put the new values */
179 (u_stk->cell) = in;
180 (u_stk->val) = (*(u_stk->cell));
181 sigspecial--;
182 if (sigint_flag && (!sigspecial))
183 SIGINT_ACTION;
184 }
185