xref: /csrg-svn/contrib/ed/u.c (revision 59475)
157702Sbostic /*-
257702Sbostic  * Copyright (c) 1992 The Regents of the University of California.
357702Sbostic  * All rights reserved.
457702Sbostic  *
557702Sbostic  * This code is derived from software contributed to Berkeley by
657702Sbostic  * Rodney Ruddock of the University of Guelph.
757702Sbostic  *
857702Sbostic  * %sccs.include.redist.c%
957702Sbostic  */
1057702Sbostic 
1157702Sbostic #ifndef lint
12*59475Sbostic static char sccsid[] = "@(#)u.c	5.4 (Berkeley) 04/28/93";
1357702Sbostic #endif /* not lint */
1457702Sbostic 
1557710Sbostic #include <sys/types.h>
1657710Sbostic 
1757710Sbostic #include <regex.h>
1857710Sbostic #include <setjmp.h>
1957710Sbostic #include <stdio.h>
2057710Sbostic #include <stdlib.h>
2157710Sbostic #include <string.h>
2257710Sbostic 
2358315Sbostic #ifdef DBI
2458315Sbostic #include <db.h>
2558315Sbostic #endif
2658315Sbostic 
2757702Sbostic #include "ed.h"
2857710Sbostic #include "extern.h"
2957702Sbostic 
3057702Sbostic /*
3157702Sbostic  * This restores the buffer to the state it was in just before the
3257702Sbostic  * last buffer modifying command - the global commands (with command
3357702Sbostic  * list) are looked at as one buffer modifying command. Note: this
3457702Sbostic  * just manipulates the undo stack (u_stk); x-ref u_add_stk(),
3557702Sbostic  * u_clr_stk(), d_add(), and d_do().
3657702Sbostic  */
3757702Sbostic void
3857702Sbostic u(inputt, errnum)
3957710Sbostic 	FILE *inputt;
4057710Sbostic 	int *errnum;
4157702Sbostic {
4257710Sbostic 	if (rol(inputt, errnum))
4357710Sbostic 		return;
44*59475Sbostic 	undo(); /* call even when u_stk==nil */
4557710Sbostic 	*errnum = 1;
4657710Sbostic }
4757702Sbostic 
4857702Sbostic 
49*59475Sbostic /* This function does the "real work" of the undo.
50*59475Sbostic  * It is separated out from u() so that the SIGHUP handling
51*59475Sbostic  * routine can call it without dealing with rol(), in turn so that
52*59475Sbostic  * the buffer is in a "good" state when saved to the 'ed.hup' file.
53*59475Sbostic  */
5457702Sbostic void
5557702Sbostic undo()
5657702Sbostic {
5757710Sbostic 	LINE *l_current, *l_bottom, *l_top;
5857710Sbostic 	struct u_layer *l_old_u_stk, *l_temp;
5957702Sbostic 
6058315Sbostic 	sigspecial++;
6157710Sbostic 	/* This is done because undo can be undone. */
6257710Sbostic 	l_current = u_current;
6357710Sbostic 	l_top = u_top;
6457710Sbostic 	l_bottom = u_bottom;
6557702Sbostic 
6657710Sbostic 	u_current = current;
6757710Sbostic 	u_top = top;
6857710Sbostic 	u_bottom = bottom;
6957702Sbostic 
7057710Sbostic 	l_old_u_stk = u_stk;
7157710Sbostic 	u_stk = NULL;
7257702Sbostic 
7357710Sbostic 	while (l_old_u_stk != NULL) {
7457710Sbostic 		u_add_stk(l_old_u_stk->cell);
7557710Sbostic 		(*(l_old_u_stk->cell)) = (l_old_u_stk->val);
7657710Sbostic 		l_temp = l_old_u_stk;
7757710Sbostic 		l_old_u_stk = l_old_u_stk->below;
7857710Sbostic 		free(l_temp);
7957710Sbostic 	}
8057702Sbostic 
8157710Sbostic 	current = l_current;
8257710Sbostic 	top = l_top;
8357710Sbostic 	bottom = l_bottom;
8458315Sbostic 	sigspecial--;
8558315Sbostic 	if (sigint_flag && (!sigspecial))
8658315Sbostic 		SIGINT_ACTION;
8757710Sbostic }
8857702Sbostic 
89*59475Sbostic 
9057710Sbostic /*
9157710Sbostic  * This function should be called before u_add_stk is in each command
9257702Sbostic  * function, _except_ when the global flag is high (>0) -- otherwise,
9357702Sbostic  * we couldn't undo all of the global commands, only the last iteration
9457702Sbostic  * of the last command -- and the u command.
9557702Sbostic  * This is where we begin to dispose of ed's undo knowledge of a line.
9657702Sbostic  * The call to d_do() gets rid of the rest.
9757702Sbostic  */
9857702Sbostic void
9957702Sbostic u_clr_stk()
10057702Sbostic {
10157710Sbostic 	register struct u_layer *l_temp;
10257702Sbostic 
10357710Sbostic 	u_current = current;
10457710Sbostic 	u_top = top;
10557710Sbostic 	u_bottom = bottom;
10657702Sbostic 
10758315Sbostic 	sigspecial++;
10857710Sbostic 	/* Only if there is something to delete in the buffer. */
10957710Sbostic 	if ((u_stk) && (d_stk))
11057710Sbostic 		d_do();
11157702Sbostic 
11257710Sbostic 	while (u_stk != NULL) {
11357710Sbostic 		l_temp = u_stk;
11457710Sbostic 		u_stk = u_stk->below;
11557710Sbostic 		free(l_temp);
11657710Sbostic 	}
11757710Sbostic 	u_stk = NULL;		/* Just to sure. */
11858315Sbostic 	sigspecial--;
11958315Sbostic 	if (sigint_flag && (!sigspecial))
12058315Sbostic 		SIGINT_ACTION;
12157710Sbostic }
12257702Sbostic 
12357702Sbostic /*
12457702Sbostic  * Place the addresses of and the pointer values of the LINE structures
12557710Sbostic  * that are being changed on the undo stack.  This is a quick, simple,
12657710Sbostic  * and effective way to preserve what could be be brought back on request
12757710Sbostic  * without keeping a copy of every bleep'n thing.
12857702Sbostic  */
12957702Sbostic void
13057702Sbostic u_add_stk(in)
13157710Sbostic 	LINE **in;
13257702Sbostic {
13357710Sbostic 	register struct u_layer *l_now;
13457702Sbostic 
13557710Sbostic 	if (in == NULL)
13657710Sbostic 		return;
13757710Sbostic 	l_now = malloc(sizeof(struct u_layer));
13857710Sbostic 	if (l_now == NULL) {
13957710Sbostic 		strcpy(help_msg, "undo: out of memory error");
14057710Sbostic 		return;
14157710Sbostic 	}
14258315Sbostic 	sigspecial++;
14357710Sbostic 	if (u_stk == NULL)
14457710Sbostic 		(l_now->below) = NULL;
14557710Sbostic 	else
14657710Sbostic 		(l_now->below) = u_stk;
14757710Sbostic 	u_stk = l_now;
14857710Sbostic 	(u_stk->cell) = in;
14957710Sbostic 	(u_stk->val) = (*(u_stk->cell));
15058315Sbostic 	sigspecial--;
15158315Sbostic 	if (sigint_flag && (!sigspecial))
15258315Sbostic 		SIGINT_ACTION;
15357710Sbostic }
154*59475Sbostic 
155*59475Sbostic 
156*59475Sbostic /* This 'u' function is just for when 's' notices that a series
157*59475Sbostic  * of adjacent lines are changing. It reduces the undo stack height
158*59475Sbostic  * and lowers the number of (costly) malloc's with reuse. For
159*59475Sbostic  * the environmentally aware the third 'R' is with the 'g' code.
160*59475Sbostic  */
161*59475Sbostic 
162*59475Sbostic void
163*59475Sbostic u_pop_n_swap(in)
164*59475Sbostic 	LINE **in;
165*59475Sbostic {
166*59475Sbostic 	sigspecial++;
167*59475Sbostic 	/* put the old value back */
168*59475Sbostic 	(*(u_stk->cell)) = (u_stk->val);
169*59475Sbostic 	/* put the new values */
170*59475Sbostic 	(u_stk->cell) = in;
171*59475Sbostic 	(u_stk->val) = (*(u_stk->cell));
172*59475Sbostic 	sigspecial--;
173*59475Sbostic 	if (sigint_flag && (!sigspecial))
174*59475Sbostic 		SIGINT_ACTION;
175*59475Sbostic }
176