|
|
1.1 ! root 1: /* ! 2: * Window management. ! 3: * Some of the functions are internal, and some are attached to keys that the ! 4: * user actually types. ! 5: */ ! 6: #include <stdio.h> ! 7: #include "ed.h" ! 8: ! 9: /* ! 10: * Reposition dot in the current window to line "n". If the argument is ! 11: * positive, it is that line. If it is negative it is that line from the ! 12: * bottom. If it is 0 the window is centered (this is what the standard ! 13: * redisplay code does). With no argument it defaults to 1. Because of ! 14: * the default, it works like in Gosling. ! 15: * Bound to M-!. ! 16: */ ! 17: reposition(f, n) ! 18: { ! 19: curwp->w_force = n; ! 20: curwp->w_flag |= WFFORCE; ! 21: return (TRUE); ! 22: } ! 23: ! 24: /* ! 25: * Refresh the screen. With no argument, it just does the refresh. ! 26: * With an argument it recenters "." in the current window. ! 27: * Bound to "C-L". ! 28: */ ! 29: refresh(f, n) ! 30: { ! 31: if (f == FALSE) ! 32: sgarbf = TRUE; ! 33: else { ! 34: curwp->w_force = 0; /* Center dot. */ ! 35: curwp->w_flag |= WFFORCE; ! 36: } ! 37: return (TRUE); ! 38: } ! 39: ! 40: /* ! 41: * The command make the next window (next => down the screen) the current ! 42: * window. There are no real errors, although the command does nothing if ! 43: * there is only 1 window on the screen. ! 44: * Bound to "C-X C-N". ! 45: */ ! 46: nextwind(f, n) ! 47: { ! 48: register WINDOW *wp; ! 49: ! 50: if ((wp=curwp->w_wndp) == NULL) ! 51: wp = wheadp; ! 52: curwp = wp; ! 53: curbp = wp->w_bufp; ! 54: return (TRUE); ! 55: } ! 56: ! 57: /* ! 58: * This command makes the previous window (previous => up the screen) the ! 59: * current window. There arn't any errors, although the command does not ! 60: * do a lot if there is 1 window. ! 61: */ ! 62: prevwind(f, n) ! 63: { ! 64: register WINDOW *wp1; ! 65: register WINDOW *wp2; ! 66: ! 67: wp1 = wheadp; ! 68: wp2 = curwp; ! 69: if (wp1 == wp2) ! 70: wp2 = NULL; ! 71: while (wp1->w_wndp != wp2) ! 72: wp1 = wp1->w_wndp; ! 73: curwp = wp1; ! 74: curbp = wp1->w_bufp; ! 75: return (TRUE); ! 76: } ! 77: ! 78: /* ! 79: * This command moves the current window down by "arg" lines. Recompute ! 80: * the top line in the window. The move up and move down code is almost ! 81: * completely the same; most of the work has to do with reframing the ! 82: * window, and picking a new dot. We share the code by having "move down" ! 83: * just be an interface to "move up". Magic. ! 84: * Bound to "C-X C-N". ! 85: */ ! 86: mvdnwind(f, n) ! 87: register int n; ! 88: { ! 89: return (mvupwind(f, -n)); ! 90: } ! 91: ! 92: /* ! 93: * Move the current window up by "arg" lines. Recompute the new top ! 94: * line of the window. Look to see if "." is still on the screen. ! 95: * If it is, you win. If it isn't, then move "." to center it in the ! 96: * new framing of the window (this command does not really move "."; ! 97: * it moves the frame). Bound to "C-X C-P". ! 98: */ ! 99: mvupwind(f, n) ! 100: register int n; ! 101: { ! 102: register LINE *lp; ! 103: register int i; ! 104: ! 105: lp = curwp->w_linep; ! 106: if (n < 0) { ! 107: while (n++ && lp!=curbp->b_linep) ! 108: lp = lforw(lp); ! 109: } else { ! 110: while (n-- && lback(lp)!=curbp->b_linep) ! 111: lp = lback(lp); ! 112: } ! 113: curwp->w_linep = lp; ! 114: curwp->w_flag |= WFHARD; /* Mode line is OK. */ ! 115: for (i=0; i<curwp->w_ntrows; ++i) { ! 116: if (lp == curwp->w_dotp) ! 117: return (TRUE); ! 118: if (lp == curbp->b_linep) ! 119: break; ! 120: lp = lforw(lp); ! 121: } ! 122: lp = curwp->w_linep; ! 123: i = curwp->w_ntrows/2; ! 124: while (i-- && lp!=curbp->b_linep) ! 125: lp = lforw(lp); ! 126: curwp->w_dotp = lp; ! 127: curwp->w_doto = 0; ! 128: return (TRUE); ! 129: } ! 130: ! 131: /* ! 132: * This command makes the current window the only window on the screen. ! 133: * Try to set the framing so that "." does not have to move on the display. ! 134: * Some care has to be taken to keep the values of dot and mark in the buffer ! 135: * structures right if the distruction of a window makes a buffer become ! 136: * undisplayed. ! 137: * Bound to "C-X 1". ! 138: */ ! 139: onlywind(f, n) ! 140: { ! 141: register WINDOW *wp; ! 142: register WINDOW *np; ! 143: np = wheadp; ! 144: while ((wp = np) != NULL) { ! 145: np = wp->w_wndp; ! 146: if (wp != curwp) ! 147: zappwind(wp); ! 148: } ! 149: return (TRUE); ! 150: } ! 151: ! 152: /* ! 153: * Split the current window. A window smaller than 3 lines cannot be split. ! 154: * The only other error that is possible is a "malloc" failure allocating the ! 155: * structure for the new window. ! 156: * Bound to "C-X 2". ! 157: */ ! 158: splitwind(f, n) ! 159: { ! 160: register WINDOW *wp; ! 161: register LINE *lp; ! 162: register int ntru; ! 163: register int ntrl; ! 164: register int ntrd; ! 165: register WINDOW *wp1; ! 166: register WINDOW *wp2; ! 167: ! 168: if (curwp->w_ntrows < 3) { ! 169: mlwrite("Cannot split a %d line window", curwp->w_ntrows); ! 170: return (FALSE); ! 171: } ! 172: if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) { ! 173: mlwrite("Cannot allocate WINDOW block"); ! 174: return (FALSE); ! 175: } ! 176: ++curbp->b_nwnd; /* Displayed twice. */ ! 177: wp->w_bufp = curbp; ! 178: wp->w_dotp = curwp->w_dotp; ! 179: wp->w_doto = curwp->w_doto; ! 180: wp->w_markp = curwp->w_markp; ! 181: wp->w_marko = curwp->w_marko; ! 182: wp->w_flag = 0; ! 183: wp->w_force = 0; ! 184: ntru = (curwp->w_ntrows-1) / 2; /* Upper size */ ! 185: ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */ ! 186: lp = curwp->w_linep; ! 187: ntrd = 0; ! 188: while (lp != curwp->w_dotp) { ! 189: ++ntrd; ! 190: lp = lforw(lp); ! 191: } ! 192: lp = curwp->w_linep; ! 193: if (ntrd <= ntru) { /* Old is upper window. */ ! 194: if (ntrd == ntru) /* Hit mode line. */ ! 195: lp = lforw(lp); ! 196: curwp->w_ntrows = ntru; ! 197: wp->w_wndp = curwp->w_wndp; ! 198: curwp->w_wndp = wp; ! 199: wp->w_toprow = curwp->w_toprow+ntru+1; ! 200: wp->w_ntrows = ntrl; ! 201: } else { /* Old is lower window */ ! 202: wp1 = NULL; ! 203: wp2 = wheadp; ! 204: while (wp2 != curwp) { ! 205: wp1 = wp2; ! 206: wp2 = wp2->w_wndp; ! 207: } ! 208: if (wp1 == NULL) ! 209: wheadp = wp; ! 210: else ! 211: wp1->w_wndp = wp; ! 212: wp->w_wndp = curwp; ! 213: wp->w_toprow = curwp->w_toprow; ! 214: wp->w_ntrows = ntru; ! 215: ++ntru; /* Mode line. */ ! 216: curwp->w_toprow += ntru; ! 217: curwp->w_ntrows = ntrl; ! 218: while (ntru--) ! 219: lp = lforw(lp); ! 220: } ! 221: curwp->w_linep = lp; /* Adjust the top lines */ ! 222: wp->w_linep = lp; /* if necessary. */ ! 223: curwp->w_flag |= WFMODE|WFHARD; ! 224: wp->w_flag |= WFMODE|WFHARD; ! 225: return (TRUE); ! 226: } ! 227: ! 228: /* ! 229: * Enlarge the current window. ! 230: * Find the window that loses space. Make sure it is big enough. ! 231: * If so, hack the window descriptions, and ask redisplay to do all the ! 232: * hard work. You don't just set "force reframe" because dot would move. ! 233: * Bound to "C-X Z". ! 234: */ ! 235: enlargewind(f, n) ! 236: { ! 237: register WINDOW *adjwp; ! 238: register LINE *lp; ! 239: register int i; ! 240: ! 241: if (n < 0) ! 242: return (shrinkwind(f, -n)); ! 243: if (wheadp->w_wndp == NULL) { ! 244: mlwrite("Only one window"); ! 245: return (FALSE); ! 246: } ! 247: if ((adjwp=curwp->w_wndp) == NULL) { ! 248: adjwp = wheadp; ! 249: while (adjwp->w_wndp != curwp) ! 250: adjwp = adjwp->w_wndp; ! 251: } ! 252: if (adjwp->w_ntrows <= n) { ! 253: mlwrite("Impossible change"); ! 254: return (FALSE); ! 255: } ! 256: if (curwp->w_wndp == adjwp) { /* Shrink below. */ ! 257: lp = adjwp->w_linep; ! 258: for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i) ! 259: lp = lforw(lp); ! 260: adjwp->w_linep = lp; ! 261: adjwp->w_toprow += n; ! 262: } else { /* Shrink above. */ ! 263: lp = curwp->w_linep; ! 264: for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i) ! 265: lp = lback(lp); ! 266: curwp->w_linep = lp; ! 267: curwp->w_toprow -= n; ! 268: } ! 269: curwp->w_ntrows += n; ! 270: adjwp->w_ntrows -= n; ! 271: curwp->w_flag |= WFMODE|WFHARD; ! 272: adjwp->w_flag |= WFMODE|WFHARD; ! 273: return (TRUE); ! 274: } ! 275: ! 276: /* ! 277: * Shrink the current window. ! 278: * Find the window that gains space. Hack at the window descriptions. ! 279: * Ask the redisplay to do all the hard work. ! 280: * Bound to "C-X C-Z". ! 281: */ ! 282: shrinkwind(f, n) ! 283: { ! 284: register WINDOW *adjwp; ! 285: register LINE *lp; ! 286: register int i; ! 287: ! 288: if (n < 0) ! 289: return (enlargewind(f, -n)); ! 290: if (wheadp->w_wndp == NULL) { ! 291: mlwrite("Only one window"); ! 292: return (FALSE); ! 293: } ! 294: if ((adjwp=curwp->w_wndp) == NULL) { ! 295: adjwp = wheadp; ! 296: while (adjwp->w_wndp != curwp) ! 297: adjwp = adjwp->w_wndp; ! 298: } ! 299: if (curwp->w_ntrows <= n) { ! 300: mlwrite("Impossible change"); ! 301: return (FALSE); ! 302: } ! 303: if (curwp->w_wndp == adjwp) { /* Grow below. */ ! 304: lp = adjwp->w_linep; ! 305: for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i) ! 306: lp = lback(lp); ! 307: adjwp->w_linep = lp; ! 308: adjwp->w_toprow -= n; ! 309: } else { /* Grow above. */ ! 310: lp = curwp->w_linep; ! 311: for (i=0; i<n && lp!=curbp->b_linep; ++i) ! 312: lp = lforw(lp); ! 313: curwp->w_linep = lp; ! 314: curwp->w_toprow += n; ! 315: } ! 316: curwp->w_ntrows -= n; ! 317: adjwp->w_ntrows += n; ! 318: curwp->w_flag |= WFMODE|WFHARD; ! 319: adjwp->w_flag |= WFMODE|WFHARD; ! 320: return (TRUE); ! 321: } ! 322: ! 323: /* ! 324: * Pick a window for a pop-up. ! 325: * Split the screen if there is only one window. Pick the uppermost window ! 326: * that isn't the current window. An LRU algorithm might be better. ! 327: * Return a pointer, or NULL on error. ! 328: */ ! 329: WINDOW * ! 330: wpopup() ! 331: { ! 332: register WINDOW *wp; ! 333: ! 334: if (wheadp->w_wndp == NULL /* Only 1 window */ ! 335: && splitwind(FALSE, 0) == FALSE) /* and it won't split */ ! 336: return (NULL); ! 337: wp = wheadp; /* Find window to use */ ! 338: while (wp!=NULL && wp==curwp) ! 339: wp = wp->w_wndp; ! 340: return (wp); ! 341: } ! 342: ! 343: /* Remove a window specified from the screen, giving the space that it ! 344: * vacates to the window above it, if any, or the window below it otherwise. ! 345: * If this is the only window, don't remove it at all, but show a message. ! 346: * Try to leave the dot where it was on the physical screen. ! 347: */ ! 348: zappwind(twp) ! 349: WINDOW *twp; ! 350: { ! 351: register WINDOW *wp; ! 352: register WINDOW *pp; ! 353: ! 354: pp = NULL; ! 355: wp = wheadp; ! 356: ! 357: while (wp != twp) { ! 358: pp = wp; ! 359: if ((wp = wp->w_wndp) == NULL) { ! 360: return FALSE; ! 361: } ! 362: } ! 363: ! 364: if (pp == NULL) { /* if first window... */ ! 365: register int i; ! 366: register LINE *lp; ! 367: LINE *elp; ! 368: ! 369: if ((pp = wp->w_wndp) == NULL) { ! 370: wp->w_flag = WFMODE|WFHARD; ! 371: mlwrite("[Only one window]"); ! 372: return FALSE; /* Only window */ ! 373: } ! 374: wheadp = pp; ! 375: i = pp->w_toprow - wp->w_toprow; ! 376: lp = pp->w_linep; ! 377: elp = pp->w_bufp->b_linep; ! 378: while (i > 0 && lback(lp)!=elp) { ! 379: --i; ! 380: lp = lback(lp); ! 381: } ! 382: pp->w_linep = lp; ! 383: pp->w_toprow = wp->w_toprow; ! 384: } else { /* Not first window... */ ! 385: pp->w_wndp = wp->w_wndp; ! 386: } ! 387: if (wp == curwp) { ! 388: curwp = pp; ! 389: curbp = pp->w_bufp; ! 390: } ! 391: pp->w_ntrows += wp->w_ntrows + 1; ! 392: if (--wp->w_bufp->b_nwnd <= 0) { ! 393: register BUFFER *bp = wp->w_bufp; ! 394: bp->b_dotp = wp->w_dotp; ! 395: bp->b_doto = wp->w_doto; ! 396: bp->b_markp = wp->w_markp; ! 397: bp->b_marko = wp->w_marko; ! 398: } ! 399: free((char *) wp); ! 400: pp->w_flag |= WFMODE|WFHARD; ! 401: return (TRUE); ! 402: } ! 403: ! 404: /* ! 405: * Zap the first window on the screen for the specified buffer using ! 406: * zappwind(), above. Return FALSE if no window can be found associated ! 407: * with the buffer or if it was the only window. ! 408: */ ! 409: zapbwind(bp) ! 410: register BUFFER *bp; ! 411: { ! 412: register WINDOW *wp; ! 413: ! 414: if (bp->b_nwnd < 1) ! 415: return FALSE; ! 416: ! 417: wp = wheadp; ! 418: while (wp->w_bufp != bp) { ! 419: if ((wp = wp->w_wndp) == NULL) { ! 420: return FALSE; ! 421: } ! 422: } ! 423: return zappwind(wp); ! 424: } ! 425: ! 426: /* ! 427: * This command deletes the current window from the screen unless it is ! 428: * the only window. It uses zappwind(), above. ! 429: * Bound to "M-1". ! 430: */ ! 431: zapwind(f, n) ! 432: { ! 433: return zappwind(curwp); ! 434: } ! 435: ! 436: #if LIBHELP ! 437: /* ! 438: * This command deletes the first window on the screen for the help buffer. ! 439: * Bound to "M-2". ! 440: */ ! 441: zaphelp(f, n) ! 442: { ! 443: return zapbwind(helpbp); ! 444: } ! 445: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.