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