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