Sync usage with man page.
[netbsd-mini2440.git] / usr.bin / window / win.c
blob9a7d1e647278656f610ade0243d233ef1632b05c
1 /* $NetBSD: win.c,v 1.13 2003/08/07 11:17:34 agc Exp $ */
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Edward Wang at The University of California, Berkeley.
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.
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.
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)win.c 8.1 (Berkeley) 6/6/93";
39 #else
40 __RCSID("$NetBSD: win.c,v 1.13 2003/08/07 11:17:34 agc Exp $");
41 #endif
42 #endif /* not lint */
44 #include <string.h>
45 #include "defs.h"
46 #include "char.h"
47 #include "window_string.h"
50 * Higher level routines for dealing with windows.
52 * There are two types of windows: user window, and information window.
53 * User windows are the ones with a pty and shell. Information windows
54 * are for displaying error messages, and other information.
56 * The windows are doubly linked in overlapping order and divided into
57 * two groups: foreground and normal. Information
58 * windows are always foreground. User windows can be either.
59 * Addwin() adds a window to the list at the top of one of the two groups.
60 * Deletewin() deletes a window. Front() moves a window to the front
61 * of its group. Wwopen(), wwadd(), and wwdelete() should never be called
62 * directly.
66 * Open a user window.
68 struct ww *
69 openwin(int id, int row, int col, int nrow, int ncol, int nline, char *label, int type, int uflags, char *shf, char **sh)
71 struct ww *w;
73 if (id < 0 && (id = findid()) < 0)
74 return 0;
75 if (row + nrow <= 0 || row > wwnrow - 1
76 || col + ncol <= 0 || col > wwncol - 1) {
77 error("Illegal window position.");
78 return 0;
80 w = wwopen(type, 0, nrow, ncol, row, col, nline);
81 if (w == 0) {
82 error("Can't open window: %s.", wwerror());
83 return 0;
85 w->ww_id = id;
86 window[id] = w;
87 CLR(w->ww_uflags, WWU_ALLFLAGS);
88 SET(w->ww_uflags, uflags);
89 w->ww_alt = w->ww_w;
90 if (label != 0 && setlabel(w, label) < 0)
91 error("No memory for label.");
92 wwcursor(w, 1);
94 * We have to do this little maneuver to make sure
95 * addwin() puts w at the top, so we don't waste an
96 * insert and delete operation.
98 setselwin((struct ww *)0);
99 addwin(w, 0);
100 setselwin(w);
101 if (wwspawn(w, shf, sh) < 0) {
102 error("Can't execute %s: %s.", shf, wwerror());
103 closewin(w);
104 return 0;
106 return w;
110 findid(void)
112 int i;
114 for (i = 0; i < NWINDOW && window[i] != 0; i++)
116 if (i >= NWINDOW) {
117 error("Too many windows.");
118 return -1;
120 return i;
123 struct ww *
124 findselwin(void)
126 struct ww *w, *s = 0;
127 int i;
129 for (i = 0; i < NWINDOW; i++)
130 if ((w = window[i]) != 0 && w != selwin &&
131 (s == 0 ||
132 (!isfg(w) && (w->ww_order < s->ww_order || isfg(s)))))
133 s = w;
134 return s;
138 * Close a user window. Close all if w == 0.
140 void
141 closewin(struct ww *w)
143 char didit = 0;
144 int i;
146 if (w != 0) {
147 closewin1(w);
148 didit++;
149 } else
150 for (i = 0; i < NWINDOW; i++) {
151 if ((w = window[i]) == 0)
152 continue;
153 closewin1(w);
154 didit++;
156 if (didit) {
157 if (selwin == 0) {
158 if (lastselwin != 0) {
159 setselwin(lastselwin);
160 lastselwin = 0;
161 } else if ((w = findselwin()))
162 setselwin(w);
164 if (lastselwin == 0 && selwin)
165 if ((w = findselwin()))
166 lastselwin = w;
167 reframe();
172 * Open an information (display) window.
174 struct ww *
175 openiwin(int nrow, const char *label)
177 struct ww *w;
179 if ((w = wwopen(WWT_INTERNAL, 0, nrow, wwncol, 2, 0, 0)) == 0)
180 return 0;
181 SET(w->ww_wflags, WWW_MAPNL | WWW_NOINTR | WWW_NOUPDATE | WWW_UNCTRL);
182 SET(w->ww_uflags, WWU_HASFRAME | WWU_CENTER);
183 w->ww_id = -1;
184 (void) setlabel(w, label);
185 addwin(w, 1);
186 reframe();
187 return w;
191 * Close an information window.
193 void
194 closeiwin(struct ww *w)
196 closewin1(w);
197 reframe();
200 void
201 closewin1(struct ww *w)
203 if (w == selwin)
204 selwin = 0;
205 if (w == lastselwin)
206 lastselwin = 0;
207 if (w->ww_id >= 0 && w->ww_id < NWINDOW)
208 window[w->ww_id] = 0;
209 if (w->ww_label)
210 str_free(w->ww_label);
211 deletewin(w);
212 wwclose(w);
216 * Move the window to the top of its group.
217 * Don't do it if already fully visible.
218 * Wwvisible() doesn't work for tinted windows.
219 * But anything to make it faster.
220 * Always reframe() if doreframe is true.
222 void
223 front(struct ww *w, char doreframe)
225 if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) {
226 deletewin(w);
227 addwin(w, isfg(w));
228 doreframe = 1;
230 if (doreframe)
231 reframe();
235 * Add a window at the top of normal windows or foreground windows.
236 * For normal windows, we put it behind the current window.
238 void
239 addwin(struct ww *w, char fg)
241 if (fg) {
242 wwadd(w, framewin);
243 if (fgwin == framewin)
244 fgwin = w;
245 } else
246 wwadd(w, selwin != 0 && selwin != w && !isfg(selwin)
247 ? selwin : fgwin);
251 * Delete a window.
253 void
254 deletewin(struct ww *w)
256 if (fgwin == w)
257 fgwin = w->ww_back;
258 wwdelete(w);
261 void
262 reframe(void)
264 struct ww *w;
266 wwunframe(framewin);
267 for (w = wwhead.ww_back; w != &wwhead; w = w->ww_back)
268 if (ISSET(w->ww_uflags, WWU_HASFRAME)) {
269 wwframe(w, framewin);
270 labelwin(w);
274 void
275 labelwin(struct ww *w)
277 int mode = w == selwin ? WWM_REV : 0;
279 if (!ISSET(w->ww_uflags, WWU_HASFRAME))
280 return;
281 if (w->ww_id >= 0) {
282 char buf[2];
284 buf[0] = w->ww_id + '1';
285 buf[1] = 0;
286 wwlabel(w, framewin, 1, buf, mode);
288 if (w->ww_label) {
289 int col;
291 if (ISSET(w->ww_uflags, WWU_CENTER)) {
292 col = (w->ww_w.nc - strlen(w->ww_label)) / 2;
293 col = MAX(3, col);
294 } else
295 col = 3;
296 wwlabel(w, framewin, col, w->ww_label, mode);
300 void
301 stopwin(struct ww *w)
303 if (w->ww_pty >= 0 && w->ww_type == WWT_PTY && wwstoptty(w->ww_pty) < 0)
304 error("Can't stop output: %s.", wwerror());
305 else
306 SET(w->ww_pflags, WWP_STOPPED);
309 void
310 startwin(struct ww *w)
312 if (w->ww_pty >= 0 && w->ww_type == WWT_PTY &&
313 wwstarttty(w->ww_pty) < 0)
314 error("Can't start output: %s.", wwerror());
315 else
316 CLR(w->ww_pflags, WWP_STOPPED);
319 void
320 sizewin(struct ww *w, int nrow, int ncol)
322 struct ww *back = w->ww_back;
324 w->ww_alt.nr = w->ww_w.nr;
325 w->ww_alt.nc = w->ww_w.nc;
326 wwdelete(w);
327 if (wwsize(w, nrow, ncol) < 0)
328 error("Can't resize window: %s.", wwerror());
329 wwadd(w, back);
330 reframe();
333 void
334 waitnl(struct ww *w)
336 (void) waitnl1(w, "[Type any key to continue]");
340 more(struct ww *w, char always)
342 int c;
343 int uc = ISSET(w->ww_wflags, WWW_UNCTRL);
345 if (!always && w->ww_cur.r < w->ww_w.b - 2)
346 return 0;
347 c = waitnl1(w, "[Type escape to abort, any other key to continue]");
348 CLR(w->ww_wflags, WWW_UNCTRL);
349 wwputs("\033E", w);
350 SET(w->ww_wflags, uc);
351 return c == ctrl('[') ? 2 : 1;
355 waitnl1(struct ww *w, const char *prompt)
357 int uc = ISSET(w->ww_wflags, WWW_UNCTRL);
359 CLR(w->ww_wflags, WWW_UNCTRL);
360 front(w, 0);
361 wwprintf(w, "\033Y%c%c\033sA%s\033rA ",
362 w->ww_w.nr - 1 + ' ', ' ', prompt); /* print on last line */
363 wwcurtowin(w);
364 while (wwpeekc() < 0)
365 wwiomux();
366 SET(w->ww_wflags, uc);
367 return wwgetc();