]>
Commit | Line | Data |
---|---|---|
44bd5ea7 A |
1 | /* $NetBSD: win.c,v 1.10 1998/08/25 20:59:43 ross Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (c) 1983, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | |
6 | * | |
7 | * This code is derived from software contributed to Berkeley by | |
8 | * Edward Wang at The University of California, Berkeley. | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. All advertising materials mentioning features or use of this software | |
19 | * must display the following acknowledgement: | |
20 | * This product includes software developed by the University of | |
21 | * California, Berkeley and its contributors. | |
22 | * 4. Neither the name of the University nor the names of its contributors | |
23 | * may be used to endorse or promote products derived from this software | |
24 | * without specific prior written permission. | |
25 | * | |
26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
36 | * SUCH DAMAGE. | |
37 | */ | |
38 | ||
39 | #include <sys/cdefs.h> | |
40 | #ifndef lint | |
41 | #if 0 | |
42 | static char sccsid[] = "@(#)win.c 8.1 (Berkeley) 6/6/93"; | |
43 | #else | |
44 | __RCSID("$NetBSD: win.c,v 1.10 1998/08/25 20:59:43 ross Exp $"); | |
45 | #endif | |
46 | #endif /* not lint */ | |
47 | ||
48 | #include <string.h> | |
49 | #include "defs.h" | |
50 | #include "char.h" | |
51 | #include "window_string.h" | |
52 | ||
53 | /* | |
54 | * Higher level routines for dealing with windows. | |
55 | * | |
56 | * There are two types of windows: user window, and information window. | |
57 | * User windows are the ones with a pty and shell. Information windows | |
58 | * are for displaying error messages, and other information. | |
59 | * | |
60 | * The windows are doubly linked in overlapping order and divided into | |
61 | * two groups: foreground and normal. Information | |
62 | * windows are always foreground. User windows can be either. | |
63 | * Addwin() adds a window to the list at the top of one of the two groups. | |
64 | * Deletewin() deletes a window. Front() moves a window to the front | |
65 | * of its group. Wwopen(), wwadd(), and wwdelete() should never be called | |
66 | * directly. | |
67 | */ | |
68 | ||
69 | /* | |
70 | * Open a user window. | |
71 | */ | |
72 | struct ww * | |
73 | openwin(id, row, col, nrow, ncol, nline, label, type, uflags, shf, sh) | |
74 | int id, row, col, nrow, ncol, nline; | |
75 | char *label; | |
76 | int type, uflags; | |
77 | char *shf, **sh; | |
78 | { | |
79 | struct ww *w; | |
80 | ||
81 | if (id < 0 && (id = findid()) < 0) | |
82 | return 0; | |
83 | if (row + nrow <= 0 || row > wwnrow - 1 | |
84 | || col + ncol <= 0 || col > wwncol - 1) { | |
85 | error("Illegal window position."); | |
86 | return 0; | |
87 | } | |
88 | w = wwopen(type, 0, nrow, ncol, row, col, nline); | |
89 | if (w == 0) { | |
90 | error("Can't open window: %s.", wwerror()); | |
91 | return 0; | |
92 | } | |
93 | w->ww_id = id; | |
94 | window[id] = w; | |
95 | CLR(w->ww_uflags, WWU_ALLFLAGS); | |
96 | SET(w->ww_uflags, uflags); | |
97 | w->ww_alt = w->ww_w; | |
98 | if (label != 0 && setlabel(w, label) < 0) | |
99 | error("No memory for label."); | |
100 | wwcursor(w, 1); | |
101 | /* | |
102 | * We have to do this little maneuver to make sure | |
103 | * addwin() puts w at the top, so we don't waste an | |
104 | * insert and delete operation. | |
105 | */ | |
106 | setselwin((struct ww *)0); | |
107 | addwin(w, 0); | |
108 | setselwin(w); | |
109 | if (wwspawn(w, shf, sh) < 0) { | |
110 | error("Can't execute %s: %s.", shf, wwerror()); | |
111 | closewin(w); | |
112 | return 0; | |
113 | } | |
114 | return w; | |
115 | } | |
116 | ||
117 | int | |
118 | findid() | |
119 | { | |
120 | int i; | |
121 | ||
122 | for (i = 0; i < NWINDOW && window[i] != 0; i++) | |
123 | ; | |
124 | if (i >= NWINDOW) { | |
125 | error("Too many windows."); | |
126 | return -1; | |
127 | } | |
128 | return i; | |
129 | } | |
130 | ||
131 | struct ww * | |
132 | findselwin() | |
133 | { | |
134 | struct ww *w, *s = 0; | |
135 | int i; | |
136 | ||
137 | for (i = 0; i < NWINDOW; i++) | |
138 | if ((w = window[i]) != 0 && w != selwin && | |
139 | (s == 0 || | |
140 | (!isfg(w) && (w->ww_order < s->ww_order || isfg(s))))) | |
141 | s = w; | |
142 | return s; | |
143 | } | |
144 | ||
145 | /* | |
146 | * Close a user window. Close all if w == 0. | |
147 | */ | |
148 | void | |
149 | closewin(w) | |
150 | struct ww *w; | |
151 | { | |
152 | char didit = 0; | |
153 | int i; | |
154 | ||
155 | if (w != 0) { | |
156 | closewin1(w); | |
157 | didit++; | |
158 | } else | |
159 | for (i = 0; i < NWINDOW; i++) { | |
160 | if ((w = window[i]) == 0) | |
161 | continue; | |
162 | closewin1(w); | |
163 | didit++; | |
164 | } | |
165 | if (didit) { | |
166 | if (selwin == 0) { | |
167 | if (lastselwin != 0) { | |
168 | setselwin(lastselwin); | |
169 | lastselwin = 0; | |
170 | } else if ((w = findselwin())) | |
171 | setselwin(w); | |
172 | } | |
173 | if (lastselwin == 0 && selwin) | |
174 | if ((w = findselwin())) | |
175 | lastselwin = w; | |
176 | reframe(); | |
177 | } | |
178 | } | |
179 | ||
180 | /* | |
181 | * Open an information (display) window. | |
182 | */ | |
183 | struct ww * | |
184 | openiwin(nrow, label) | |
185 | int nrow; | |
186 | char *label; | |
187 | { | |
188 | struct ww *w; | |
189 | ||
190 | if ((w = wwopen(WWT_INTERNAL, 0, nrow, wwncol, 2, 0, 0)) == 0) | |
191 | return 0; | |
192 | SET(w->ww_wflags, WWW_MAPNL | WWW_NOINTR | WWW_NOUPDATE | WWW_UNCTRL); | |
193 | SET(w->ww_uflags, WWU_HASFRAME | WWU_CENTER); | |
194 | w->ww_id = -1; | |
195 | (void) setlabel(w, label); | |
196 | addwin(w, 1); | |
197 | reframe(); | |
198 | return w; | |
199 | } | |
200 | ||
201 | /* | |
202 | * Close an information window. | |
203 | */ | |
204 | void | |
205 | closeiwin(w) | |
206 | struct ww *w; | |
207 | { | |
208 | closewin1(w); | |
209 | reframe(); | |
210 | } | |
211 | ||
212 | void | |
213 | closewin1(w) | |
214 | struct ww *w; | |
215 | { | |
216 | if (w == selwin) | |
217 | selwin = 0; | |
218 | if (w == lastselwin) | |
219 | lastselwin = 0; | |
220 | if (w->ww_id >= 0 && w->ww_id < NWINDOW) | |
221 | window[w->ww_id] = 0; | |
222 | if (w->ww_label) | |
223 | str_free(w->ww_label); | |
224 | deletewin(w); | |
225 | wwclose(w); | |
226 | } | |
227 | ||
228 | /* | |
229 | * Move the window to the top of its group. | |
230 | * Don't do it if already fully visible. | |
231 | * Wwvisible() doesn't work for tinted windows. | |
232 | * But anything to make it faster. | |
233 | * Always reframe() if doreframe is true. | |
234 | */ | |
235 | void | |
236 | front(w, doreframe) | |
237 | struct ww *w; | |
238 | char doreframe; | |
239 | { | |
240 | if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) { | |
241 | deletewin(w); | |
242 | addwin(w, isfg(w)); | |
243 | doreframe = 1; | |
244 | } | |
245 | if (doreframe) | |
246 | reframe(); | |
247 | } | |
248 | ||
249 | /* | |
250 | * Add a window at the top of normal windows or foreground windows. | |
251 | * For normal windows, we put it behind the current window. | |
252 | */ | |
253 | void | |
254 | addwin(w, fg) | |
255 | struct ww *w; | |
256 | char fg; | |
257 | { | |
258 | if (fg) { | |
259 | wwadd(w, framewin); | |
260 | if (fgwin == framewin) | |
261 | fgwin = w; | |
262 | } else | |
263 | wwadd(w, selwin != 0 && selwin != w && !isfg(selwin) | |
264 | ? selwin : fgwin); | |
265 | } | |
266 | ||
267 | /* | |
268 | * Delete a window. | |
269 | */ | |
270 | void | |
271 | deletewin(w) | |
272 | struct ww *w; | |
273 | { | |
274 | if (fgwin == w) | |
275 | fgwin = w->ww_back; | |
276 | wwdelete(w); | |
277 | } | |
278 | ||
279 | void | |
280 | reframe() | |
281 | { | |
282 | struct ww *w; | |
283 | ||
284 | wwunframe(framewin); | |
285 | for (w = wwhead.ww_back; w != &wwhead; w = w->ww_back) | |
286 | if (ISSET(w->ww_uflags, WWU_HASFRAME)) { | |
287 | wwframe(w, framewin); | |
288 | labelwin(w); | |
289 | } | |
290 | } | |
291 | ||
292 | void | |
293 | labelwin(w) | |
294 | struct ww *w; | |
295 | { | |
296 | int mode = w == selwin ? WWM_REV : 0; | |
297 | ||
298 | if (!ISSET(w->ww_uflags, WWU_HASFRAME)) | |
299 | return; | |
300 | if (w->ww_id >= 0) { | |
301 | char buf[2]; | |
302 | ||
303 | buf[0] = w->ww_id + '1'; | |
304 | buf[1] = 0; | |
305 | wwlabel(w, framewin, 1, buf, mode); | |
306 | } | |
307 | if (w->ww_label) { | |
308 | int col; | |
309 | ||
310 | if (ISSET(w->ww_uflags, WWU_CENTER)) { | |
311 | col = (w->ww_w.nc - strlen(w->ww_label)) / 2; | |
312 | col = MAX(3, col); | |
313 | } else | |
314 | col = 3; | |
315 | wwlabel(w, framewin, col, w->ww_label, mode); | |
316 | } | |
317 | } | |
318 | ||
319 | void | |
320 | stopwin(w) | |
321 | struct ww *w; | |
322 | { | |
323 | if (w->ww_pty >= 0 && w->ww_type == WWT_PTY && wwstoptty(w->ww_pty) < 0) | |
324 | error("Can't stop output: %s.", wwerror()); | |
325 | else | |
326 | SET(w->ww_pflags, WWP_STOPPED); | |
327 | } | |
328 | ||
329 | void | |
330 | startwin(w) | |
331 | struct ww *w; | |
332 | { | |
333 | if (w->ww_pty >= 0 && w->ww_type == WWT_PTY && | |
334 | wwstarttty(w->ww_pty) < 0) | |
335 | error("Can't start output: %s.", wwerror()); | |
336 | else | |
337 | CLR(w->ww_pflags, WWP_STOPPED); | |
338 | } | |
339 | ||
340 | void | |
341 | sizewin(w, nrow, ncol) | |
342 | struct ww *w; | |
343 | int nrow, ncol; | |
344 | { | |
345 | struct ww *back = w->ww_back; | |
346 | ||
347 | w->ww_alt.nr = w->ww_w.nr; | |
348 | w->ww_alt.nc = w->ww_w.nc; | |
349 | wwdelete(w); | |
350 | if (wwsize(w, nrow, ncol) < 0) | |
351 | error("Can't resize window: %s.", wwerror()); | |
352 | wwadd(w, back); | |
353 | reframe(); | |
354 | } | |
355 | ||
356 | void | |
357 | waitnl(w) | |
358 | struct ww *w; | |
359 | { | |
360 | (void) waitnl1(w, "[Type any key to continue]"); | |
361 | } | |
362 | ||
363 | int | |
364 | more(w, always) | |
365 | struct ww *w; | |
366 | char always; | |
367 | { | |
368 | int c; | |
369 | int uc = ISSET(w->ww_wflags, WWW_UNCTRL); | |
370 | ||
371 | if (!always && w->ww_cur.r < w->ww_w.b - 2) | |
372 | return 0; | |
373 | c = waitnl1(w, "[Type escape to abort, any other key to continue]"); | |
374 | CLR(w->ww_wflags, WWW_UNCTRL); | |
375 | wwputs("\033E", w); | |
376 | SET(w->ww_wflags, uc); | |
377 | return c == ctrl('[') ? 2 : 1; | |
378 | } | |
379 | ||
380 | int | |
381 | waitnl1(w, prompt) | |
382 | struct ww *w; | |
383 | char *prompt; | |
384 | { | |
385 | int uc = ISSET(w->ww_wflags, WWW_UNCTRL); | |
386 | ||
387 | CLR(w->ww_wflags, WWW_UNCTRL); | |
388 | front(w, 0); | |
389 | wwprintf(w, "\033Y%c%c\033sA%s\033rA ", | |
390 | w->ww_w.nr - 1 + ' ', ' ', prompt); /* print on last line */ | |
391 | wwcurtowin(w); | |
392 | while (wwpeekc() < 0) | |
393 | wwiomux(); | |
394 | SET(w->ww_wflags, uc); | |
395 | return wwgetc(); | |
396 | } |