undo.c revision 50471
11057Salm/* undo.c: This file contains the undo routines for the ed line editor */
21057Salm/*-
31057Salm * Copyright (c) 1993 Andrew Moore, Talke Studio.
41057Salm * All rights reserved.
51057Salm *
61057Salm * Redistribution and use in source and binary forms, with or without
71057Salm * modification, are permitted provided that the following conditions
81057Salm * are met:
91057Salm * 1. Redistributions of source code must retain the above copyright
101057Salm *    notice, this list of conditions and the following disclaimer.
111057Salm * 2. Redistributions in binary form must reproduce the above copyright
121057Salm *    notice, this list of conditions and the following disclaimer in the
131057Salm *    documentation and/or other materials provided with the distribution.
141057Salm *
151057Salm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161057Salm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171057Salm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181057Salm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191057Salm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201057Salm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211057Salm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221057Salm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231057Salm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241057Salm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251057Salm * SUCH DAMAGE.
261057Salm */
271057Salm
281057Salm#ifndef lint
2927963Ssteve#if 0
3020420Sstevestatic char * const rcsid = "@(#)undo.c,v 1.1 1994/02/01 00:34:44 alm Exp";
3127963Ssteve#else
3227963Sstevestatic char * const rcsid =
3350471Speter  "$FreeBSD: head/bin/ed/undo.c 50471 1999-08-27 23:15:48Z peter $";
3427963Ssteve#endif
351057Salm#endif /* not lint */
361057Salm
371057Salm#include "ed.h"
381057Salm
391057Salm
401057Salm#define USIZE 100				/* undo stack size */
411057Salmundo_t *ustack = NULL;				/* undo stack */
421057Salmlong usize = 0;					/* stack size variable */
431057Salmlong u_p = 0;					/* undo stack pointer */
441057Salm
4546684Skris/* push_undo_stack: return pointer to initialized undo node */
461057Salmundo_t *
471057Salmpush_undo_stack(type, from, to)
481057Salm	int type;
491057Salm	long from;
501057Salm	long to;
511057Salm{
521057Salm	undo_t *t;
531057Salm
541057Salm#if defined(sun) || defined(NO_REALLOC_NULL)
551057Salm	if (ustack == NULL &&
561057Salm	    (ustack = (undo_t *) malloc((usize = USIZE) * sizeof(undo_t))) == NULL) {
571057Salm		fprintf(stderr, "%s\n", strerror(errno));
581057Salm		sprintf(errmsg, "out of memory");
591057Salm		return NULL;
601057Salm	}
611057Salm#endif
621057Salm	t = ustack;
631057Salm	if (u_p < usize ||
641057Salm	    (t = (undo_t *) realloc(ustack, (usize += USIZE) * sizeof(undo_t))) != NULL) {
651057Salm		ustack = t;
661057Salm		ustack[u_p].type = type;
671057Salm		ustack[u_p].t = get_addressed_line_node(to);
681057Salm		ustack[u_p].h = get_addressed_line_node(from);
691057Salm		return ustack + u_p++;
701057Salm	}
711057Salm	/* out of memory - release undo stack */
721057Salm	fprintf(stderr, "%s\n", strerror(errno));
731057Salm	sprintf(errmsg, "out of memory");
741057Salm	clear_undo_stack();
751057Salm	free(ustack);
761057Salm	ustack = NULL;
771057Salm	usize = 0;
781057Salm	return NULL;
791057Salm}
801057Salm
811057Salm
821057Salm/* USWAP: swap undo nodes */
831057Salm#define USWAP(x,y) { \
841057Salm	undo_t utmp; \
851057Salm	utmp = x, x = y, y = utmp; \
861057Salm}
871057Salm
881057Salm
891057Salmlong u_current_addr = -1;	/* if >= 0, undo enabled */
901057Salmlong u_addr_last = -1;		/* if >= 0, undo enabled */
911057Salm
921057Salm/* pop_undo_stack: undo last change to the editor buffer */
931057Salmint
941057Salmpop_undo_stack()
951057Salm{
961057Salm	long n;
971057Salm	long o_current_addr = current_addr;
981057Salm	long o_addr_last = addr_last;
991057Salm
1001057Salm	if (u_current_addr == -1 || u_addr_last == -1) {
1011057Salm		sprintf(errmsg, "nothing to undo");
1021057Salm		return ERR;
1031057Salm	} else if (u_p)
1041057Salm		modified = 1;
1051057Salm	get_addressed_line_node(0);	/* this get_addressed_line_node last! */
1061057Salm	SPL1();
1071057Salm	for (n = u_p; n-- > 0;) {
1081057Salm		switch(ustack[n].type) {
1091057Salm		case UADD:
1101057Salm			REQUE(ustack[n].h->q_back, ustack[n].t->q_forw);
1111057Salm			break;
1121057Salm		case UDEL:
1131057Salm			REQUE(ustack[n].h->q_back, ustack[n].h);
1141057Salm			REQUE(ustack[n].t, ustack[n].t->q_forw);
1151057Salm			break;
1161057Salm		case UMOV:
1171057Salm		case VMOV:
1181057Salm			REQUE(ustack[n - 1].h, ustack[n].h->q_forw);
1191057Salm			REQUE(ustack[n].t->q_back, ustack[n - 1].t);
1201057Salm			REQUE(ustack[n].h, ustack[n].t);
1211057Salm			n--;
1221057Salm			break;
1231057Salm		default:
1241057Salm			/*NOTREACHED*/
1251057Salm			;
1261057Salm		}
1271057Salm		ustack[n].type ^= 1;
1281057Salm	}
1291057Salm	/* reverse undo stack order */
1301057Salm	for (n = u_p; n-- > (u_p + 1)/ 2;)
1311057Salm		USWAP(ustack[n], ustack[u_p - 1 - n]);
1321057Salm	if (isglobal)
1331057Salm		clear_active_list();
1341057Salm	current_addr = u_current_addr, u_current_addr = o_current_addr;
1351057Salm	addr_last = u_addr_last, u_addr_last = o_addr_last;
1361057Salm	SPL0();
1371057Salm	return 0;
1381057Salm}
1391057Salm
1401057Salm
1411057Salm/* clear_undo_stack: clear the undo stack */
1421057Salmvoid
1431057Salmclear_undo_stack()
1441057Salm{
1451057Salm	line_t *lp, *ep, *tl;
1461057Salm
1471057Salm	while (u_p--)
1481057Salm		if (ustack[u_p].type == UDEL) {
1491057Salm			ep = ustack[u_p].t->q_forw;
1501057Salm			for (lp = ustack[u_p].h; lp != ep; lp = tl) {
1511057Salm				unmark_line_node(lp);
1521057Salm				tl = lp->q_forw;
1531057Salm				free(lp);
1541057Salm			}
1551057Salm		}
1561057Salm	u_p = 0;
1571057Salm	u_current_addr = current_addr;
1581057Salm	u_addr_last = addr_last;
1591057Salm}
160