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