xref: /original-bsd/contrib/ed/d.c (revision 97bd5884)
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[] = "@(#)d.c	5.2 (Berkeley) 01/23/93";
13 #endif /* not lint */
14 
15 #include <sys/types.h>
16 
17 #include <db.h>
18 #include <regex.h>
19 #include <setjmp.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "ed.h"
25 #include "extern.h"
26 
27 static void d_add __P((LINE *, LINE *));
28 
29 /*
30  * This removes lines in the buffer from user access. The specified
31  * lines are not really deleted yet(!) as they might be called back
32  * by an undo. So the pointers from start, End, and neighbours are placed
33  * in a stack for deletion later when no undo can be performed on these lines.
34  * The lines in the buffer are freed then as well.
35  */
36 void
37 d(inputt, errnum)
38 	FILE *inputt;
39 	int *errnum;
40 {
41 	LINE *l_temp1, *l_temp2;
42 
43 	if (start_default && End_default)
44 		start = End = current;
45 	else
46 		if (start_default)
47 			start = End;
48 	if (start == NULL) {
49 		strcpy(help_msg, "bad address");
50 		*errnum = -1;
51 		return;
52 	}
53 	start_default = End_default = 0;
54 
55 	if (rol(inputt, errnum))
56 		return;
57 
58 	if ((u_set == 0) && (g_flag == 0))
59 		u_clr_stk();	/* for undo */
60 
61 	if ((start == NULL) && (End == NULL)) {	/* nothing to do... */
62 		*errnum = 1;
63 		return;
64 	}
65 	if (sigint_flag)
66 		SIGINT_ACTION;
67 
68 	d_add(start, End);	/* for buffer clearing later(!) */
69 
70 	/*
71 	 * Now change preserve the pointers in case of undo and then adjust
72 	 * them.
73 	 */
74 	if (start == top) {
75 		top = End->below;
76 		if (top != NULL) {
77 			u_add_stk(&(top->above));
78 			(top->above) = NULL;
79 		}
80 	} else {
81 		l_temp1 = start->above;
82 		u_add_stk(&(l_temp1->below));
83 		(l_temp1->below) = End->below;
84 	}
85 
86 	if (End == bottom) {
87 		bottom = start->above;
88 		current = bottom;
89 	} else {
90 		l_temp2 = End->below;
91 		u_add_stk(&(l_temp2->above));
92 		(l_temp2->above) = start->above;
93 		current = l_temp2;
94 	}
95 
96 	/* To keep track of the marks. */
97 	ku_chk(start, End, NULL);
98 	change_flag = 1L;
99 
100 	if (sigint_flag)	/* next stable spot */
101 		SIGINT_ACTION;
102 
103 	if (start == End) {
104 		*errnum = 1;
105 		return;
106 	}
107 	*errnum = 1;
108 }
109 
110 
111 /*
112  * This keeps a stack of the start and end lines deleted for clean-up
113  * later (in d_do()). A stack is used because of the global commands.
114  */
115 static void
116 d_add(top_d, bottom_d)
117 	LINE *top_d, *bottom_d;
118 {
119 	struct d_layer *l_temp;
120 
121 	l_temp = malloc(sizeof(struct d_layer));
122 	(l_temp->begin) = top_d;
123 	(l_temp->end) = bottom_d;
124 	(l_temp->next) = d_stk;
125 	d_stk = l_temp;
126 
127 }
128 
129 /*
130  * This cleans up the LINE structures deleted and no longer accessible
131  * to undo. It performs garbage clean-up on the now non-referenced
132  * text in the buffer.
133  */
134 void
135 d_do()
136 {
137 	struct d_layer *l_temp;
138 	DBT l_db_key;
139 	LINE *l_temp2, *l_temp3;
140 	int l_flag;
141 
142 	l_temp = d_stk;
143 	do {
144 		l_flag = 0;
145 		l_temp2 = l_temp->begin;
146 		do {
147 			l_temp3 = l_temp2;
148 			/*
149 			 * We do it, but db(3) says it doesn't really do it
150 			 * yet.
151 			 */
152 			l_db_key.size = sizeof(recno_t);
153 			l_db_key.data = &(l_temp2->handle);
154 			(dbhtmp->del) (dbhtmp, &l_db_key, (u_int) 0);
155 			if ((l_temp->end) == l_temp2)
156 				l_flag = 1;
157 			l_temp2 = l_temp3->below;
158 			free(l_temp3);
159 		} while (l_flag == 0);
160 
161 		d_stk = d_stk->next;
162 		free(l_temp);
163 		l_temp = d_stk;
164 	} while (d_stk);
165 
166 	d_stk = NULL;		/* just to be sure */
167 }
168