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