]> git.saurik.com Git - apple/shell_cmds.git/blame - window/win.c
shell_cmds-34.tar.gz
[apple/shell_cmds.git] / window / win.c
CommitLineData
44bd5ea7
A
1/* $NetBSD: win.c,v 1.10 1998/08/25 20:59:43 ross 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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#include <sys/cdefs.h>
40#ifndef lint
41#if 0
42static char sccsid[] = "@(#)win.c 8.1 (Berkeley) 6/6/93";
43#else
44__RCSID("$NetBSD: win.c,v 1.10 1998/08/25 20:59:43 ross Exp $");
45#endif
46#endif /* not lint */
47
48#include <string.h>
49#include "defs.h"
50#include "char.h"
51#include "window_string.h"
52
53/*
54 * Higher level routines for dealing with windows.
55 *
56 * There are two types of windows: user window, and information window.
57 * User windows are the ones with a pty and shell. Information windows
58 * are for displaying error messages, and other information.
59 *
60 * The windows are doubly linked in overlapping order and divided into
61 * two groups: foreground and normal. Information
62 * windows are always foreground. User windows can be either.
63 * Addwin() adds a window to the list at the top of one of the two groups.
64 * Deletewin() deletes a window. Front() moves a window to the front
65 * of its group. Wwopen(), wwadd(), and wwdelete() should never be called
66 * directly.
67 */
68
69/*
70 * Open a user window.
71 */
72struct ww *
73openwin(id, row, col, nrow, ncol, nline, label, type, uflags, shf, sh)
74 int id, row, col, nrow, ncol, nline;
75 char *label;
76 int type, uflags;
77 char *shf, **sh;
78{
79 struct ww *w;
80
81 if (id < 0 && (id = findid()) < 0)
82 return 0;
83 if (row + nrow <= 0 || row > wwnrow - 1
84 || col + ncol <= 0 || col > wwncol - 1) {
85 error("Illegal window position.");
86 return 0;
87 }
88 w = wwopen(type, 0, nrow, ncol, row, col, nline);
89 if (w == 0) {
90 error("Can't open window: %s.", wwerror());
91 return 0;
92 }
93 w->ww_id = id;
94 window[id] = w;
95 CLR(w->ww_uflags, WWU_ALLFLAGS);
96 SET(w->ww_uflags, uflags);
97 w->ww_alt = w->ww_w;
98 if (label != 0 && setlabel(w, label) < 0)
99 error("No memory for label.");
100 wwcursor(w, 1);
101 /*
102 * We have to do this little maneuver to make sure
103 * addwin() puts w at the top, so we don't waste an
104 * insert and delete operation.
105 */
106 setselwin((struct ww *)0);
107 addwin(w, 0);
108 setselwin(w);
109 if (wwspawn(w, shf, sh) < 0) {
110 error("Can't execute %s: %s.", shf, wwerror());
111 closewin(w);
112 return 0;
113 }
114 return w;
115}
116
117int
118findid()
119{
120 int i;
121
122 for (i = 0; i < NWINDOW && window[i] != 0; i++)
123 ;
124 if (i >= NWINDOW) {
125 error("Too many windows.");
126 return -1;
127 }
128 return i;
129}
130
131struct ww *
132findselwin()
133{
134 struct ww *w, *s = 0;
135 int i;
136
137 for (i = 0; i < NWINDOW; i++)
138 if ((w = window[i]) != 0 && w != selwin &&
139 (s == 0 ||
140 (!isfg(w) && (w->ww_order < s->ww_order || isfg(s)))))
141 s = w;
142 return s;
143}
144
145/*
146 * Close a user window. Close all if w == 0.
147 */
148void
149closewin(w)
150 struct ww *w;
151{
152 char didit = 0;
153 int i;
154
155 if (w != 0) {
156 closewin1(w);
157 didit++;
158 } else
159 for (i = 0; i < NWINDOW; i++) {
160 if ((w = window[i]) == 0)
161 continue;
162 closewin1(w);
163 didit++;
164 }
165 if (didit) {
166 if (selwin == 0) {
167 if (lastselwin != 0) {
168 setselwin(lastselwin);
169 lastselwin = 0;
170 } else if ((w = findselwin()))
171 setselwin(w);
172 }
173 if (lastselwin == 0 && selwin)
174 if ((w = findselwin()))
175 lastselwin = w;
176 reframe();
177 }
178}
179
180/*
181 * Open an information (display) window.
182 */
183struct ww *
184openiwin(nrow, label)
185 int nrow;
186 char *label;
187{
188 struct ww *w;
189
190 if ((w = wwopen(WWT_INTERNAL, 0, nrow, wwncol, 2, 0, 0)) == 0)
191 return 0;
192 SET(w->ww_wflags, WWW_MAPNL | WWW_NOINTR | WWW_NOUPDATE | WWW_UNCTRL);
193 SET(w->ww_uflags, WWU_HASFRAME | WWU_CENTER);
194 w->ww_id = -1;
195 (void) setlabel(w, label);
196 addwin(w, 1);
197 reframe();
198 return w;
199}
200
201/*
202 * Close an information window.
203 */
204void
205closeiwin(w)
206 struct ww *w;
207{
208 closewin1(w);
209 reframe();
210}
211
212void
213closewin1(w)
214 struct ww *w;
215{
216 if (w == selwin)
217 selwin = 0;
218 if (w == lastselwin)
219 lastselwin = 0;
220 if (w->ww_id >= 0 && w->ww_id < NWINDOW)
221 window[w->ww_id] = 0;
222 if (w->ww_label)
223 str_free(w->ww_label);
224 deletewin(w);
225 wwclose(w);
226}
227
228/*
229 * Move the window to the top of its group.
230 * Don't do it if already fully visible.
231 * Wwvisible() doesn't work for tinted windows.
232 * But anything to make it faster.
233 * Always reframe() if doreframe is true.
234 */
235void
236front(w, doreframe)
237 struct ww *w;
238 char doreframe;
239{
240 if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) {
241 deletewin(w);
242 addwin(w, isfg(w));
243 doreframe = 1;
244 }
245 if (doreframe)
246 reframe();
247}
248
249/*
250 * Add a window at the top of normal windows or foreground windows.
251 * For normal windows, we put it behind the current window.
252 */
253void
254addwin(w, fg)
255 struct ww *w;
256 char fg;
257{
258 if (fg) {
259 wwadd(w, framewin);
260 if (fgwin == framewin)
261 fgwin = w;
262 } else
263 wwadd(w, selwin != 0 && selwin != w && !isfg(selwin)
264 ? selwin : fgwin);
265}
266
267/*
268 * Delete a window.
269 */
270void
271deletewin(w)
272 struct ww *w;
273{
274 if (fgwin == w)
275 fgwin = w->ww_back;
276 wwdelete(w);
277}
278
279void
280reframe()
281{
282 struct ww *w;
283
284 wwunframe(framewin);
285 for (w = wwhead.ww_back; w != &wwhead; w = w->ww_back)
286 if (ISSET(w->ww_uflags, WWU_HASFRAME)) {
287 wwframe(w, framewin);
288 labelwin(w);
289 }
290}
291
292void
293labelwin(w)
294 struct ww *w;
295{
296 int mode = w == selwin ? WWM_REV : 0;
297
298 if (!ISSET(w->ww_uflags, WWU_HASFRAME))
299 return;
300 if (w->ww_id >= 0) {
301 char buf[2];
302
303 buf[0] = w->ww_id + '1';
304 buf[1] = 0;
305 wwlabel(w, framewin, 1, buf, mode);
306 }
307 if (w->ww_label) {
308 int col;
309
310 if (ISSET(w->ww_uflags, WWU_CENTER)) {
311 col = (w->ww_w.nc - strlen(w->ww_label)) / 2;
312 col = MAX(3, col);
313 } else
314 col = 3;
315 wwlabel(w, framewin, col, w->ww_label, mode);
316 }
317}
318
319void
320stopwin(w)
321 struct ww *w;
322{
323 if (w->ww_pty >= 0 && w->ww_type == WWT_PTY && wwstoptty(w->ww_pty) < 0)
324 error("Can't stop output: %s.", wwerror());
325 else
326 SET(w->ww_pflags, WWP_STOPPED);
327}
328
329void
330startwin(w)
331 struct ww *w;
332{
333 if (w->ww_pty >= 0 && w->ww_type == WWT_PTY &&
334 wwstarttty(w->ww_pty) < 0)
335 error("Can't start output: %s.", wwerror());
336 else
337 CLR(w->ww_pflags, WWP_STOPPED);
338}
339
340void
341sizewin(w, nrow, ncol)
342 struct ww *w;
343 int nrow, ncol;
344{
345 struct ww *back = w->ww_back;
346
347 w->ww_alt.nr = w->ww_w.nr;
348 w->ww_alt.nc = w->ww_w.nc;
349 wwdelete(w);
350 if (wwsize(w, nrow, ncol) < 0)
351 error("Can't resize window: %s.", wwerror());
352 wwadd(w, back);
353 reframe();
354}
355
356void
357waitnl(w)
358 struct ww *w;
359{
360 (void) waitnl1(w, "[Type any key to continue]");
361}
362
363int
364more(w, always)
365 struct ww *w;
366 char always;
367{
368 int c;
369 int uc = ISSET(w->ww_wflags, WWW_UNCTRL);
370
371 if (!always && w->ww_cur.r < w->ww_w.b - 2)
372 return 0;
373 c = waitnl1(w, "[Type escape to abort, any other key to continue]");
374 CLR(w->ww_wflags, WWW_UNCTRL);
375 wwputs("\033E", w);
376 SET(w->ww_wflags, uc);
377 return c == ctrl('[') ? 2 : 1;
378}
379
380int
381waitnl1(w, prompt)
382 struct ww *w;
383 char *prompt;
384{
385 int uc = ISSET(w->ww_wflags, WWW_UNCTRL);
386
387 CLR(w->ww_wflags, WWW_UNCTRL);
388 front(w, 0);
389 wwprintf(w, "\033Y%c%c\033sA%s\033rA ",
390 w->ww_w.nr - 1 + ' ', ' ', prompt); /* print on last line */
391 wwcurtowin(w);
392 while (wwpeekc() < 0)
393 wwiomux();
394 SET(w->ww_wflags, uc);
395 return wwgetc();
396}