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