xref: /original-bsd/contrib/ed/u.c (revision 50ed812d)
1 /*-
2  * Copyright (c) 1992 The Regents of the University of California.
3  * 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	5.4 (Berkeley) 04/28/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 /*
31  * This restores the buffer to the state it was in just before the
32  * last buffer modifying command - the global commands (with command
33  * list) are looked at as one buffer modifying command. Note: this
34  * just manipulates the undo stack (u_stk); x-ref u_add_stk(),
35  * u_clr_stk(), d_add(), and d_do().
36  */
37 void
38 u(inputt, errnum)
39 	FILE *inputt;
40 	int *errnum;
41 {
42 	if (rol(inputt, errnum))
43 		return;
44 	undo(); /* call even when u_stk==nil */
45 	*errnum = 1;
46 }
47 
48 
49 /* This function does the "real work" of the undo.
50  * It is separated out from u() so that the SIGHUP handling
51  * routine can call it without dealing with rol(), in turn so that
52  * the buffer is in a "good" state when saved to the 'ed.hup' file.
53  */
54 void
55 undo()
56 {
57 	LINE *l_current, *l_bottom, *l_top;
58 	struct u_layer *l_old_u_stk, *l_temp;
59 
60 	sigspecial++;
61 	/* This is done because undo can be undone. */
62 	l_current = u_current;
63 	l_top = u_top;
64 	l_bottom = u_bottom;
65 
66 	u_current = current;
67 	u_top = top;
68 	u_bottom = bottom;
69 
70 	l_old_u_stk = u_stk;
71 	u_stk = NULL;
72 
73 	while (l_old_u_stk != NULL) {
74 		u_add_stk(l_old_u_stk->cell);
75 		(*(l_old_u_stk->cell)) = (l_old_u_stk->val);
76 		l_temp = l_old_u_stk;
77 		l_old_u_stk = l_old_u_stk->below;
78 		free(l_temp);
79 	}
80 
81 	current = l_current;
82 	top = l_top;
83 	bottom = l_bottom;
84 	sigspecial--;
85 	if (sigint_flag && (!sigspecial))
86 		SIGINT_ACTION;
87 }
88 
89 
90 /*
91  * This function should be called before u_add_stk is in each command
92  * function, _except_ when the global flag is high (>0) -- otherwise,
93  * we couldn't undo all of the global commands, only the last iteration
94  * of the last command -- and the u command.
95  * This is where we begin to dispose of ed's undo knowledge of a line.
96  * The call to d_do() gets rid of the rest.
97  */
98 void
99 u_clr_stk()
100 {
101 	register struct u_layer *l_temp;
102 
103 	u_current = current;
104 	u_top = top;
105 	u_bottom = bottom;
106 
107 	sigspecial++;
108 	/* Only if there is something to delete in the buffer. */
109 	if ((u_stk) && (d_stk))
110 		d_do();
111 
112 	while (u_stk != NULL) {
113 		l_temp = u_stk;
114 		u_stk = u_stk->below;
115 		free(l_temp);
116 	}
117 	u_stk = NULL;		/* Just to sure. */
118 	sigspecial--;
119 	if (sigint_flag && (!sigspecial))
120 		SIGINT_ACTION;
121 }
122 
123 /*
124  * Place the addresses of and the pointer values of the LINE structures
125  * that are being changed on the undo stack.  This is a quick, simple,
126  * and effective way to preserve what could be be brought back on request
127  * without keeping a copy of every bleep'n thing.
128  */
129 void
130 u_add_stk(in)
131 	LINE **in;
132 {
133 	register struct u_layer *l_now;
134 
135 	if (in == NULL)
136 		return;
137 	l_now = malloc(sizeof(struct u_layer));
138 	if (l_now == NULL) {
139 		strcpy(help_msg, "undo: out of memory error");
140 		return;
141 	}
142 	sigspecial++;
143 	if (u_stk == NULL)
144 		(l_now->below) = NULL;
145 	else
146 		(l_now->below) = u_stk;
147 	u_stk = l_now;
148 	(u_stk->cell) = in;
149 	(u_stk->val) = (*(u_stk->cell));
150 	sigspecial--;
151 	if (sigint_flag && (!sigspecial))
152 		SIGINT_ACTION;
153 }
154 
155 
156 /* This 'u' function is just for when 's' notices that a series
157  * of adjacent lines are changing. It reduces the undo stack height
158  * and lowers the number of (costly) malloc's with reuse. For
159  * the environmentally aware the third 'R' is with the 'g' code.
160  */
161 
162 void
163 u_pop_n_swap(in)
164 	LINE **in;
165 {
166 	sigspecial++;
167 	/* put the old value back */
168 	(*(u_stk->cell)) = (u_stk->val);
169 	/* put the new values */
170 	(u_stk->cell) = in;
171 	(u_stk->val) = (*(u_stk->cell));
172 	sigspecial--;
173 	if (sigint_flag && (!sigspecial))
174 		SIGINT_ACTION;
175 }
176