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