xref: /original-bsd/usr.bin/window/win.c (revision fbb2a877)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)win.c	3.21 (Berkeley) 08/04/88";
20 #endif /* not lint */
21 
22 #include "defs.h"
23 #include "char.h"
24 
25 /*
26  * Higher level routines for dealing with windows.
27  *
28  * There are two types of windows: user window, and information window.
29  * User windows are the ones with a pty and shell.  Information windows
30  * are for displaying error messages, and other information.
31  *
32  * The windows are doubly linked in overlapping order and divided into
33  * two groups: foreground and normal.  Information
34  * windows are always foreground.  User windows can be either.
35  * Addwin() adds a window to the list at the top of one of the two groups.
36  * Deletewin() deletes a window.  Front() moves a window to the front
37  * of its group.  Wwopen(), wwadd(), and wwdelete() should never be called
38  * directly.
39  */
40 
41 /*
42  * Open a user window.
43  */
44 struct ww *
45 openwin(id, row, col, nrow, ncol, nline, label, haspty, hasframe, shf, sh)
46 char *label;
47 char haspty, hasframe;
48 char *shf, **sh;
49 {
50 	register struct ww *w;
51 
52 	if (id < 0 && (id = findid()) < 0)
53 		return 0;
54 	if (row + nrow <= 0 || row > wwnrow - 1
55 	    || col + ncol <= 0 || col > wwncol - 1) {
56 		error("Illegal window position.");
57 		return 0;
58 	}
59 	w = wwopen(haspty ? WWO_PTY : WWO_SOCKET, nrow, ncol, row, col, nline);
60 	if (w == 0) {
61 		error("Can't open window: %s.", wwerror());
62 		return 0;
63 	}
64 	w->ww_id = id;
65 	window[id] = w;
66 	w->ww_hasframe = hasframe;
67 	w->ww_alt = w->ww_w;
68 	if (label != 0 && setlabel(w, label) < 0)
69 		error("No memory for label.");
70 	wwcursor(w, 1);
71 	/*
72 	 * We have to do this little maneuver to make sure
73 	 * addwin() puts w at the top, so we don't waste an
74 	 * insert and delete operation.
75 	 */
76 	setselwin((struct ww *)0);
77 	addwin(w, 0);
78 	setselwin(w);
79 	if (wwspawn(w, shf, sh) < 0) {
80 		error("Can't execute %s: %s.", shf, wwerror());
81 		closewin(w);
82 		return 0;
83 	}
84 	return w;
85 }
86 
87 findid()
88 {
89 	register i;
90 
91 	for (i = 0; i < NWINDOW && window[i] != 0; i++)
92 		;
93 	if (i >= NWINDOW) {
94 		error("Too many windows.");
95 		return -1;
96 	}
97 	return i;
98 }
99 
100 struct ww *
101 findselwin()
102 {
103 	register struct ww *w, *s = 0;
104 	register i;
105 
106 	for (i = 0; i < NWINDOW; i++)
107 		if ((w = window[i]) != 0 && w != selwin &&
108 		    (s == 0 ||
109 		     !isfg(w) && (w->ww_order < s->ww_order || isfg(s))))
110 			s = w;
111 	return s;
112 }
113 
114 /*
115  * Close a user window.  Close all if w == 0.
116  */
117 closewin(w)
118 register struct ww *w;
119 {
120 	char didit = 0;
121 	register i;
122 
123 	if (w != 0) {
124 		closewin1(w);
125 		didit++;
126 	} else
127 		for (i = 0; i < NWINDOW; i++) {
128 			if ((w = window[i]) == 0)
129 				continue;
130 			closewin1(w);
131 			didit++;
132 		}
133 	if (didit) {
134 		if (selwin == 0)
135 			if (lastselwin != 0) {
136 				setselwin(lastselwin);
137 				lastselwin = 0;
138 			} else if (w = findselwin())
139 				setselwin(w);
140 		if (lastselwin == 0 && selwin)
141 			if (w = findselwin())
142 				lastselwin = w;
143 		reframe();
144 	}
145 }
146 
147 /*
148  * Open an information (display) window.
149  */
150 struct ww *
151 openiwin(nrow, label)
152 char *label;
153 {
154 	register struct ww *w;
155 
156 	if ((w = wwopen(0, nrow, wwncol, 2, 0, 0)) == 0)
157 		return 0;
158 	w->ww_mapnl = 1;
159 	w->ww_hasframe = 1;
160 	w->ww_nointr = 1;
161 	w->ww_noupdate = 1;
162 	w->ww_unctrl = 1;
163 	w->ww_id = -1;
164 	w->ww_center = 1;
165 	(void) setlabel(w, label);
166 	addwin(w, 1);
167 	reframe();
168 	return w;
169 }
170 
171 /*
172  * Close an information window.
173  */
174 closeiwin(w)
175 struct ww *w;
176 {
177 	closewin1(w);
178 	reframe();
179 }
180 
181 closewin1(w)
182 register struct ww *w;
183 {
184 	if (w == selwin)
185 		selwin = 0;
186 	if (w == lastselwin)
187 		lastselwin = 0;
188 	if (w->ww_id >= 0 && w->ww_id < NWINDOW)
189 		window[w->ww_id] = 0;
190 	if (w->ww_label)
191 		str_free(w->ww_label);
192 	deletewin(w);
193 	wwclose(w);
194 }
195 
196 /*
197  * Move the window to the top of its group.
198  * Don't do it if already fully visible.
199  * Wwvisible() doesn't work for tinted windows.
200  * But anything to make it faster.
201  * Always reframe() if doreframe is true.
202  */
203 front(w, doreframe)
204 register struct ww *w;
205 char doreframe;
206 {
207 	if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) {
208 		deletewin(w);
209 		addwin(w, isfg(w));
210 		doreframe = 1;
211 	}
212 	if (doreframe)
213 		reframe();
214 }
215 
216 /*
217  * Add a window at the top of normal windows or foreground windows.
218  * For normal windows, we put it behind the current window.
219  */
220 addwin(w, fg)
221 register struct ww *w;
222 char fg;
223 {
224 	if (fg) {
225 		wwadd(w, framewin);
226 		if (fgwin == framewin)
227 			fgwin = w;
228 	} else
229 		wwadd(w, selwin != 0 && selwin != w && !isfg(selwin)
230 				? selwin : fgwin);
231 }
232 
233 /*
234  * Delete a window.
235  */
236 deletewin(w)
237 register struct ww *w;
238 {
239 	if (fgwin == w)
240 		fgwin = w->ww_back;
241 	wwdelete(w);
242 }
243 
244 reframe()
245 {
246 	register struct ww *w;
247 
248 	wwunframe(framewin);
249 	for (w = wwhead.ww_back; w != &wwhead; w = w->ww_back)
250 		if (w->ww_hasframe) {
251 			wwframe(w, framewin);
252 			labelwin(w);
253 		}
254 }
255 
256 labelwin(w)
257 register struct ww *w;
258 {
259 	int mode = w == selwin ? WWM_REV : 0;
260 
261 	if (!w->ww_hasframe)
262 		return;
263 	if (w->ww_id >= 0) {
264 		char buf[2];
265 
266 		buf[0] = w->ww_id + '1';
267 		buf[1] = 0;
268 		wwlabel(w, framewin, 1, buf, mode);
269 	}
270 	if (w->ww_label) {
271 		int col;
272 
273 		if (w->ww_center) {
274 			col = (w->ww_w.nc - strlen(w->ww_label)) / 2;
275 			col = MAX(3, col);
276 		} else
277 			col = 3;
278 		wwlabel(w, framewin, col, w->ww_label, mode);
279 	}
280 }
281 
282 stopwin(w)
283 	register struct ww *w;
284 {
285 	w->ww_stopped = 1;
286 	if (w->ww_pty >= 0 && w->ww_ispty)
287 		(void) ioctl(w->ww_pty, TIOCSTOP, (char *)0);
288 }
289 
290 startwin(w)
291 	register struct ww *w;
292 {
293 	w->ww_stopped = 0;
294 	if (w->ww_pty >= 0 && w->ww_ispty)
295 		(void) ioctl(w->ww_pty, TIOCSTART, (char *)0);
296 }
297 
298 sizewin(w, nrow, ncol)
299 register struct ww *w;
300 {
301 	struct ww *back = w->ww_back;
302 
303 	w->ww_alt.nr = w->ww_w.nr;
304 	w->ww_alt.nc = w->ww_w.nc;
305 	wwdelete(w);
306 	if (wwsize(w, nrow, ncol) < 0)
307 		error("Can't resize window: %s.", wwerror());
308 	wwadd(w, back);
309 	reframe();
310 }
311 
312 waitnl(w)
313 struct ww *w;
314 {
315 	(void) waitnl1(w, "[Type any key to continue]");
316 }
317 
318 more(w, always)
319 register struct ww *w;
320 char always;
321 {
322 	int c;
323 	char uc = w->ww_unctrl;
324 
325 	if (!always && w->ww_cur.r < w->ww_w.b - 2)
326 		return 0;
327 	c = waitnl1(w, "[Type escape to abort, any other key to continue]");
328 	w->ww_unctrl = 0;
329 	wwputs("\033E", w);
330 	w->ww_unctrl = uc;
331 	return c == ctrl('[') ? 2 : 1;
332 }
333 
334 waitnl1(w, prompt)
335 register struct ww *w;
336 char *prompt;
337 {
338 	char uc = w->ww_unctrl;
339 
340 	w->ww_unctrl = 0;
341 	front(w, 0);
342 	wwprintf(w, "\033Y%c%c\033sA%s\033rA ",
343 		w->ww_w.nr - 1 + ' ', ' ', prompt);	/* print on last line */
344 	wwcurtowin(w);
345 	while (wwpeekc() < 0)
346 		wwiomux();
347 	w->ww_unctrl = uc;
348 	return wwgetc();
349 }
350