xref: /dragonfly/usr.bin/window/cmd7.c (revision a632cd2d33eae3cdf365948061576a303057c733)
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
c_size(struct ww * w)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
c_yank(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
yank_highlight(int row1,int col1,int row2,int col2)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
yank_highlight_line(int r,int c,int cend)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
unyank(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
yank_line(int r,int c,int cend)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
c_put(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