undo.c revision 46684
11573Srgrimes/* undo.c: This file contains the undo routines for the ed line editor */ 21573Srgrimes/*- 31573Srgrimes * Copyright (c) 1993 Andrew Moore, Talke Studio. 41573Srgrimes * All rights reserved. 51573Srgrimes * 61573Srgrimes * Redistribution and use in source and binary forms, with or without 71573Srgrimes * modification, are permitted provided that the following conditions 81573Srgrimes * are met: 91573Srgrimes * 1. Redistributions of source code must retain the above copyright 101573Srgrimes * notice, this list of conditions and the following disclaimer. 111573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer in the 131573Srgrimes * documentation and/or other materials provided with the distribution. 141573Srgrimes * 151573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 191573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251573Srgrimes * SUCH DAMAGE. 261573Srgrimes */ 271573Srgrimes 281573Srgrimes#ifndef lint 291573Srgrimes#if 0 301573Srgrimesstatic char * const rcsid = "@(#)undo.c,v 1.1 1994/02/01 00:34:44 alm Exp"; 311573Srgrimes#else 321573Srgrimesstatic char * const rcsid = 331573Srgrimes "$Id: undo.c,v 1.7 1997/08/07 21:33:47 steve Exp $"; 341573Srgrimes#endif 351573Srgrimes#endif /* not lint */ 361573Srgrimes 371573Srgrimes#include "ed.h" 381573Srgrimes 391573Srgrimes 401573Srgrimes#define USIZE 100 /* undo stack size */ 411573Srgrimesundo_t *ustack = NULL; /* undo stack */ 421573Srgrimeslong usize = 0; /* stack size variable */ 431573Srgrimeslong u_p = 0; /* undo stack pointer */ 441573Srgrimes 451573Srgrimes/* push_undo_stack: return pointer to initialized undo node */ 461573Srgrimesundo_t * 471573Srgrimespush_undo_stack(type, from, to) 481573Srgrimes int type; 491573Srgrimes long from; 501573Srgrimes long to; 511573Srgrimes{ 521573Srgrimes undo_t *t; 531573Srgrimes 541573Srgrimes#if defined(sun) || defined(NO_REALLOC_NULL) 551573Srgrimes if (ustack == NULL && 561573Srgrimes (ustack = (undo_t *) malloc((usize = USIZE) * sizeof(undo_t))) == NULL) { 571573Srgrimes fprintf(stderr, "%s\n", strerror(errno)); 581573Srgrimes sprintf(errmsg, "out of memory"); 591573Srgrimes return NULL; 601573Srgrimes } 611573Srgrimes#endif 621573Srgrimes t = ustack; 631573Srgrimes if (u_p < usize || 641573Srgrimes (t = (undo_t *) realloc(ustack, (usize += USIZE) * sizeof(undo_t))) != NULL) { 651573Srgrimes ustack = t; 661573Srgrimes ustack[u_p].type = type; 671573Srgrimes ustack[u_p].t = get_addressed_line_node(to); 681573Srgrimes ustack[u_p].h = get_addressed_line_node(from); 691573Srgrimes return ustack + u_p++; 701573Srgrimes } 711573Srgrimes /* out of memory - release undo stack */ 721573Srgrimes fprintf(stderr, "%s\n", strerror(errno)); 731573Srgrimes sprintf(errmsg, "out of memory"); 741573Srgrimes clear_undo_stack(); 751573Srgrimes free(ustack); 761573Srgrimes ustack = NULL; 771573Srgrimes usize = 0; 781573Srgrimes return NULL; 791573Srgrimes} 801573Srgrimes 811573Srgrimes 821573Srgrimes/* USWAP: swap undo nodes */ 831573Srgrimes#define USWAP(x,y) { \ 841573Srgrimes undo_t utmp; \ 851573Srgrimes utmp = x, x = y, y = utmp; \ 861573Srgrimes} 871573Srgrimes 881573Srgrimes 891573Srgrimeslong u_current_addr = -1; /* if >= 0, undo enabled */ 908870Srgrimeslong u_addr_last = -1; /* if >= 0, undo enabled */ 911573Srgrimes 921573Srgrimes/* pop_undo_stack: undo last change to the editor buffer */ 931573Srgrimesint 941573Srgrimespop_undo_stack() 951573Srgrimes{ 961573Srgrimes long n; 971573Srgrimes long o_current_addr = current_addr; 981573Srgrimes long o_addr_last = addr_last; 991573Srgrimes 1001573Srgrimes if (u_current_addr == -1 || u_addr_last == -1) { 1011573Srgrimes sprintf(errmsg, "nothing to undo"); 1021573Srgrimes return ERR; 1031573Srgrimes } else if (u_p) 1041573Srgrimes modified = 1; 1051573Srgrimes get_addressed_line_node(0); /* this get_addressed_line_node last! */ 1061573Srgrimes SPL1(); 1071573Srgrimes for (n = u_p; n-- > 0;) { 1081573Srgrimes switch(ustack[n].type) { 1091573Srgrimes case UADD: 1101573Srgrimes REQUE(ustack[n].h->q_back, ustack[n].t->q_forw); 1111573Srgrimes break; 1121573Srgrimes case UDEL: 1131573Srgrimes REQUE(ustack[n].h->q_back, ustack[n].h); 1141573Srgrimes REQUE(ustack[n].t, ustack[n].t->q_forw); 1151573Srgrimes break; 1161573Srgrimes case UMOV: 1171573Srgrimes case VMOV: 1181573Srgrimes REQUE(ustack[n - 1].h, ustack[n].h->q_forw); 1191573Srgrimes REQUE(ustack[n].t->q_back, ustack[n - 1].t); 1201573Srgrimes REQUE(ustack[n].h, ustack[n].t); 1211573Srgrimes n--; 1221573Srgrimes break; 1231573Srgrimes default: 1241573Srgrimes /*NOTREACHED*/ 1251573Srgrimes ; 1261573Srgrimes } 1271573Srgrimes ustack[n].type ^= 1; 1281573Srgrimes } 1291573Srgrimes /* reverse undo stack order */ 1301573Srgrimes for (n = u_p; n-- > (u_p + 1)/ 2;) 1311573Srgrimes USWAP(ustack[n], ustack[u_p - 1 - n]); 1321573Srgrimes if (isglobal) 1331573Srgrimes clear_active_list(); 1341573Srgrimes current_addr = u_current_addr, u_current_addr = o_current_addr; 1351573Srgrimes addr_last = u_addr_last, u_addr_last = o_addr_last; 1361573Srgrimes SPL0(); 1371573Srgrimes return 0; 1381573Srgrimes} 1391573Srgrimes 1401573Srgrimes 1411573Srgrimes/* clear_undo_stack: clear the undo stack */ 1421573Srgrimesvoid 1431573Srgrimesclear_undo_stack() 1441573Srgrimes{ 1451573Srgrimes line_t *lp, *ep, *tl; 1461573Srgrimes 1471573Srgrimes while (u_p--) 1481573Srgrimes if (ustack[u_p].type == UDEL) { 1491573Srgrimes ep = ustack[u_p].t->q_forw; 1501573Srgrimes for (lp = ustack[u_p].h; lp != ep; lp = tl) { 1511573Srgrimes unmark_line_node(lp); 1521573Srgrimes tl = lp->q_forw; 1531573Srgrimes free(lp); 1541573Srgrimes } 1551573Srgrimes } 1561573Srgrimes u_p = 0; 1571573Srgrimes u_current_addr = current_addr; 1581573Srgrimes u_addr_last = addr_last; 1591573Srgrimes} 1601573Srgrimes