xref: /dragonfly/usr.bin/window/cmd7.c (revision d4ef6694)
1 /*	@(#)cmd7.c	8.1 (Berkeley) 6/6/93	*/
2 /*	$NetBSD: cmd7.c,v 1.8 2006/05/02 22:30:25 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1983, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Edward Wang at The University of California, Berkeley.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include "defs.h"
39 #include "window_string.h"
40 
41 void	unyank(void);
42 void	yank_highlight(int, int, int, int);
43 void	yank_highlight_line(int, int, int);
44 void	yank_line(int, int, int);
45 
46 /*
47  * Window size.
48  */
49 void
50 c_size(struct ww *w)
51 {
52 	int col, row;
53 
54 	if (!terse)
55 		wwputs("New window size (lower right corner): ", cmdwin);
56 	col = MIN(w->ww_w.r, wwncol) - 1;
57 	row = MIN(w->ww_w.b, wwnrow) - 1;
58 	wwadd(boxwin, framewin->ww_back);
59 	for (;;) {
60 		wwbox(boxwin, w->ww_w.t - 1, w->ww_w.l - 1,
61 			row - w->ww_w.t + 3, col - w->ww_w.l + 3);
62 		wwsetcursor(row, col);
63 		while (wwpeekc() < 0)
64 			wwiomux();
65 		switch (getpos(&row, &col, w->ww_w.t, w->ww_w.l,
66 			wwnrow - 1, wwncol - 1)) {
67 		case 3:
68 			wwunbox(boxwin);
69 			wwdelete(boxwin);
70 			return;
71 		case 2:
72 			wwunbox(boxwin);
73 			break;
74 		case 1:
75 			wwunbox(boxwin);
76 		case 0:
77 			continue;
78 		}
79 		break;
80 	}
81 	wwdelete(boxwin);
82 	if (!terse)
83 		wwputc('\n', cmdwin);
84 	wwcurtowin(cmdwin);
85 	sizewin(w, row - w->ww_w.t + 1, col - w->ww_w.l + 1);
86 }
87 
88 /*
89  * Yank and put
90  */
91 
92 struct yb {
93 	char *line;
94 	int length;
95 	struct yb *link;
96 };
97 struct yb *yb_head, *yb_tail;
98 
99 void
100 c_yank(void)
101 {
102 	struct ww *w = selwin;
103 	int col1, row1;
104 	int col2, row2;
105 	int r, c;
106 
107 	if (!terse)
108 		wwputs("Yank starting position: ", cmdwin);
109 	wwcursor(w, 0);
110 	row1 = w->ww_cur.r;
111 	col1 = w->ww_cur.c;
112 	for (;;) {
113 		wwsetcursor(row1, col1);
114 		while (wwpeekc() < 0)
115 			wwiomux();
116 		switch (getpos(&row1, &col1, w->ww_i.t, w->ww_i.l,
117 			       w->ww_i.b - 1, w->ww_i.r - 1)) {
118 		case 3:
119 			goto out;
120 		case 2:
121 			break;
122 		case 1:
123 		case 0:
124 			continue;
125 		}
126 		break;
127 	}
128 	if (!terse)
129 		wwputs("\nYank ending position: ", cmdwin);
130 	row2 = row1;
131 	col2 = col1;
132 	for (;;) {
133 		wwsetcursor(row2, col2);
134 		while (wwpeekc() < 0)
135 			wwiomux();
136 		r = row2;
137 		c = col2;
138 		switch (getpos(&row2, &col2, w->ww_i.t, w->ww_i.l,
139 			       w->ww_i.b - 1, w->ww_i.r - 1)) {
140 		case 3:
141 			yank_highlight(row1, col1, r, c);
142 			goto out;
143 		case 2:
144 			break;
145 		case 1:
146 			yank_highlight(row1, col1, r, c);
147 			yank_highlight(row1, col1, row2, col2);
148 		case 0:
149 			continue;
150 		}
151 		break;
152 	}
153 	if (row2 < row1 || (row2 == row1 && col2 < col1)) {
154 		r = row1;
155 		c = col1;
156 		row1 = row2;
157 		col1 = col2;
158 		row2 = r;
159 		col2 = c;
160 	}
161 	unyank();
162 	c = col1;
163 	for (r = row1; r < row2; r++) {
164 		yank_line(r, c, w->ww_b.r);
165 		c = w->ww_b.l;
166 	}
167 	yank_line(r, c, col2);
168 	yank_highlight(row1, col1, row2, col2);
169 	if (!terse)
170 		wwputc('\n', cmdwin);
171 out:
172 	wwcursor(w, 1);
173 }
174 
175 void
176 yank_highlight(int row1, int col1, int row2, int col2)
177 {
178 	struct ww *w = selwin;
179 	int r, c;
180 
181 	if ((wwavailmodes & WWM_REV) == 0)
182 		return;
183 	if (row2 < row1 || (row2 == row1 && col2 < col1)) {
184 		r = row1;
185 		c = col1;
186 		row1 = row2;
187 		col1 = col2;
188 		row2 = r;
189 		col2 = c;
190 	}
191 	c = col1;
192 	for (r = row1; r < row2; r++) {
193 		yank_highlight_line(r, c, w->ww_b.r);
194 		c = w->ww_b.l;
195 	}
196 	yank_highlight_line(r, c, col2);
197 }
198 
199 void
200 yank_highlight_line(int r, int c, int cend)
201 {
202 	struct ww *w = selwin;
203 	char *win;
204 
205 	if (r < w->ww_i.t || r >= w->ww_i.b)
206 		return;
207 	if (c < w->ww_i.l)
208 		c = w->ww_i.l;
209 	if (cend >= w->ww_i.r)
210 		cend = w->ww_i.r;
211 	for (win = w->ww_win[r] + c; c < cend; c++, win++) {
212 		*win ^= WWM_REV;
213 		if (wwsmap[r][c] == w->ww_index) {
214 			if (*win == 0)
215 				w->ww_nvis[r]++;
216 			else if (*win == WWM_REV)
217 				w->ww_nvis[r]--;
218 			wwns[r][c].c_m ^= WWM_REV;
219 			wwtouched[r] |= WWU_TOUCHED;
220 		}
221 	}
222 }
223 
224 void
225 unyank(void)
226 {
227 	struct yb *yp, *yq;
228 
229 	for (yp = yb_head; yp; yp = yq) {
230 		yq = yp->link;
231 		str_free(yp->line);
232 		free((char *) yp);
233 	}
234 	yb_head = yb_tail = NULL;
235 }
236 
237 void
238 yank_line(int r, int c, int cend)
239 {
240 	struct yb *yp;
241 	int nl = 0;
242 	int n;
243 	union ww_char *bp;
244 	char *cp;
245 
246 	if (c == cend)
247 		return;
248 	if ((yp = (struct yb *) malloc(sizeof *yp)) == NULL)
249 		return;
250 	yp->link = NULL;
251 	nl = cend == selwin->ww_b.r;
252 	bp = selwin->ww_buf[r];
253 	for (cend--; cend >= c; cend--)
254 		if (bp[cend].c_c != ' ')
255 			break;
256 	yp->length = n = cend - c + 1;
257 	if (nl)
258 		yp->length++;
259 	if ((yp->line = str_alloc(yp->length + 1)) == NULL) {
260 		free(yp);
261 		return;
262 	}
263 	for (bp += c, cp = yp->line; --n >= 0;)
264 		*cp++ = bp++->c_c;
265 	if (nl)
266 		*cp++ = '\n';
267 	*cp = 0;
268 	if (yb_head)
269 		yb_tail = yb_tail->link = yp;
270 	else
271 		yb_head = yb_tail = yp;
272 }
273 
274 void
275 c_put(void)
276 {
277 	struct yb *yp;
278 
279 	for (yp = yb_head; yp; yp = yp->link)
280 		(void) write(selwin->ww_pty, yp->line, yp->length);
281 }
282