xref: /csrg-svn/contrib/ed/u.c (revision 57710)
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.2 (Berkeley) 01/23/93";
13 #endif /* not lint */
14 
15 #include <sys/types.h>
16 
17 #include <db.h>
18 #include <regex.h>
19 #include <setjmp.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "ed.h"
25 #include "extern.h"
26 
27 /*
28  * This restores the buffer to the state it was in just before the
29  * last buffer modifying command - the global commands (with command
30  * list) are looked at as one buffer modifying command. Note: this
31  * just manipulates the undo stack (u_stk); x-ref u_add_stk(),
32  * u_clr_stk(), d_add(), and d_do().
33  */
34 void
35 u(inputt, errnum)
36 	FILE *inputt;
37 	int *errnum;
38 {
39 	if (rol(inputt, errnum))
40 		return;
41 
42 	if (u_stk == NULL) {
43 		*errnum = 1;
44 		return;
45 	}
46 	undo();
47 	*errnum = 1;
48 }
49 
50 
51 /* This function does the "real work" of the undo. */
52 void
53 undo()
54 {
55 	LINE *l_current, *l_bottom, *l_top;
56 	struct u_layer *l_old_u_stk, *l_temp;
57 
58 	/* This is done because undo can be undone. */
59 	l_current = u_current;
60 	l_top = u_top;
61 	l_bottom = u_bottom;
62 
63 	u_current = current;
64 	u_top = top;
65 	u_bottom = bottom;
66 
67 	l_old_u_stk = u_stk;
68 	u_stk = NULL;
69 
70 	while (l_old_u_stk != NULL) {
71 		u_add_stk(l_old_u_stk->cell);
72 		(*(l_old_u_stk->cell)) = (l_old_u_stk->val);
73 		l_temp = l_old_u_stk;
74 		l_old_u_stk = l_old_u_stk->below;
75 		free(l_temp);
76 	}
77 
78 	current = l_current;
79 	top = l_top;
80 	bottom = l_bottom;
81 }
82 
83 /*
84  * This function should be called before u_add_stk is in each command
85  * function, _except_ when the global flag is high (>0) -- otherwise,
86  * we couldn't undo all of the global commands, only the last iteration
87  * of the last command -- and the u command.
88  * This is where we begin to dispose of ed's undo knowledge of a line.
89  * The call to d_do() gets rid of the rest.
90  */
91 void
92 u_clr_stk()
93 {
94 	register struct u_layer *l_temp;
95 
96 	u_current = current;
97 	u_top = top;
98 	u_bottom = bottom;
99 
100 	/* Only if there is something to delete in the buffer. */
101 	if ((u_stk) && (d_stk))
102 		d_do();
103 
104 	while (u_stk != NULL) {
105 		l_temp = u_stk;
106 		u_stk = u_stk->below;
107 		free(l_temp);
108 	}
109 	u_stk = NULL;		/* Just to sure. */
110 }
111 
112 /*
113  * Place the addresses of and the pointer values of the LINE structures
114  * that are being changed on the undo stack.  This is a quick, simple,
115  * and effective way to preserve what could be be brought back on request
116  * without keeping a copy of every bleep'n thing.
117  */
118 void
119 u_add_stk(in)
120 	LINE **in;
121 {
122 	register struct u_layer *l_now;
123 
124 	if (in == NULL)
125 		return;
126 	l_now = malloc(sizeof(struct u_layer));
127 	if (l_now == NULL) {
128 		strcpy(help_msg, "undo: out of memory error");
129 		return;
130 	}
131 	if (u_stk == NULL)
132 		(l_now->below) = NULL;
133 	else
134 		(l_now->below) = u_stk;
135 	u_stk = l_now;
136 	(u_stk->cell) = in;
137 	(u_stk->val) = (*(u_stk->cell));
138 }
139