157702Sbostic /*-
2*60663Sbostic * Copyright (c) 1992, 1993
3*60663Sbostic * The Regents of the University of California. 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*60663Sbostic static char sccsid[] = "@(#)u.c 8.1 (Berkeley) 05/31/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
3059915Sbostic struct d_layer *old_d_stk=NULL;
3159915Sbostic
3259915Sbostic
3357702Sbostic /*
3457702Sbostic * This restores the buffer to the state it was in just before the
3557702Sbostic * last buffer modifying command - the global commands (with command
3657702Sbostic * list) are looked at as one buffer modifying command. Note: this
3757702Sbostic * just manipulates the undo stack (u_stk); x-ref u_add_stk(),
3857702Sbostic * u_clr_stk(), d_add(), and d_do().
3957702Sbostic */
4057702Sbostic void
u(inputt,errnum)4157702Sbostic u(inputt, errnum)
4257710Sbostic FILE *inputt;
4357710Sbostic int *errnum;
4457702Sbostic {
4557710Sbostic if (rol(inputt, errnum))
4657710Sbostic return;
4759475Sbostic undo(); /* call even when u_stk==nil */
4857710Sbostic *errnum = 1;
4957710Sbostic }
5057702Sbostic
5157702Sbostic
5259475Sbostic /* This function does the "real work" of the undo.
5359475Sbostic * It is separated out from u() so that the SIGHUP handling
5459475Sbostic * routine can call it without dealing with rol(), in turn so that
5559475Sbostic * the buffer is in a "good" state when saved to the 'ed.hup' file.
5659475Sbostic */
5757702Sbostic void
undo()5857702Sbostic undo()
5957702Sbostic {
6057710Sbostic LINE *l_current, *l_bottom, *l_top;
6157710Sbostic struct u_layer *l_old_u_stk, *l_temp;
6259915Sbostic struct d_layer *l_d_temp;
6357702Sbostic
6458315Sbostic sigspecial++;
6557710Sbostic /* This is done because undo can be undone. */
6657710Sbostic l_current = u_current;
6757710Sbostic l_top = u_top;
6857710Sbostic l_bottom = u_bottom;
6957702Sbostic
7057710Sbostic u_current = current;
7157710Sbostic u_top = top;
7257710Sbostic u_bottom = bottom;
7357702Sbostic
7459915Sbostic l_d_temp = old_d_stk;
7559915Sbostic old_d_stk = d_stk;
7659915Sbostic d_stk = l_d_temp;
7759915Sbostic
7857710Sbostic l_old_u_stk = u_stk;
7957710Sbostic u_stk = NULL;
8057702Sbostic
8157710Sbostic while (l_old_u_stk != NULL) {
8257710Sbostic u_add_stk(l_old_u_stk->cell);
8357710Sbostic (*(l_old_u_stk->cell)) = (l_old_u_stk->val);
8457710Sbostic l_temp = l_old_u_stk;
8557710Sbostic l_old_u_stk = l_old_u_stk->below;
8657710Sbostic free(l_temp);
8757710Sbostic }
8857702Sbostic
8957710Sbostic current = l_current;
9057710Sbostic top = l_top;
9157710Sbostic bottom = l_bottom;
9258315Sbostic sigspecial--;
9358315Sbostic if (sigint_flag && (!sigspecial))
9458315Sbostic SIGINT_ACTION;
9557710Sbostic }
9657702Sbostic
9759475Sbostic
9857710Sbostic /*
9957710Sbostic * This function should be called before u_add_stk is in each command
10057702Sbostic * function, _except_ when the global flag is high (>0) -- otherwise,
10157702Sbostic * we couldn't undo all of the global commands, only the last iteration
10257702Sbostic * of the last command -- and the u command.
10357702Sbostic * This is where we begin to dispose of ed's undo knowledge of a line.
10457702Sbostic * The call to d_do() gets rid of the rest.
10557702Sbostic */
10657702Sbostic void
u_clr_stk()10757702Sbostic u_clr_stk()
10857702Sbostic {
10957710Sbostic register struct u_layer *l_temp;
11057702Sbostic
11157710Sbostic u_current = current;
11257710Sbostic u_top = top;
11357710Sbostic u_bottom = bottom;
11457702Sbostic
11558315Sbostic sigspecial++;
11657710Sbostic /* Only if there is something to delete in the buffer. */
11757710Sbostic if ((u_stk) && (d_stk))
11857710Sbostic d_do();
11957702Sbostic
12057710Sbostic while (u_stk != NULL) {
12157710Sbostic l_temp = u_stk;
12257710Sbostic u_stk = u_stk->below;
12357710Sbostic free(l_temp);
12457710Sbostic }
12557710Sbostic u_stk = NULL; /* Just to sure. */
12659915Sbostic old_d_stk = NULL; /* so something in use isn't freed! */
12758315Sbostic sigspecial--;
12858315Sbostic if (sigint_flag && (!sigspecial))
12958315Sbostic SIGINT_ACTION;
13057710Sbostic }
13157702Sbostic
13257702Sbostic /*
13357702Sbostic * Place the addresses of and the pointer values of the LINE structures
13457710Sbostic * that are being changed on the undo stack. This is a quick, simple,
13557710Sbostic * and effective way to preserve what could be be brought back on request
13657710Sbostic * without keeping a copy of every bleep'n thing.
13757702Sbostic */
13857702Sbostic void
u_add_stk(in)13957702Sbostic u_add_stk(in)
14057710Sbostic LINE **in;
14157702Sbostic {
14257710Sbostic register struct u_layer *l_now;
14357702Sbostic
14457710Sbostic if (in == NULL)
14557710Sbostic return;
14657710Sbostic l_now = malloc(sizeof(struct u_layer));
14757710Sbostic if (l_now == NULL) {
14857710Sbostic strcpy(help_msg, "undo: out of memory error");
14957710Sbostic return;
15057710Sbostic }
15158315Sbostic sigspecial++;
15257710Sbostic if (u_stk == NULL)
15357710Sbostic (l_now->below) = NULL;
15457710Sbostic else
15557710Sbostic (l_now->below) = u_stk;
15657710Sbostic u_stk = l_now;
15757710Sbostic (u_stk->cell) = in;
15857710Sbostic (u_stk->val) = (*(u_stk->cell));
15958315Sbostic sigspecial--;
16058315Sbostic if (sigint_flag && (!sigspecial))
16158315Sbostic SIGINT_ACTION;
16257710Sbostic }
16359475Sbostic
16459475Sbostic
16559475Sbostic /* This 'u' function is just for when 's' notices that a series
16659475Sbostic * of adjacent lines are changing. It reduces the undo stack height
16759475Sbostic * and lowers the number of (costly) malloc's with reuse. For
16859475Sbostic * the environmentally aware the third 'R' is with the 'g' code.
16959475Sbostic */
17059475Sbostic
17159475Sbostic void
u_pop_n_swap(in)17259475Sbostic u_pop_n_swap(in)
17359475Sbostic LINE **in;
17459475Sbostic {
17559475Sbostic sigspecial++;
17659475Sbostic /* put the old value back */
17759475Sbostic (*(u_stk->cell)) = (u_stk->val);
17859475Sbostic /* put the new values */
17959475Sbostic (u_stk->cell) = in;
18059475Sbostic (u_stk->val) = (*(u_stk->cell));
18159475Sbostic sigspecial--;
18259475Sbostic if (sigint_flag && (!sigspecial))
18359475Sbostic SIGINT_ACTION;
18459475Sbostic }
185