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