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