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