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