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