|
|
1.1 root 1: /***************************************************************************
2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
3: * is provided to you without charge, and with no warranty. You may give *
4: * away copies of JOVE, including sources, provided that this notice is *
5: * included in all the files. *
6: ***************************************************************************/
7:
8: /* This creates/deletes/divides/grows/shrinks windows. */
9:
10: #include "jove.h"
11: #include "termcap.h"
12:
13: private char onlyone[] = "You only have one window!",
14: toosmall[] = "Resulting window would be too small.";
15:
16: Window *curwind,
17: *fwind = 0;
18:
19: /* First line in a Window */
20:
21: int
22: FLine(w)
23: register Window *w;
24: {
25: register Window *wp = fwind;
26: register int lineno = -1;
27:
28: do {
29: if (wp == w)
30: return lineno + 1;
31: lineno += wp->w_height;
32: wp = wp->w_next;
33: } while (wp != fwind);
34: complain("window?");
35: /* NOTREACHED */
36: }
37:
38: /* Delete `wp' from the screen. If it is the only window left
39: on the screen, then complain. It gives its body
40: to the next window if there is one, otherwise the previous
41: window gets the body. */
42:
43: void
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: #ifdef MAC
68: RemoveScrollBar(wp);
69: Windchange++;
70: #endif
71: free((char *) wp);
72: }
73:
74: /* Divide the window WP N times, or at least once. Complains if WP is too
75: small to be split into that many pieces. It returns the new window. */
76:
77: Window *
78: div_wind(wp, n)
79: register Window *wp;
80: {
81: register Window *new;
82: int amt;
83:
84: if (n < 1)
85: n = 1;
86: amt = wp->w_height / (n + 1);
87: if (amt < 2)
88: complain(toosmall);
89:
90: while (--n >= 0) {
91: new = (Window *) emalloc(sizeof (Window));
92: new->w_flags = 0;
93: new->w_LRscroll = 0;
94:
95: new->w_height = amt;
96: wp->w_height -= amt;
97:
98: /* set the lines such that w_line is the center in
99: each Window */
100: new->w_line = wp->w_line;
101: new->w_char = wp->w_char;
102: new->w_bufp = wp->w_bufp;
103: new->w_top = prev_line(new->w_line, HALF(new));
104:
105: /* Link the new window into the list */
106: new->w_prev = wp;
107: new->w_next = wp->w_next;
108: new->w_next->w_prev = new;
109: wp->w_next = new;
110: #ifdef MAC
111: new->w_control = 0;
112: #endif
113: }
114: #ifdef MAC
115: Windchange++;
116: #endif
117: return new;
118: }
119:
120: /* Initialze the first window setting the bounds to the size of the
121: screen. There is no buffer with this window. See parse for the
122: setting of this window. */
123:
124: void
125: winit()
126: {
127: register Window *w;
128:
129: w = curwind = fwind = (Window *) emalloc(sizeof (Window));
130: w->w_line = w->w_top = 0;
131: w->w_LRscroll = 0;
132: w->w_flags = 0;
133: w->w_char = 0;
134: w->w_next = w->w_prev = fwind;
135: w->w_height = ILI;
136: #ifdef MAC
137: w->w_control = 0;
138: Windchange++;
139: #endif
140: }
141:
142: /* Change to previous window. */
143:
144: void
145: PrevWindow()
146: {
147: register Window *new = curwind->w_prev;
148:
149: if (Asking)
150: complain((char *) 0);
151: if (one_windp())
152: complain(onlyone);
153: SetWind(new);
154: }
155:
156: /* Make NEW the current Window */
157:
158: void
159: SetWind(new)
160: register Window *new;
161: {
162: if (!Asking) { /* can you say kludge? */
163: curwind->w_line = curline;
164: curwind->w_char = curchar;
165: curwind->w_bufp = curbuf;
166: }
167: if (new == curwind)
168: return;
169: SetBuf(new->w_bufp);
170: if (!inlist(new->w_bufp->b_first, new->w_line)) {
171: new->w_line = curline;
172: new->w_char = curchar;
173: }
174: DotTo(new->w_line, new->w_char);
175: if (curchar > strlen(linebuf))
176: new->w_char = curchar = strlen(linebuf);
177: curwind = new;
178: }
179:
180: /* delete the current window if it isn't the only one left */
181:
182: void
183: DelCurWindow()
184: {
185: SetABuf(curwind->w_bufp);
186: del_wind(curwind);
187: }
188:
189: /* put the current line of `w' in the middle of the window */
190:
191: void
192: CentWind(w)
193: register Window *w;
194: {
195: SetTop(w, prev_line(w->w_line, HALF(w)));
196: }
197:
198: int ScrollStep = 0; /* full scrolling */
199:
200: /* Calculate the new topline of the window. If ScrollStep == 0
201: it means we should center the current line in the window. */
202:
203: void
204: CalcWind(w)
205: register Window *w;
206: {
207: register int up;
208: int scr_step;
209: Line *newtop;
210:
211: if (ScrollStep == 0) /* Means just center it */
212: CentWind(w);
213: else {
214: up = inorder(w->w_line, 0, w->w_top, 0);
215: if (up == -1) {
216: CentWind(w);
217: return;
218: }
219: scr_step = (ScrollStep < 0) ? SIZE(w) + ScrollStep :
220: ScrollStep - 1;
221: if (up) /* point is above the screen */
222: newtop = prev_line(w->w_line, scr_step);
223: else
224: newtop = prev_line(w->w_line, (SIZE(w) - 1 - scr_step));
225: if (LineDist(newtop, w->w_top) >= SIZE(w) - 1)
226: CentWind(w);
227: else
228: SetTop(w, newtop);
229: }
230: }
231:
232: /* This is bound to C-X 4 [BTF]. To make the screen stay the
233: same we have to remember various things, like the current
234: top line in the current window. It's sorta gross, but it's
235: necessary because of the way this is implemented (i.e., in
236: terms of do_find(), do_select() which manipulate the windows. */
237:
238: void
239: WindFind()
240: {
241: register Buffer *obuf = curbuf,
242: *nbuf;
243: Line *ltop = curwind->w_top;
244: Bufpos savedot;
245: extern void
246: FindTag(),
247: BufSelect(),
248: FindFile();
249:
250: DOTsave(&savedot);
251:
252: switch (waitchar((int *) 0)) {
253: case 't':
254: case 'T':
255: ExecCmd((data_obj *) FindCmd(FindTag));
256: break;
257:
258: case 'b':
259: case 'B':
260: ExecCmd((data_obj *) FindCmd(BufSelect));
261: break;
262:
263: case 'f':
264: case 'F':
265: ExecCmd((data_obj *) FindCmd(FindFile));
266: break;
267:
268: default:
269: complain("T: find-tag, F: find-file, B: select-buffer.");
270: }
271:
272: nbuf = curbuf;
273: SetBuf(obuf);
274: SetDot(&savedot);
275: SetTop(curwind, ltop); /* there! it's as if we did nothing */
276:
277: if (one_windp())
278: (void) div_wind(curwind, 1);
279:
280: tiewind(curwind->w_next, nbuf);
281: SetWind(curwind->w_next);
282: }
283:
284: /* Go into one window mode by deleting all the other windows */
285:
286: void
287: OneWindow()
288: {
289: while (curwind->w_next != curwind)
290: del_wind(curwind->w_next);
291: }
292:
293: Window *
294: windbp(bp)
295: register Buffer *bp;
296: {
297:
298: register Window *wp = fwind;
299:
300: if (bp == 0)
301: return 0;
302: do {
303: if (wp->w_bufp == bp)
304: return wp;
305: wp = wp->w_next;
306: } while (wp != fwind);
307: return 0;
308: }
309:
310: /* Change window into the next window. Curwind becomes the new window. */
311:
312: void
313: NextWindow()
314: {
315: register Window *new = curwind->w_next;
316:
317: if (Asking)
318: complain((char *) 0);
319: if (one_windp())
320: complain(onlyone);
321: SetWind(new);
322: }
323:
324: /* Scroll the next Window */
325:
326: void
327: PageNWind()
328: {
329: if (one_windp())
330: complain(onlyone);
331: NextWindow();
332: NextPage();
333: PrevWindow();
334: }
335:
336: Window *
337: w_nam_typ(name, type)
338: register char *name;
339: {
340: register Window *w;
341: register Buffer *b;
342:
343: b = buf_exists(name);
344: w = fwind;
345: if (b) do {
346: if (w->w_bufp == b)
347: return w;
348: } while ((w = w->w_next) != fwind);
349:
350: w = fwind;
351: do {
352: if (w->w_bufp->b_type == type)
353: return w;
354: } while ((w = w->w_next) != fwind);
355:
356: return 0;
357: }
358:
359: /* Put a window with the buffer `name' in it. Erase the buffer if
360: `clobber' is non-zero. */
361:
362: void
363: pop_wind(name, clobber, btype)
364: register char *name;
365: {
366: register Window *wp;
367: register Buffer *newb;
368:
369: if (newb = buf_exists(name))
370: btype = -1; /* if the buffer exists, don't change
371: it's type */
372: if ((wp = w_nam_typ(name, btype)) == 0) {
373: if (one_windp())
374: SetWind(div_wind(curwind, 1));
375: else
376: PrevWindow();
377: } else
378: SetWind(wp);
379:
380: newb = do_select((Window *) 0, name);
381: if (clobber) {
382: initlist(newb);
383: newb->b_modified = NO;
384: }
385: tiewind(curwind, newb);
386: if (btype != -1)
387: newb->b_type = btype;
388: SetBuf(newb);
389: }
390:
391: void
392: GrowWindow()
393: {
394: WindSize(curwind, abs(arg_value()));
395: }
396:
397: void
398: ShrWindow()
399: {
400: WindSize(curwind, -abs(arg_value()));
401: }
402:
403: /* Change the size of the window by inc. First arg is the window,
404: second is the increment. */
405:
406: void
407: WindSize(w, inc)
408: register Window *w;
409: register int inc;
410: {
411: if (one_windp())
412: complain(onlyone);
413:
414: if (inc == 0)
415: return;
416: else if (inc < 0) { /* Shrinking this Window. */
417: if (w->w_height + inc < 2)
418: complain(toosmall);
419: w->w_height += inc;
420: w->w_prev->w_height -= inc;
421: } else /* Growing the window. */
422: WindSize(w->w_next, -inc);
423: #ifdef MAC
424: Windchange++;
425: #endif
426: }
427:
428: /* Set the topline of the window, calculating its number in the buffer.
429: This is for numbering the lines only. */
430:
431: void
432: SetTop(w, line)
433: Window *w;
434: register Line *line;
435: {
436: register Line *lp = w->w_bufp->b_first;
437: register int num = 0;
438:
439: w->w_top = line;
440: if (w->w_flags & W_NUMLINES) {
441: while (lp) {
442: num += 1;
443: if (line == lp)
444: break;
445: lp = lp->l_next;
446: }
447: w->w_topnum = num;
448: }
449: }
450:
451: void
452: WNumLines()
453: {
454: curwind->w_flags ^= W_NUMLINES;
455: SetTop(curwind, curwind->w_top);
456: }
457:
458: void
459: WVisSpace()
460: {
461: curwind->w_flags ^= W_VISSPACE;
462: ClAndRedraw();
463: }
464:
465: /* Return the line number that `line' occupies in `windes' */
466:
467: int
468: in_window(windes, line)
469: register Window *windes;
470: register Line *line;
471: {
472: register int i;
473: register Line *top = windes->w_top;
474:
475: for (i = 0; top && i < windes->w_height - 1; i++, top = top->l_next)
476: if (top == line)
477: return FLine(windes) + i;
478: return -1;
479: }
480:
481: void
482: SplitWind()
483: {
484: SetWind(div_wind(curwind, is_an_arg() ? (arg_value() - 1) : 1));
485: }
486:
487: /* Goto the window with the named buffer. If no such window
488: exists, pop one and attach the buffer to it. */
489: void
490: GotoWind()
491: {
492: extern Buffer *lastbuf;
493: char *bname;
494: Window *w;
495:
496: bname = ask_buf(lastbuf);
497: w = curwind->w_next;
498: do {
499: if (w->w_bufp->b_name == bname) {
500: SetABuf(curbuf);
501: SetWind(w);
502: return;
503: }
504: w = w->w_next;
505: } while (w != curwind);
506: SetABuf(curbuf);
507: pop_wind(bname, NO, -1);
508: }
509:
510: void
511: ScrollRight()
512: {
513: int amt = (is_an_arg() ? arg_value() : 10);
514:
515: if (curwind->w_LRscroll - amt < 0)
516: curwind->w_LRscroll = 0;
517: else
518: curwind->w_LRscroll -= amt;
519: UpdModLine = YES;
520: }
521:
522: void
523: ScrollLeft()
524: {
525: int amt = (is_an_arg() ? arg_value() : 10);
526:
527: curwind->w_LRscroll += amt;
528: UpdModLine = YES;
529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.