Annotation of src/usr.bin/mg/window.c, Revision 1.2
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: */
16: /*ARGSUSED*/
17: reposition(f, n)
18: {
19: #ifndef GOSREC
20: curwp->w_force = (f & FFARG) ? (n>=0 ? n+1 : n) : 0;
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: */
44: /*ARGSUSED*/
45: refresh(f, n)
46: {
1.2 ! millert 47: register MGWIN *wp;
1.1 deraadt 48: register int oldnrow;
49: register int oldncol;
50:
51: oldnrow = nrow;
52: oldncol = ncol;
53: ttresize();
54: if (nrow!=oldnrow || ncol!=oldncol) {
55: wp = wheadp; /* Find last. */
56: while (wp->w_wndp != NULL)
57: wp = wp->w_wndp;
58: if (nrow < wp->w_toprow+3) { /* Check if too small. */
59: ewprintf("Display unusable");
60: return (FALSE);
61: }
62: wp->w_ntrows = nrow-wp->w_toprow-2;
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: */
79: /*ARGSUSED*/
80: nextwind(f, n)
81: {
1.2 ! millert 82: register MGWIN *wp;
1.1 deraadt 83:
84: if ((wp=curwp->w_wndp) == NULL)
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: */
100: /*ARGSUSED*/
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: */
129: /*ARGSUSED*/
130: onlywind(f, n)
131: {
1.2 ! millert 132: register MGWIN *wp;
1.1 deraadt 133: register LINE *lp;
134: register int i;
135:
136: while (wheadp != curwp) {
137: wp = wheadp;
138: wheadp = wp->w_wndp;
139: if (--wp->w_bufp->b_nwnd == 0) {
140: wp->w_bufp->b_dotp = wp->w_dotp;
141: wp->w_bufp->b_doto = wp->w_doto;
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) {
151: wp->w_bufp->b_dotp = wp->w_dotp;
152: wp->w_bufp->b_doto = wp->w_doto;
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;
159: i = curwp->w_toprow;
160: while (i!=0 && lback(lp)!=curbp->b_linep) {
161: --i;
162: lp = lback(lp);
163: }
164: curwp->w_toprow = 0;
165: curwp->w_ntrows = nrow-2; /* 2 = mode, echo. */
166: curwp->w_linep = lp;
167: curwp->w_flag |= WFMODE|WFHARD;
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: */
178: /*ARGSUSED*/
179: splitwind(f, n)
180: {
1.2 ! millert 181: register MGWIN *wp;
1.1 deraadt 182: register LINE *lp;
183: register int ntru;
184: register int ntrd;
185: int ntrl;
1.2 ! millert 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.2 ! millert 192: if ((wp = (MGWIN *)malloc(sizeof(MGWIN))) == NULL) {
! 193: ewprintf("Can't get %d", sizeof(MGWIN));
1.1 deraadt 194: return (FALSE);
195: }
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;
200: wp->w_markp = curwp->w_markp;
201: wp->w_marko = curwp->w_marko;
202: wp->w_flag = 0;
203: wp->w_force = 0;
204: ntru = (curwp->w_ntrows-1) / 2; /* Upper size */
205: ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */
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;
213: if (ntrd <= ntru) { /* Old is upper window. */
214: if (ntrd == ntru) /* Hit mode line. */
215: lp = lforw(lp);
216: curwp->w_ntrows = ntru;
217: wp->w_wndp = curwp->w_wndp;
218: curwp->w_wndp = wp;
219: wp->w_toprow = curwp->w_toprow+ntru+1;
220: wp->w_ntrows = ntrl;
221: } else { /* Old is lower window */
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;
232: wp->w_wndp = curwp;
233: wp->w_toprow = curwp->w_toprow;
234: wp->w_ntrows = ntru;
235: ++ntru; /* Mode line. */
236: curwp->w_toprow += ntru;
237: curwp->w_ntrows = ntrl;
238: while (ntru--)
239: lp = lforw(lp);
240: }
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;
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: */
256: /*ARGSUSED*/
257: enlargewind(f, n)
258: {
1.2 ! millert 259: register MGWIN *adjwp;
1.1 deraadt 260: register LINE *lp;
261: register int i;
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: }
269: if ((adjwp=curwp->w_wndp) == NULL) {
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: }
278: if (curwp->w_wndp == adjwp) { /* Shrink below. */
279: lp = adjwp->w_linep;
280: for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
281: lp = lforw(lp);
282: adjwp->w_linep = lp;
283: adjwp->w_toprow += n;
284: } else { /* Shrink above. */
285: lp = curwp->w_linep;
286: for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
287: lp = lback(lp);
288: curwp->w_linep = lp;
289: curwp->w_toprow -= n;
290: }
291: curwp->w_ntrows += n;
292: adjwp->w_ntrows -= n;
293: curwp->w_flag |= WFMODE|WFHARD;
294: adjwp->w_flag |= WFMODE|WFHARD;
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.1 deraadt 307: register LINE *lp;
308: register int i;
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: */
320: if ( !(f & FFRAND) && curwp->w_ntrows <= n) {
321: ewprintf("Impossible change");
322: return (FALSE);
323: }
324: if ((adjwp=curwp->w_wndp) == NULL) {
325: adjwp = wheadp;
326: while (adjwp->w_wndp != curwp)
327: adjwp = adjwp->w_wndp;
328: }
329: if (curwp->w_wndp == adjwp) { /* Grow below. */
330: lp = adjwp->w_linep;
331: for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
332: lp = lback(lp);
333: adjwp->w_linep = lp;
334: adjwp->w_toprow -= n;
335: } else { /* Grow above. */
336: lp = curwp->w_linep;
337: for (i=0; i<n && lp!=curbp->b_linep; ++i)
338: lp = lforw(lp);
339: curwp->w_linep = lp;
340: curwp->w_toprow += n;
341: }
342: curwp->w_ntrows -= n;
343: adjwp->w_ntrows += n;
344: curwp->w_flag |= WFMODE|WFHARD;
345: adjwp->w_flag |= WFMODE|WFHARD;
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: */
353: /*ARGSUSED*/
354: delwind(f, n)
355: {
1.2 ! millert 356: register MGWIN *wp, *nwp;
1.1 deraadt 357:
358: wp = curwp; /* Cheap... */
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) {
363: wp->w_bufp->b_dotp = wp->w_dotp;
364: wp->w_bufp->b_doto = wp->w_doto;
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 */
369: if (wp == wheadp) wheadp = curwp = wp->w_wndp;
370: else if ((curwp = wp->w_wndp) == NULL) curwp = wheadp;
371: curbp = curwp->w_bufp;
372: for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
373: if (nwp->w_wndp == wp) {
374: nwp->w_wndp = wp->w_wndp;
375: break ;
376: }
377: free((char *) wp);
378: return TRUE;
379: }
380: /*
381: * Pick a window for a pop-up.
382: * Split the screen if there is only
383: * one window. Pick the uppermost window that
384: * isn't the current window. An LRU algorithm
385: * might be better. Return a pointer, or
386: * NULL on error.
387: */
1.2 ! millert 388: MGWIN *
1.1 deraadt 389: wpopup() {
1.2 ! millert 390: register MGWIN *wp;
1.1 deraadt 391:
392: if (wheadp->w_wndp == NULL
393: && splitwind(FFRAND, 0) == FALSE)
394: return NULL;
395: wp = wheadp; /* Find window to use */
396: while (wp!=NULL && wp==curwp)
397: wp = wp->w_wndp;
398: return wp;
399: }