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