|
|
1.1 root 1: /*************************************************************************
2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3: * provided to you without charge for use only on a licensed Unix *
4: * system. You may copy JOVE provided that this notice is included with *
5: * the copy. You may not sell copies of this program or versions *
6: * modified for use on microcomputer systems, unless the copies are *
7: * included with a Unix system distribution and the source is provided. *
8: *************************************************************************/
9:
10: /* This creates/deletes/divides/grows/shrinks windows. */
11:
12: #include "jove.h"
13: #include "termcap.h"
14:
15: static char onlyone[] = "You only have one window!",
16: toosmall[] = "Resulting window would be too small.";
17:
18: Window *curwind,
19: *fwind = 0;
20:
21: /* First line in a Window */
22:
23: FLine(w)
24: register Window *w;
25: {
26: register Window *wp = fwind;
27: register int lineno = -1;
28:
29: do {
30: if (wp == w)
31: return lineno + 1;
32: lineno += wp->w_height;
33: wp = wp->w_next;
34: } while (wp != fwind);
35: complain("window?");
36: /* NOTREACHED */
37: }
38:
39: /* Delete `wp' from the screen. If it is the only window left
40: on the screen, then complain. It gives its body
41: to the next window if there is one, otherwise the previous
42: window gets the body. */
43:
44: del_wind(wp)
45: register Window *wp;
46: {
47: register Window *prev = wp->w_prev;
48:
49: if (one_windp())
50: complain(onlyone);
51:
52: wp->w_prev->w_next = wp->w_next;
53: wp->w_next->w_prev = wp->w_prev;
54:
55: if (fwind == wp) {
56: fwind = wp->w_next;
57: fwind->w_height += wp->w_height;
58: /* Here try to do something intelligent for redisplay() */
59: SetTop(fwind, prev_line(fwind->w_top, wp->w_height));
60: if (curwind == wp)
61: SetWind(fwind);
62: } else {
63: prev->w_height += wp->w_height;
64: if (curwind == wp)
65: SetWind(prev);
66: }
67: free((char *) wp);
68: }
69:
70: /* Divide the window WP N times, or at least once. Complains if WP is too
71: small to be split into that many pieces. It returns the new window. */
72:
73: Window *
74: div_wind(wp, n)
75: register Window *wp;
76: {
77: register Window *new;
78: int amt;
79:
80: if (n < 1)
81: n = 1;
82: amt = wp->w_height / (n + 1);
83: if (amt < 2)
84: complain(toosmall);
85:
86: while (--n >= 0) {
87: new = (Window *) emalloc(sizeof (Window));
88: new->w_visspace = new->w_numlines = 0;
89:
90: new->w_height = amt;
91: wp->w_height -= amt;
92:
93: /* set the lines such that w_line is the center in
94: each Window */
95: new->w_line = wp->w_line;
96: new->w_char = wp->w_char;
97: new->w_bufp = wp->w_bufp;
98: new->w_top = prev_line(new->w_line, HALF(new));
99:
100: /* Link the new window into the list */
101: new->w_prev = wp;
102: new->w_next = wp->w_next;
103: new->w_next->w_prev = new;
104: wp->w_next = new;
105: }
106: return new;
107: }
108:
109: /* Initialze the first window setting the bounds to the size of the
110: screen. There is no buffer with this window. See parse for the
111: setting of this window. */
112:
113: winit()
114: {
115: register Window *w;
116:
117: w = curwind = fwind = (Window *) emalloc(sizeof (Window));
118: w->w_line = w->w_top = 0;
119: w->w_visspace = w->w_numlines = 0;
120: w->w_char = 0;
121: w->w_next = w->w_prev = fwind;
122: w->w_height = ILI;
123: }
124:
125: /* Change to previous window. */
126:
127: PrevWindow()
128: {
129: register Window *new = curwind->w_prev;
130:
131: if (one_windp())
132: complain(onlyone);
133: SetWind(new);
134: }
135:
136: /* Make NEW the current Window */
137:
138: SetWind(new)
139: register Window *new;
140: {
141: if (!Asking){ /* can you say kludge? */
142: curwind->w_line = curline;
143: curwind->w_char = curchar;
144: curwind->w_bufp = curbuf;
145: }
146: if (new == curwind)
147: return;
148: SetBuf(new->w_bufp);
149: if (!inlist(new->w_bufp->b_first, new->w_line)) {
150: new->w_line = curline;
151: new->w_char = curchar;
152: }
153: DotTo(new->w_line, new->w_char);
154: if (curchar > strlen(linebuf))
155: new->w_char = curchar = strlen(linebuf);
156: curwind = new;
157: }
158:
159: /* Delete the current window if it isn't the only one left */
160:
161: DelCurWindow()
162: {
163: del_wind(curwind);
164: }
165:
166: /* Put the current line of `w' in the middle of the window */
167:
168: CentWind(w)
169: register Window *w;
170: {
171: SetTop(w, prev_line(w->w_line, HALF(w)));
172: }
173:
174: int ScrollStep = 0; /* Full scrolling */
175:
176: /* Calculate the new topline of the screen. If ScrollStep == 0
177: it means we should center the current line in the window. */
178:
179: CalcWind(w)
180: register Window *w;
181: {
182: register int up;
183: Line *newtop;
184:
185: if (ScrollStep == 0) /* Means just center it */
186: CentWind(w);
187: else {
188: up = inorder(w->w_line, 0, w->w_top, 0);
189: if (up == -1) {
190: CentWind(w);
191: return;
192: }
193: if (up) /* Dot is above the screen */
194: newtop = prev_line(w->w_line, min(ScrollStep - 1, HALF(w)));
195: else
196: newtop = prev_line(w->w_line, (SIZE(w) - 1) -
197: min(ScrollStep - 1, HALF(w)));
198: if (LineDist(newtop, w->w_top) >= SIZE(w) - 1)
199: CentWind(w);
200: else
201: SetTop(w, newtop);
202: }
203: }
204:
205: WindFind()
206: {
207: register Buffer *savebuf = curbuf;
208: Bufpos savedot;
209: extern int
210: FindTag(),
211: BufSelect(),
212: FindFile();
213:
214: DOTsave(&savedot);
215:
216: switch (waitchar()) {
217: case 't':
218: case 'T':
219: ExecCmd((data_obj *) FindCmd(FindTag));
220: break;
221:
222: case 'b':
223: case 'B':
224: ExecCmd((data_obj *) FindCmd(BufSelect));
225: break;
226:
227: case 'f':
228: case 'F':
229: ExecCmd((data_obj *) FindCmd(FindFile));
230: break;
231:
232: default:
233: complain("T: find-tag, F: find-file, B: select-buffer.");
234: }
235:
236: if (one_windp())
237: (void) div_wind(curwind, 1);
238:
239: tiewind(curwind->w_next, curbuf);
240: SetBuf(savebuf); /* Back to original buffer */
241: SetDot(&savedot); /* in original position */
242: tiewind(curwind, curbuf);
243: SetWind(curwind->w_next);
244: }
245:
246: /* Go into one window mode by deleting all the other windows */
247:
248: OneWindow()
249: {
250: while (curwind->w_next != curwind)
251: del_wind(curwind->w_next);
252: }
253:
254: Window *
255: windbp(bp)
256: register Buffer *bp;
257: {
258:
259: register Window *wp = fwind;
260:
261: if (bp == 0)
262: return 0;
263: do {
264: if (wp->w_bufp == bp)
265: return wp;
266: wp = wp->w_next;
267: } while (wp != fwind);
268: return 0;
269: }
270:
271: /* Look for a window containing a buffer whose name is `name' */
272:
273: Window *
274: windlook(name)
275: register char *name;
276: {
277: return windbp(buf_exists(name));
278: }
279:
280: /* Change window into the next window. Curwind becomes the new window. */
281:
282: NextWindow()
283: {
284: register Window *new = curwind->w_next;
285:
286: if (one_windp())
287: complain(onlyone);
288: SetWind(new);
289: }
290:
291: /* Scroll the next Window */
292:
293: PageNWind()
294: {
295: if (one_windp())
296: complain(onlyone);
297: NextWindow();
298: NextPage();
299: PrevWindow();
300: }
301:
302: Window *
303: w_nam_typ(name, type)
304: register char *name;
305: {
306: register Window *w;
307: register Buffer *b;
308:
309: b = buf_exists(name);
310: w = fwind;
311: if (b) do {
312: if (w->w_bufp == b)
313: return w;
314: } while ((w = w->w_next) != fwind);
315:
316: w = fwind;
317: do {
318: if (w->w_bufp->b_type == type)
319: return w;
320: } while ((w = w->w_next) != fwind);
321:
322: return 0;
323: }
324:
325: /* Put a window with the buffer `name' in it. Erase the buffer if
326: `clobber' is non-zero. */
327:
328: pop_wind(name, clobber, btype)
329: register char *name;
330: {
331: register Window *wp;
332: register Buffer *newb;
333:
334: if ((wp = w_nam_typ(name, btype)) == 0) {
335: if (one_windp())
336: SetWind(div_wind(curwind, 1));
337: else
338: PrevWindow();
339: } else
340: SetWind(wp);
341:
342: newb = do_select((Window *) 0, name);
343: if (clobber)
344: initlist(newb);
345: tiewind(curwind, newb);
346: #ifdef IPROCS
347: if (newb->b_type != B_IPROCESS && btype != -1)
348: #else
349: if (btype != -1)
350: #endif
351: newb->b_type = btype;
352: SetBuf(newb);
353: }
354:
355: GrowWindow()
356: {
357: WindSize(curwind, abs(exp));
358: }
359:
360: ShrWindow()
361: {
362: WindSize(curwind, -abs(exp));
363: }
364:
365: /* Change the size of the window by inc. First arg is the window,
366: second is the increment. */
367:
368: WindSize(w, inc)
369: register Window *w;
370: register int inc;
371: {
372: if (one_windp())
373: complain(onlyone);
374:
375: if (inc == 0)
376: return;
377: else if (inc < 0) { /* Shrinking this Window. */
378: if (w->w_height + inc < 2)
379: complain(toosmall);
380: w->w_height += inc;
381: w->w_prev->w_height -= inc;
382: } else /* Growing the window. */
383: WindSize(w->w_next, -inc);
384: }
385:
386: /* Set the topline of the window, calculating its number in the buffer.
387: This is for numbering the lines only. */
388:
389: SetTop(w, line)
390: Window *w;
391: register Line *line;
392: {
393: register Line *lp = w->w_bufp->b_first;
394: register int num = 0;
395:
396: w->w_top = line;
397: if (w->w_numlines) {
398: while (lp) {
399: num++;
400: if (line == lp)
401: break;
402: lp = lp->l_next;
403: }
404: w->w_topnum = num;
405: }
406: }
407:
408: WNumLines()
409: {
410: curwind->w_numlines = !curwind->w_numlines;
411: SetTop(curwind, curwind->w_top);
412: }
413:
414: WVisSpace()
415: {
416: curwind->w_visspace = !curwind->w_visspace;
417: ClAndRedraw();
418: }
419:
420: /* Return the line number that `line' occupies in `windes' */
421:
422: in_window(windes, line)
423: register Window *windes;
424: register Line *line;
425: {
426: register int i;
427: register Line *top = windes->w_top;
428:
429: for (i = 0; top && i < windes->w_height - 1; i++, top = top->l_next)
430: if (top == line)
431: return FLine(windes) + i;
432: return -1;
433: }
434:
435: SplitWind()
436: {
437: SetWind(div_wind(curwind, exp_p ? (exp - 1) : 1));
438: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.