Merge from vendor branch LIBARCHIVE:
[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  * @(#)cmd7.c   8.1 (Berkeley) 6/6/93
37  * $FreeBSD: src/usr.bin/window/cmd7.c,v 1.2.6.2 2001/05/17 09:45:00 obrien Exp $
38  * $DragonFly: src/usr.bin/window/cmd7.c,v 1.3 2005/04/15 17:55:29 drhodus Exp $
39  */
40
41 #include <stdlib.h>
42 #include "defs.h"
43 #include "mystring.h"
44
45 /*
46  * Window size.
47  */
48
49 c_size(w)
50 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 c_yank()
100 {
101         struct ww *w = selwin;
102         int col1, row1;
103         int col2, row2;
104         int r, c;
105
106         if (!terse)
107                 wwputs("Yank starting position: ", cmdwin);
108         wwcursor(w, 0);
109         row1 = w->ww_cur.r;
110         col1 = w->ww_cur.c;
111         for (;;) {
112                 wwsetcursor(row1, col1);
113                 while (wwpeekc() < 0)
114                         wwiomux();
115                 switch (getpos(&row1, &col1, w->ww_i.t, w->ww_i.l,
116                                w->ww_i.b - 1, w->ww_i.r - 1)) {
117                 case 3:
118                         goto out;
119                 case 2:
120                         break;
121                 case 1:
122                 case 0:
123                         continue;
124                 }
125                 break;
126         }
127         if (!terse)
128                 wwputs("\nYank ending position: ", cmdwin);
129         row2 = row1;
130         col2 = col1;
131         for (;;) {
132                 wwsetcursor(row2, col2);
133                 while (wwpeekc() < 0)
134                         wwiomux();
135                 r = row2;
136                 c = col2;
137                 switch (getpos(&row2, &col2, w->ww_i.t, w->ww_i.l,
138                                w->ww_i.b - 1, w->ww_i.r - 1)) {
139                 case 3:
140                         yank_highlight(row1, col1, r, c);
141                         goto out;
142                 case 2:
143                         break;
144                 case 1:
145                         yank_highlight(row1, col1, r, c);
146                         yank_highlight(row1, col1, row2, col2);
147                 case 0:
148                         continue;
149                 }
150                 break;
151         }
152         if (row2 < row1 || row2 == row1 && col2 < col1) {
153                 r = row1;
154                 c = col1;
155                 row1 = row2;
156                 col1 = col2;
157                 row2 = r;
158                 col2 = c;
159         }
160         unyank();
161         c = col1;
162         for (r = row1; r < row2; r++) {
163                 yank_line(r, c, w->ww_b.r);
164                 c = w->ww_b.l;
165         }
166         yank_line(r, c, col2);
167         yank_highlight(row1, col1, row2, col2);
168         if (!terse)
169                 wwputc('\n', cmdwin);
170 out:
171         wwcursor(w, 1);
172 }
173
174 yank_highlight(row1, col1, row2, col2)
175 {
176         struct ww *w = selwin;
177         int r, c;
178
179         if ((wwavailmodes & WWM_REV) == 0)
180                 return;
181         if (row2 < row1 || row2 == row1 && col2 < col1) {
182                 r = row1;
183                 c = col1;
184                 row1 = row2;
185                 col1 = col2;
186                 row2 = r;
187                 col2 = c;
188         }
189         c = col1;
190         for (r = row1; r < row2; r++) {
191                 yank_highlight_line(r, c, w->ww_b.r);
192                 c = w->ww_b.l;
193         }
194         yank_highlight_line(r, c, col2);
195 }
196
197 yank_highlight_line(r, c, cend)
198 {
199         struct ww *w = selwin;
200         char *win;
201
202         if (r < w->ww_i.t || r >= w->ww_i.b)
203                 return;
204         if (c < w->ww_i.l)
205                 c = w->ww_i.l;
206         if (cend >= w->ww_i.r)
207                 cend = w->ww_i.r;
208         for (win = w->ww_win[r] + c; c < cend; c++, win++) {
209                 *win ^= WWM_REV;
210                 if (wwsmap[r][c] == w->ww_index) {
211                         if (*win == 0)
212                                 w->ww_nvis[r]++;
213                         else if (*win == WWM_REV)
214                                 w->ww_nvis[r]--;
215                         wwns[r][c].c_m ^= WWM_REV;
216                         wwtouched[r] |= WWU_TOUCHED;
217                 }
218         }
219 }
220
221 unyank()
222 {
223         struct yb *yp, *yq;
224
225         for (yp = yb_head; yp; yp = yq) {
226                 yq = yp->link;
227                 str_free(yp->line);
228                 free((char *) yp);
229         }
230         yb_head = yb_tail = 0;
231 }
232
233 yank_line(r, c, cend)
234 {
235         struct yb *yp;
236         int nl = 0;
237         int n;
238         union ww_char *bp;
239         char *cp;
240
241         if (c == cend)
242                 return;
243         if ((yp = (struct yb *) malloc(sizeof *yp)) == 0)
244                 return;
245         yp->link = 0;
246         nl = cend == selwin->ww_b.r;
247         bp = selwin->ww_buf[r];
248         for (cend--; cend >= c; cend--)
249                 if (bp[cend].c_c != ' ')
250                         break;
251         yp->length = n = cend - c + 1;
252         if (nl)
253                 yp->length++;
254         yp->line = str_alloc(yp->length + 1);
255         for (bp += c, cp = yp->line; --n >= 0;)
256                 *cp++ = bp++->c_c;
257         if (nl)
258                 *cp++ = '\n';
259         *cp = 0;
260         if (yb_head)
261                 yb_tail = yb_tail->link = yp;
262         else
263                 yb_head = yb_tail = yp;
264 }
265
266 c_put()
267 {
268         struct yb *yp;
269
270         for (yp = yb_head; yp; yp = yp->link)
271                 (void) write(selwin->ww_pty, yp->line, yp->length);
272 }