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