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 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 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 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 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 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