|
|
1.1 root 1: /*
2: * Window management.
3: * Some of the functions are internal, and some are attached to keys that the
4: * user actually types.
5: */
6: #include <stdio.h>
7: #include "ed.h"
8:
9: /*
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). With no argument it defaults to 1. Because of
14: * the default, it works like in Gosling.
15: * Bound to M-!.
16: */
17: reposition(f, n)
18: {
19: curwp->w_force = n;
20: curwp->w_flag |= WFFORCE;
21: return (TRUE);
22: }
23:
24: /*
25: * Refresh the screen. With no argument, it just does the refresh.
26: * With an argument it recenters "." in the current window.
27: * Bound to "C-L".
28: */
29: refresh(f, n)
30: {
31: if (f == FALSE)
32: sgarbf = TRUE;
33: else {
34: curwp->w_force = 0; /* Center dot. */
35: curwp->w_flag |= WFFORCE;
36: }
37: return (TRUE);
38: }
39:
40: /*
41: * The command make the next window (next => down the screen) the current
42: * window. There are no real errors, although the command does nothing if
43: * there is only 1 window on the screen.
44: * Bound to "C-X C-N".
45: */
46: nextwind(f, n)
47: {
48: register WINDOW *wp;
49:
50: if ((wp=curwp->w_wndp) == NULL)
51: wp = wheadp;
52: curwp = wp;
53: curbp = wp->w_bufp;
54: return (TRUE);
55: }
56:
57: /*
58: * This command makes the previous window (previous => up the screen) the
59: * current window. There arn't any errors, although the command does not
60: * do a lot if there is 1 window.
61: */
62: prevwind(f, n)
63: {
64: register WINDOW *wp1;
65: register WINDOW *wp2;
66:
67: wp1 = wheadp;
68: wp2 = curwp;
69: if (wp1 == wp2)
70: wp2 = NULL;
71: while (wp1->w_wndp != wp2)
72: wp1 = wp1->w_wndp;
73: curwp = wp1;
74: curbp = wp1->w_bufp;
75: return (TRUE);
76: }
77:
78: /*
79: * This command moves the current window down by "arg" lines. Recompute
80: * the top line in the window. The move up and move down code is almost
81: * completely the same; most of the work has to do with reframing the
82: * window, and picking a new dot. We share the code by having "move down"
83: * just be an interface to "move up". Magic.
84: * Bound to "C-X C-N".
85: */
86: mvdnwind(f, n)
87: register int n;
88: {
89: return (mvupwind(f, -n));
90: }
91:
92: /*
93: * Move the current window up by "arg" lines. Recompute the new top
94: * line of the window. Look to see if "." is still on the screen.
95: * If it is, you win. If it isn't, then move "." to center it in the
96: * new framing of the window (this command does not really move ".";
97: * it moves the frame). Bound to "C-X C-P".
98: */
99: mvupwind(f, n)
100: register int n;
101: {
102: register LINE *lp;
103: register int i;
104:
105: lp = curwp->w_linep;
106: if (n < 0) {
107: while (n++ && lp!=curbp->b_linep)
108: lp = lforw(lp);
109: } else {
110: while (n-- && lback(lp)!=curbp->b_linep)
111: lp = lback(lp);
112: }
113: curwp->w_linep = lp;
114: curwp->w_flag |= WFHARD; /* Mode line is OK. */
115: for (i=0; i<curwp->w_ntrows; ++i) {
116: if (lp == curwp->w_dotp)
117: return (TRUE);
118: if (lp == curbp->b_linep)
119: break;
120: lp = lforw(lp);
121: }
122: lp = curwp->w_linep;
123: i = curwp->w_ntrows/2;
124: while (i-- && lp!=curbp->b_linep)
125: lp = lforw(lp);
126: curwp->w_dotp = lp;
127: curwp->w_doto = 0;
128: return (TRUE);
129: }
130:
131: /*
132: * This command makes the current window the only window on the screen.
133: * Try to set the framing so that "." does not have to move on the display.
134: * Some care has to be taken to keep the values of dot and mark in the buffer
135: * structures right if the distruction of a window makes a buffer become
136: * undisplayed.
137: * Bound to "C-X 1".
138: */
139: onlywind(f, n)
140: {
141: register WINDOW *wp;
142: register WINDOW *np;
143: np = wheadp;
144: while ((wp = np) != NULL) {
145: np = wp->w_wndp;
146: if (wp != curwp)
147: zappwind(wp);
148: }
149: return (TRUE);
150: }
151:
152: /*
153: * Split the current window. A window smaller than 3 lines cannot be split.
154: * The only other error that is possible is a "malloc" failure allocating the
155: * structure for the new window.
156: * Bound to "C-X 2".
157: */
158: splitwind(f, n)
159: {
160: register WINDOW *wp;
161: register LINE *lp;
162: register int ntru;
163: register int ntrl;
164: register int ntrd;
165: register WINDOW *wp1;
166: register WINDOW *wp2;
167:
168: if (curwp->w_ntrows < 3) {
169: mlwrite("Cannot split a %d line window", curwp->w_ntrows);
170: return (FALSE);
171: }
172: if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
173: mlwrite("Cannot allocate WINDOW block");
174: return (FALSE);
175: }
176: ++curbp->b_nwnd; /* Displayed twice. */
177: wp->w_bufp = curbp;
178: wp->w_dotp = curwp->w_dotp;
179: wp->w_doto = curwp->w_doto;
180: wp->w_markp = curwp->w_markp;
181: wp->w_marko = curwp->w_marko;
182: wp->w_flag = 0;
183: wp->w_force = 0;
184: ntru = (curwp->w_ntrows-1) / 2; /* Upper size */
185: ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */
186: lp = curwp->w_linep;
187: ntrd = 0;
188: while (lp != curwp->w_dotp) {
189: ++ntrd;
190: lp = lforw(lp);
191: }
192: lp = curwp->w_linep;
193: if (ntrd <= ntru) { /* Old is upper window. */
194: if (ntrd == ntru) /* Hit mode line. */
195: lp = lforw(lp);
196: curwp->w_ntrows = ntru;
197: wp->w_wndp = curwp->w_wndp;
198: curwp->w_wndp = wp;
199: wp->w_toprow = curwp->w_toprow+ntru+1;
200: wp->w_ntrows = ntrl;
201: } else { /* Old is lower window */
202: wp1 = NULL;
203: wp2 = wheadp;
204: while (wp2 != curwp) {
205: wp1 = wp2;
206: wp2 = wp2->w_wndp;
207: }
208: if (wp1 == NULL)
209: wheadp = wp;
210: else
211: wp1->w_wndp = wp;
212: wp->w_wndp = curwp;
213: wp->w_toprow = curwp->w_toprow;
214: wp->w_ntrows = ntru;
215: ++ntru; /* Mode line. */
216: curwp->w_toprow += ntru;
217: curwp->w_ntrows = ntrl;
218: while (ntru--)
219: lp = lforw(lp);
220: }
221: curwp->w_linep = lp; /* Adjust the top lines */
222: wp->w_linep = lp; /* if necessary. */
223: curwp->w_flag |= WFMODE|WFHARD;
224: wp->w_flag |= WFMODE|WFHARD;
225: return (TRUE);
226: }
227:
228: /*
229: * Enlarge the current window.
230: * Find the window that loses space. Make sure it is big enough.
231: * If so, hack the window descriptions, and ask redisplay to do all the
232: * hard work. You don't just set "force reframe" because dot would move.
233: * Bound to "C-X Z".
234: */
235: enlargewind(f, n)
236: {
237: register WINDOW *adjwp;
238: register LINE *lp;
239: register int i;
240:
241: if (n < 0)
242: return (shrinkwind(f, -n));
243: if (wheadp->w_wndp == NULL) {
244: mlwrite("Only one window");
245: return (FALSE);
246: }
247: if ((adjwp=curwp->w_wndp) == NULL) {
248: adjwp = wheadp;
249: while (adjwp->w_wndp != curwp)
250: adjwp = adjwp->w_wndp;
251: }
252: if (adjwp->w_ntrows <= n) {
253: mlwrite("Impossible change");
254: return (FALSE);
255: }
256: if (curwp->w_wndp == adjwp) { /* Shrink below. */
257: lp = adjwp->w_linep;
258: for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
259: lp = lforw(lp);
260: adjwp->w_linep = lp;
261: adjwp->w_toprow += n;
262: } else { /* Shrink above. */
263: lp = curwp->w_linep;
264: for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
265: lp = lback(lp);
266: curwp->w_linep = lp;
267: curwp->w_toprow -= n;
268: }
269: curwp->w_ntrows += n;
270: adjwp->w_ntrows -= n;
271: curwp->w_flag |= WFMODE|WFHARD;
272: adjwp->w_flag |= WFMODE|WFHARD;
273: return (TRUE);
274: }
275:
276: /*
277: * Shrink the current window.
278: * Find the window that gains space. Hack at the window descriptions.
279: * Ask the redisplay to do all the hard work.
280: * Bound to "C-X C-Z".
281: */
282: shrinkwind(f, n)
283: {
284: register WINDOW *adjwp;
285: register LINE *lp;
286: register int i;
287:
288: if (n < 0)
289: return (enlargewind(f, -n));
290: if (wheadp->w_wndp == NULL) {
291: mlwrite("Only one window");
292: return (FALSE);
293: }
294: if ((adjwp=curwp->w_wndp) == NULL) {
295: adjwp = wheadp;
296: while (adjwp->w_wndp != curwp)
297: adjwp = adjwp->w_wndp;
298: }
299: if (curwp->w_ntrows <= n) {
300: mlwrite("Impossible change");
301: return (FALSE);
302: }
303: if (curwp->w_wndp == adjwp) { /* Grow below. */
304: lp = adjwp->w_linep;
305: for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
306: lp = lback(lp);
307: adjwp->w_linep = lp;
308: adjwp->w_toprow -= n;
309: } else { /* Grow above. */
310: lp = curwp->w_linep;
311: for (i=0; i<n && lp!=curbp->b_linep; ++i)
312: lp = lforw(lp);
313: curwp->w_linep = lp;
314: curwp->w_toprow += n;
315: }
316: curwp->w_ntrows -= n;
317: adjwp->w_ntrows += n;
318: curwp->w_flag |= WFMODE|WFHARD;
319: adjwp->w_flag |= WFMODE|WFHARD;
320: return (TRUE);
321: }
322:
323: /*
324: * Pick a window for a pop-up.
325: * Split the screen if there is only one window. Pick the uppermost window
326: * that isn't the current window. An LRU algorithm might be better.
327: * Return a pointer, or NULL on error.
328: */
329: WINDOW *
330: wpopup()
331: {
332: register WINDOW *wp;
333:
334: if (wheadp->w_wndp == NULL /* Only 1 window */
335: && splitwind(FALSE, 0) == FALSE) /* and it won't split */
336: return (NULL);
337: wp = wheadp; /* Find window to use */
338: while (wp!=NULL && wp==curwp)
339: wp = wp->w_wndp;
340: return (wp);
341: }
342:
343: /* Remove a window specified from the screen, giving the space that it
344: * vacates to the window above it, if any, or the window below it otherwise.
345: * If this is the only window, don't remove it at all, but show a message.
346: * Try to leave the dot where it was on the physical screen.
347: */
348: zappwind(twp)
349: WINDOW *twp;
350: {
351: register WINDOW *wp;
352: register WINDOW *pp;
353:
354: pp = NULL;
355: wp = wheadp;
356:
357: while (wp != twp) {
358: pp = wp;
359: if ((wp = wp->w_wndp) == NULL) {
360: return FALSE;
361: }
362: }
363:
364: if (pp == NULL) { /* if first window... */
365: register int i;
366: register LINE *lp;
367: LINE *elp;
368:
369: if ((pp = wp->w_wndp) == NULL) {
370: wp->w_flag = WFMODE|WFHARD;
371: mlwrite("[Only one window]");
372: return FALSE; /* Only window */
373: }
374: wheadp = pp;
375: i = pp->w_toprow - wp->w_toprow;
376: lp = pp->w_linep;
377: elp = pp->w_bufp->b_linep;
378: while (i > 0 && lback(lp)!=elp) {
379: --i;
380: lp = lback(lp);
381: }
382: pp->w_linep = lp;
383: pp->w_toprow = wp->w_toprow;
384: } else { /* Not first window... */
385: pp->w_wndp = wp->w_wndp;
386: }
387: if (wp == curwp) {
388: curwp = pp;
389: curbp = pp->w_bufp;
390: }
391: pp->w_ntrows += wp->w_ntrows + 1;
392: if (--wp->w_bufp->b_nwnd <= 0) {
393: register BUFFER *bp = wp->w_bufp;
394: bp->b_dotp = wp->w_dotp;
395: bp->b_doto = wp->w_doto;
396: bp->b_markp = wp->w_markp;
397: bp->b_marko = wp->w_marko;
398: }
399: free((char *) wp);
400: pp->w_flag |= WFMODE|WFHARD;
401: return (TRUE);
402: }
403:
404: /*
405: * Zap the first window on the screen for the specified buffer using
406: * zappwind(), above. Return FALSE if no window can be found associated
407: * with the buffer or if it was the only window.
408: */
409: zapbwind(bp)
410: register BUFFER *bp;
411: {
412: register WINDOW *wp;
413:
414: if (bp->b_nwnd < 1)
415: return FALSE;
416:
417: wp = wheadp;
418: while (wp->w_bufp != bp) {
419: if ((wp = wp->w_wndp) == NULL) {
420: return FALSE;
421: }
422: }
423: return zappwind(wp);
424: }
425:
426: /*
427: * This command deletes the current window from the screen unless it is
428: * the only window. It uses zappwind(), above.
429: * Bound to "M-1".
430: */
431: zapwind(f, n)
432: {
433: return zappwind(curwp);
434: }
435:
436: #if LIBHELP
437: /*
438: * This command deletes the first window on the screen for the help buffer.
439: * Bound to "M-2".
440: */
441: zaphelp(f, n)
442: {
443: return zapbwind(helpbp);
444: }
445: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.