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