window(1): Remove __RCSID & friends.
[dragonfly.git] / usr.bin / window / cmd7.c
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 = 0;
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)) == 0)
249                 return;
250         yp->link = 0;
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 }