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