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.3 (Berkeley) 02/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 45 if (u_stk == NULL) { 46 *errnum = 1; 47 return; 48 } 49 undo(); 50 *errnum = 1; 51 } 52 53 54 /* This function does the "real work" of the undo. */ 55 void 56 undo() 57 { 58 LINE *l_current, *l_bottom, *l_top; 59 struct u_layer *l_old_u_stk, *l_temp; 60 61 sigspecial++; 62 /* This is done because undo can be undone. */ 63 l_current = u_current; 64 l_top = u_top; 65 l_bottom = u_bottom; 66 67 u_current = current; 68 u_top = top; 69 u_bottom = bottom; 70 71 l_old_u_stk = u_stk; 72 u_stk = NULL; 73 74 while (l_old_u_stk != NULL) { 75 u_add_stk(l_old_u_stk->cell); 76 (*(l_old_u_stk->cell)) = (l_old_u_stk->val); 77 l_temp = l_old_u_stk; 78 l_old_u_stk = l_old_u_stk->below; 79 free(l_temp); 80 } 81 82 current = l_current; 83 top = l_top; 84 bottom = l_bottom; 85 sigspecial--; 86 if (sigint_flag && (!sigspecial)) 87 SIGINT_ACTION; 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