Annotation of src/usr.bin/mg/window.c, Revision 1.7
1.7 ! mickey 1: /* $OpenBSD: window.c,v 1.6 2001/05/23 22:36:15 art Exp $ */
1.5 niklas 2:
1.1 deraadt 3: /*
4: * Window handling.
5: */
1.4 millert 6:
7: #include "def.h"
1.1 deraadt 8:
9: /*
1.7 ! mickey 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). If GOSREC is undefined, default is 0, so it acts
! 14: * like GNU. If GOSREC is defined, with no argument it defaults to 1 and
1.4 millert 15: * works like in Gosling.
1.1 deraadt 16: */
1.3 millert 17: /* ARGSUSED */
1.4 millert 18: int
1.1 deraadt 19: reposition(f, n)
1.4 millert 20: int f, n;
1.1 deraadt 21: {
22: #ifndef GOSREC
1.3 millert 23: curwp->w_force = (f & FFARG) ? (n >= 0 ? n + 1 : n) : 0;
1.4 millert 24: #else /* !GOSREC */
1.1 deraadt 25: curwp->w_force = n;
1.4 millert 26: #endif /* !GOSREC */
1.1 deraadt 27: curwp->w_flag |= WFFORCE;
28: sgarbf = TRUE;
29: return TRUE;
30: }
31:
32: /*
1.7 ! mickey 33: * Refresh the display. A call is made to the "ttresize" entry in the
! 34: * terminal handler, which tries to reset "nrow" and "ncol". They will,
1.4 millert 35: * however, never be set outside of the NROW or NCOL range. If the display
1.7 ! mickey 36: * changed size, arrange that everything is redone, then call "update" to
! 37: * fix the display. We do this so the new size can be displayed. In the
! 38: * normal case the call to "update" in "main.c" refreshes the screen, and
! 39: * all of the windows need not be recomputed. Note that when you get to the
! 40: * "display unusable" message, the screen will be messed up. If you make the
1.4 millert 41: * window bigger again, and send another command, everything will get fixed!
1.1 deraadt 42: */
1.3 millert 43: /* ARGSUSED */
1.4 millert 44: int
1.1 deraadt 45: refresh(f, n)
1.4 millert 46: int f, n;
1.1 deraadt 47: {
1.4 millert 48: MGWIN *wp;
49: int oldnrow;
50: int oldncol;
1.1 deraadt 51:
52: oldnrow = nrow;
53: oldncol = ncol;
54: ttresize();
1.3 millert 55: if (nrow != oldnrow || ncol != oldncol) {
1.4 millert 56:
57: /* find last */
58: wp = wheadp;
1.1 deraadt 59: while (wp->w_wndp != NULL)
60: wp = wp->w_wndp;
1.4 millert 61:
62: /* check if too small */
63: if (nrow < wp->w_toprow + 3) {
1.1 deraadt 64: ewprintf("Display unusable");
65: return (FALSE);
66: }
1.3 millert 67: wp->w_ntrows = nrow - wp->w_toprow - 2;
1.1 deraadt 68: sgarbf = TRUE;
69: update();
70: ewprintf("New size %d by %d", nrow, ncol);
71: } else
72: sgarbf = TRUE;
73: return TRUE;
74: }
75:
76: /*
1.7 ! mickey 77: * The command to make the next window (next => down the screen) the current
! 78: * window. There are no real errors, although the command does nothing if
1.4 millert 79: * there is only 1 window on the screen.
1.1 deraadt 80: */
1.3 millert 81: /* ARGSUSED */
1.4 millert 82: int
1.1 deraadt 83: nextwind(f, n)
1.4 millert 84: int f, n;
1.1 deraadt 85: {
1.4 millert 86: MGWIN *wp;
1.1 deraadt 87:
1.3 millert 88: if ((wp = curwp->w_wndp) == NULL)
1.1 deraadt 89: wp = wheadp;
90: curwp = wp;
91: curbp = wp->w_bufp;
92: return TRUE;
93: }
94:
95: #ifdef GOSMACS
1.4 millert 96:
1.1 deraadt 97: /* not in Gnu Emacs */
98: /*
1.4 millert 99: * This command makes the previous window (previous => up the screen) the
1.7 ! mickey 100: * current window. There are no errors, although the command does not do
1.4 millert 101: * a lot if there is only 1 window.
1.1 deraadt 102: */
1.3 millert 103: /* ARGSUSED */
1.4 millert 104: int
1.1 deraadt 105: prevwind(f, n)
1.4 millert 106: int f, n;
1.1 deraadt 107: {
1.4 millert 108: MGWIN *wp1, *wp2;
1.1 deraadt 109:
110: wp1 = wheadp;
111: wp2 = curwp;
112: if (wp1 == wp2)
113: wp2 = NULL;
114: while (wp1->w_wndp != wp2)
115: wp1 = wp1->w_wndp;
116: curwp = wp1;
117: curbp = wp1->w_bufp;
118: return TRUE;
119: }
1.4 millert 120: #endif /* GOSEMACS */
1.1 deraadt 121:
122: /*
1.7 ! mickey 123: * This command makes the current window the only window on the screen. Try
! 124: * to set the framing so that "." does not have to move on the display. Some
! 125: * care has to be taken to keep the values of dot and mark in the buffer
! 126: * structures right if the distruction of a window makes a buffer become
1.4 millert 127: * undisplayed.
1.1 deraadt 128: */
1.3 millert 129: /* ARGSUSED */
1.4 millert 130: int
1.1 deraadt 131: onlywind(f, n)
1.4 millert 132: int f, n;
1.1 deraadt 133: {
1.4 millert 134: MGWIN *wp;
135: LINE *lp;
136: int i;
1.1 deraadt 137:
138: while (wheadp != curwp) {
139: wp = wheadp;
140: wheadp = wp->w_wndp;
141: if (--wp->w_bufp->b_nwnd == 0) {
1.3 millert 142: wp->w_bufp->b_dotp = wp->w_dotp;
143: wp->w_bufp->b_doto = wp->w_doto;
1.1 deraadt 144: wp->w_bufp->b_markp = wp->w_markp;
145: wp->w_bufp->b_marko = wp->w_marko;
146: }
1.4 millert 147: free((char *)wp);
1.1 deraadt 148: }
149: while (curwp->w_wndp != NULL) {
150: wp = curwp->w_wndp;
151: curwp->w_wndp = wp->w_wndp;
152: if (--wp->w_bufp->b_nwnd == 0) {
1.3 millert 153: wp->w_bufp->b_dotp = wp->w_dotp;
154: wp->w_bufp->b_doto = wp->w_doto;
1.1 deraadt 155: wp->w_bufp->b_markp = wp->w_markp;
156: wp->w_bufp->b_marko = wp->w_marko;
157: }
1.4 millert 158: free((char *)wp);
1.1 deraadt 159: }
160: lp = curwp->w_linep;
1.3 millert 161: i = curwp->w_toprow;
162: while (i != 0 && lback(lp) != curbp->b_linep) {
1.1 deraadt 163: --i;
164: lp = lback(lp);
165: }
166: curwp->w_toprow = 0;
1.4 millert 167:
168: /* 2 = mode, echo */
169: curwp->w_ntrows = nrow - 2;
1.3 millert 170: curwp->w_linep = lp;
171: curwp->w_flag |= WFMODE | WFHARD;
1.1 deraadt 172: return TRUE;
173: }
174:
175: /*
1.4 millert 176: * Split the current window. A window smaller than 3 lines cannot be split.
1.7 ! mickey 177: * The only other error that is possible is a "malloc" failure allocating the
1.4 millert 178: * structure for the new window.
1.1 deraadt 179: */
1.3 millert 180: /* ARGSUSED */
1.4 millert 181: int
1.1 deraadt 182: splitwind(f, n)
1.4 millert 183: int f, n;
1.1 deraadt 184: {
1.4 millert 185: MGWIN *wp, *wp1, *wp2;
186: LINE *lp;
187: int ntru, ntrd, ntrl;
1.1 deraadt 188:
189: if (curwp->w_ntrows < 3) {
190: ewprintf("Cannot split a %d line window", curwp->w_ntrows);
191: return (FALSE);
192: }
1.6 art 193: if ((wp = malloc(sizeof(MGWIN))) == NULL) {
1.2 millert 194: ewprintf("Can't get %d", sizeof(MGWIN));
1.1 deraadt 195: return (FALSE);
196: }
1.4 millert 197:
198: /* displayed twice */
199: ++curbp->b_nwnd;
1.3 millert 200: wp->w_bufp = curbp;
201: wp->w_dotp = curwp->w_dotp;
202: wp->w_doto = curwp->w_doto;
1.1 deraadt 203: wp->w_markp = curwp->w_markp;
204: wp->w_marko = curwp->w_marko;
1.3 millert 205: wp->w_flag = 0;
1.1 deraadt 206: wp->w_force = 0;
1.3 millert 207: ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */
208: ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */
1.1 deraadt 209: lp = curwp->w_linep;
210: ntrd = 0;
211: while (lp != curwp->w_dotp) {
212: ++ntrd;
213: lp = lforw(lp);
214: }
215: lp = curwp->w_linep;
1.4 millert 216:
217: /* old is upper window */
218: if (ntrd <= ntru) {
219: /* hit mode line */
220: if (ntrd == ntru)
1.1 deraadt 221: lp = lforw(lp);
222: curwp->w_ntrows = ntru;
223: wp->w_wndp = curwp->w_wndp;
224: curwp->w_wndp = wp;
1.3 millert 225: wp->w_toprow = curwp->w_toprow + ntru + 1;
1.1 deraadt 226: wp->w_ntrows = ntrl;
1.4 millert 227: /* old is lower window */
228: } else {
1.1 deraadt 229: wp1 = NULL;
230: wp2 = wheadp;
231: while (wp2 != curwp) {
232: wp1 = wp2;
233: wp2 = wp2->w_wndp;
234: }
235: if (wp1 == NULL)
236: wheadp = wp;
237: else
238: wp1->w_wndp = wp;
1.3 millert 239: wp->w_wndp = curwp;
1.1 deraadt 240: wp->w_toprow = curwp->w_toprow;
241: wp->w_ntrows = ntru;
1.4 millert 242:
243: /* mode line */
244: ++ntru;
1.1 deraadt 245: curwp->w_toprow += ntru;
1.3 millert 246: curwp->w_ntrows = ntrl;
1.1 deraadt 247: while (ntru--)
248: lp = lforw(lp);
249: }
1.4 millert 250:
251: /* adjust the top lines if necessary */
252: curwp->w_linep = lp;
253: wp->w_linep = lp;
254:
1.3 millert 255: curwp->w_flag |= WFMODE | WFHARD;
256: wp->w_flag |= WFMODE | WFHARD;
1.1 deraadt 257: return TRUE;
258: }
259:
260: /*
1.7 ! mickey 261: * Enlarge the current window. Find the window that loses space. Make sure
! 262: * it is big enough. If so, hack the window descriptions, and ask redisplay
! 263: * to do all the hard work. You don't just set "force reframe" because dot
1.4 millert 264: * would move.
1.1 deraadt 265: */
1.3 millert 266: /* ARGSUSED */
1.4 millert 267: int
1.1 deraadt 268: enlargewind(f, n)
1.4 millert 269: int f, n;
1.1 deraadt 270: {
1.4 millert 271: MGWIN *adjwp;
272: LINE *lp;
273: int i;
1.1 deraadt 274:
275: if (n < 0)
276: return shrinkwind(f, -n);
277: if (wheadp->w_wndp == NULL) {
278: ewprintf("Only one window");
279: return FALSE;
280: }
1.3 millert 281: if ((adjwp = curwp->w_wndp) == NULL) {
1.1 deraadt 282: adjwp = wheadp;
283: while (adjwp->w_wndp != curwp)
284: adjwp = adjwp->w_wndp;
285: }
286: if (adjwp->w_ntrows <= n) {
287: ewprintf("Impossible change");
288: return FALSE;
289: }
1.4 millert 290:
291: /* shrink below */
292: if (curwp->w_wndp == adjwp) {
1.1 deraadt 293: lp = adjwp->w_linep;
1.3 millert 294: for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
1.1 deraadt 295: lp = lforw(lp);
1.3 millert 296: adjwp->w_linep = lp;
1.1 deraadt 297: adjwp->w_toprow += n;
1.4 millert 298: /* shrink above */
299: } else {
1.1 deraadt 300: lp = curwp->w_linep;
1.3 millert 301: for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i)
1.1 deraadt 302: lp = lback(lp);
1.3 millert 303: curwp->w_linep = lp;
1.1 deraadt 304: curwp->w_toprow -= n;
305: }
306: curwp->w_ntrows += n;
307: adjwp->w_ntrows -= n;
1.3 millert 308: curwp->w_flag |= WFMODE | WFHARD;
309: adjwp->w_flag |= WFMODE | WFHARD;
1.1 deraadt 310: return TRUE;
311: }
312:
313: /*
1.7 ! mickey 314: * Shrink the current window. Find the window that gains space. Hack at the
1.4 millert 315: * window descriptions. Ask the redisplay to do all the hard work.
1.1 deraadt 316: */
1.4 millert 317: int
1.1 deraadt 318: shrinkwind(f, n)
1.4 millert 319: int f, n;
1.1 deraadt 320: {
1.4 millert 321: MGWIN *adjwp;
322: LINE *lp;
323: int i;
1.1 deraadt 324:
325: if (n < 0)
326: return enlargewind(f, -n);
327: if (wheadp->w_wndp == NULL) {
328: ewprintf("Only one window");
329: return FALSE;
330: }
331: /*
332: * Bit of flakiness - KRANDOM means it was an internal call, and
333: * to be trusted implicitly about sizes.
334: */
1.3 millert 335: if (!(f & FFRAND) && curwp->w_ntrows <= n) {
1.1 deraadt 336: ewprintf("Impossible change");
337: return (FALSE);
338: }
1.3 millert 339: if ((adjwp = curwp->w_wndp) == NULL) {
1.1 deraadt 340: adjwp = wheadp;
341: while (adjwp->w_wndp != curwp)
342: adjwp = adjwp->w_wndp;
343: }
1.4 millert 344:
345: /* grow below */
346: if (curwp->w_wndp == adjwp) {
1.1 deraadt 347: lp = adjwp->w_linep;
1.3 millert 348: for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i)
1.1 deraadt 349: lp = lback(lp);
1.3 millert 350: adjwp->w_linep = lp;
1.1 deraadt 351: adjwp->w_toprow -= n;
1.4 millert 352: /* grow above */
353: } else {
1.1 deraadt 354: lp = curwp->w_linep;
1.3 millert 355: for (i = 0; i < n && lp != curbp->b_linep; ++i)
1.1 deraadt 356: lp = lforw(lp);
1.3 millert 357: curwp->w_linep = lp;
1.1 deraadt 358: curwp->w_toprow += n;
359: }
360: curwp->w_ntrows -= n;
361: adjwp->w_ntrows += n;
1.3 millert 362: curwp->w_flag |= WFMODE | WFHARD;
363: adjwp->w_flag |= WFMODE | WFHARD;
1.1 deraadt 364: return (TRUE);
365: }
366:
367: /*
1.7 ! mickey 368: * Delete current window. Call shrink-window to do the screen updating, then
1.4 millert 369: * throw away the window.
1.1 deraadt 370: */
1.3 millert 371: /* ARGSUSED */
1.4 millert 372: int
1.1 deraadt 373: delwind(f, n)
1.4 millert 374: int f, n;
1.1 deraadt 375: {
1.4 millert 376: MGWIN *wp, *nwp;
1.1 deraadt 377:
1.3 millert 378: wp = curwp; /* Cheap... */
1.4 millert 379:
1.1 deraadt 380: /* shrinkwind returning false means only one window... */
381: if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE)
382: return FALSE;
383: if (--wp->w_bufp->b_nwnd == 0) {
1.3 millert 384: wp->w_bufp->b_dotp = wp->w_dotp;
385: wp->w_bufp->b_doto = wp->w_doto;
1.1 deraadt 386: wp->w_bufp->b_markp = wp->w_markp;
387: wp->w_bufp->b_marko = wp->w_marko;
388: }
1.4 millert 389:
1.1 deraadt 390: /* since shrinkwind did't crap out, we know we have a second window */
1.3 millert 391: if (wp == wheadp)
392: wheadp = curwp = wp->w_wndp;
393: else if ((curwp = wp->w_wndp) == NULL)
394: curwp = wheadp;
1.1 deraadt 395: curbp = curwp->w_bufp;
396: for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
397: if (nwp->w_wndp == wp) {
398: nwp->w_wndp = wp->w_wndp;
1.3 millert 399: break;
1.1 deraadt 400: }
1.4 millert 401: free((char *)wp);
1.1 deraadt 402: return TRUE;
403: }
1.4 millert 404:
1.1 deraadt 405: /*
1.7 ! mickey 406: * Pick a window for a pop-up. Split the screen if there is only one window.
1.4 millert 407: * Pick the uppermost window that isn't the current window. An LRU algorithm
408: * might be better. Return a pointer, or NULL on error.
1.1 deraadt 409: */
1.3 millert 410: MGWIN *
411: wpopup()
412: {
1.4 millert 413: MGWIN *wp;
1.1 deraadt 414:
415: if (wheadp->w_wndp == NULL
1.3 millert 416: && splitwind(FFRAND, 0) == FALSE)
1.1 deraadt 417: return NULL;
1.4 millert 418:
419: /* find a window to use */
420: wp = wheadp;
421:
1.3 millert 422: while (wp != NULL && wp == curwp)
1.1 deraadt 423: wp = wp->w_wndp;
424: return wp;
425: }