xref: /original-bsd/contrib/ed/u.c (revision beb7df4f)
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