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