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