|
|
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: #include "jove.h"
11: #include "ctype.h"
12: #include "termcap.h"
13:
14: #include <varargs.h>
15: #include <signal.h>
16: #include <sys/stat.h>
17:
18: /* Kludge windows gets called by the routines that delete lines from the
19: buffer. If the w->w_line or w->w_top are deleted and this procedure
20: is not called, the redisplay routine will barf. */
21:
22: ChkWindows(line1, line2)
23: Line *line1;
24: register Line *line2;
25: {
26: register Window *w = fwind;
27: register Line *lp;
28:
29: do {
30: for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) {
31: if (lp == w->w_top)
32: w->w_flags |= TOPGONE;
33: if (lp == w->w_line)
34: w->w_flags |= CURGONE;
35: }
36: w = w->w_next;
37: } while (w != fwind);
38: }
39:
40: extern int RingBell;
41:
42: redisplay()
43: {
44: register Window *w = fwind;
45: int lineno,
46: done_ID = 0,
47: i;
48: register struct scrimage *des_p,
49: *phys_p;
50:
51: curwind->w_line = curwind->w_bufp->b_dot;
52: curwind->w_char = curwind->w_bufp->b_char;
53:
54: if (InputPending = charp())
55: return;
56:
57: #ifdef JOB_CONTROL
58: if (UpdFreq)
59: sighold(SIGALRM);
60: #endif
61: if (RingBell) {
62: dobell(1);
63: RingBell = 0;
64: }
65: if (UpdMesg)
66: DrawMesg(YES);
67:
68: for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
69: UpdWindow(w, lineno);
70: lineno += w->w_height;
71: }
72:
73: des_p = DesiredScreen;
74: phys_p = PhysScreen;
75: for (i = 0; i < ILI; i++, des_p++, phys_p++) {
76: if (!done_ID && (des_p->s_id != phys_p->s_id)) {
77: DoIDline(i);
78: done_ID++;
79: }
80: if ((des_p->s_flags & (DIRTY | L_MOD)) ||
81: (des_p->s_id != phys_p->s_id) ||
82: (des_p->s_vln != phys_p->s_vln) ||
83: (des_p->s_offset != phys_p->s_offset))
84: UpdLine(i);
85: if (InputPending)
86: goto ret;
87: }
88:
89: UpdModLine = 0;
90:
91: if (Asking) {
92: Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking)));
93: /* Nice kludge */
94: flusho();
95: } else
96: GotoDot();
97: ret:
98: #ifdef JOB_CONTROL
99: if (UpdFreq)
100: sigrelse(SIGALRM);
101: #else
102: ; /* yuck */
103: #endif
104:
105: }
106:
107: dobell(n)
108: {
109: while (--n >= 0) {
110: if (VisBell && VB)
111: putstr(VB);
112: else
113: putpad("20\007", 1);
114: }
115: flusho();
116: }
117:
118: /* find_pos() returns the position on the line, that c_char represents
119: in line. */
120:
121: find_pos(line, c_char)
122: Line *line;
123: {
124: return calc_pos(lcontents(line), c_char);
125: }
126:
127: calc_pos(lp, c_char)
128: register char *lp;
129: register int c_char;
130: {
131: register int pos = 0;
132: register int c;
133:
134: while ((--c_char >= 0) && ((c = *lp++) & 0177) != 0) {
135: if (c == '\t')
136: pos += (tabstop - (pos % tabstop));
137: else if (isctrl(c))
138: pos += 2;
139: else
140: pos++;
141: }
142: return pos;
143: }
144:
145: int UpdModLine = 0,
146: UpdMesg = 0,
147: CanScroll = 0;
148:
149: DoIDline(start)
150: {
151: register struct scrimage *des_p = &DesiredScreen[start];
152: struct scrimage *phys_p = &PhysScreen[start];
153: register int i,
154: j;
155:
156: /* Some changes have been made. Try for insert or delete lines.
157: If either case has happened, Addlines and/or DelLines will do
158: necessary scrolling, also CONVERTING PhysScreen to account for the
159: physical changes. The comparison continues from where the
160: insertion/deletion takes place; this doesn't happen very often,
161: usually it happens with more than one window with the same
162: buffer. */
163:
164: if (!CanScroll)
165: return; /* We should never have been called! */
166:
167: for (i = start; i < ILI; i++, des_p++, phys_p++)
168: if (des_p->s_id != phys_p->s_id)
169: break;
170:
171: for (; i < ILI; i++) {
172: for (j = i + 1; j < ILI; j++) {
173: des_p = &DesiredScreen[j];
174: phys_p = &PhysScreen[j];
175: if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
176: break;
177: if (des_p->s_id == PhysScreen[i].s_id) {
178: if (des_p->s_id == 0)
179: continue;
180: if (AddLines(i, j - i)) {
181: DoIDline(j);
182: return;
183: }
184: break;
185: }
186: if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
187: if (des_p->s_id == 0)
188: continue;
189: if (DelLines(i, j - i)) {
190: DoIDline(i);
191: return;
192: }
193: break;
194: }
195: }
196: }
197: }
198:
199: /* Make DesiredScreen reflect what the screen should look like when we are done
200: with the redisplay. This deals with horizontal scrolling. Also makes
201: sure the current line of the Window is in the window. */
202:
203: UpdWindow(w, start)
204: register Window *w;
205: {
206: Line *lp;
207: int i,
208: DotIsHere = 0,
209: upper, /* Top of window */
210: lower, /* Bottom of window */
211: ntries = 0; /* # of tries at updating window. */
212: register struct scrimage *des_p,
213: *phys_p;
214: Buffer *bp = w->w_bufp;
215:
216: retry:
217: if (w->w_flags & CURGONE) {
218: w->w_line = bp->b_dot;
219: w->w_char = bp->b_char;
220: }
221: if (w->w_flags & TOPGONE)
222: CentWind(w); /* Reset topline of screen */
223: w->w_flags = 0;
224: for (i = w->w_height, lp = w->w_top; --i > 0 && lp != 0; lp = lp->l_next)
225: if (lp == w->w_line)
226: break;
227: if (i == 0 || lp == 0) { /* Current line not in window */
228: ntries++;
229: if (ntries == 1) {
230: CalcWind(w);
231: goto retry;
232: } else if (ntries == 2) {
233: w->w_top = w->w_line = w->w_bufp->b_first;
234: f_mess("ERROR in redisplay: I got hopelessly lost!");
235: goto retry;
236: } else if (ntries == 3) {
237: printf("\rOops, still lost, quitting ...\r\n");
238: finish(1);
239: }
240: }
241:
242: upper = start;
243: lower = upper + w->w_height - 1; /* Don't include modeline */
244: des_p = &DesiredScreen[upper];
245: phys_p = &PhysScreen[upper];
246: for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) {
247: des_p->s_window = w;
248: des_p->s_lp = lp;
249: des_p->s_id = lp->l_dline & ~DIRTY;
250: des_p->s_flags = isdirty(lp) ? L_MOD : 0;
251: if (w->w_numlines)
252: des_p->s_vln = w->w_topnum + (i - upper);
253: else
254: des_p->s_vln = 0;
255:
256: if (lp == w->w_line) {
257: int diff = w->w_numlines ? 8 : 0,
258: strt_col = phys_p->s_offset,
259: end_col = strt_col + (CO - 2) - diff;
260:
261: /* Right now we are displaying from strt_col to
262: end_col of the buffer line. These are PRINT
263: colums, not actual characters. */
264: w->w_dotline = i;
265: w->w_dotcol = find_pos(lp, w->w_char);
266: /* if the new dotcol is out of range, reselect
267: a horizontal window */
268: if (w->w_dotcol < strt_col || w->w_dotcol >= end_col) {
269: if (w->w_dotcol < ((CO - 2) - diff))
270: strt_col = 0;
271: else
272: strt_col = w->w_dotcol - (CO / 2);
273: }
274: w->w_dotcol += diff;
275: des_p->s_offset = strt_col;
276: DotIsHere++;
277: } else
278: des_p->s_offset = 0;
279: }
280: if (!DotIsHere) {
281: f_mess("DotNotHere is impossible!");
282: finish(1);
283: }
284:
285: /* Is structure assignment faster than copy each field seperately */
286: if (i < lower) {
287: static struct scrimage dirty_plate = { 0, DIRTY, 0, 0, 0, 0 },
288: clean_plate = { 0, 0, 0, 0, 0, 0 };
289:
290: for (; i < lower; i++, des_p++, phys_p++)
291: if (phys_p->s_id != 0)
292: *des_p = dirty_plate;
293: else
294: *des_p = clean_plate;
295: }
296:
297: des_p->s_window = w;
298: des_p->s_flags = 0;
299: if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine)
300: des_p->s_flags = MODELINE | DIRTY;
301: }
302:
303: /* Write whatever is in mesgbuf (maybe we are Asking, or just printed
304: a message). Turns off the UpdateMesg line flag. */
305:
306: DrawMesg(abortable)
307: {
308: if (charp())
309: return;
310: i_set(ILI, 0);
311: if (swrite(mesgbuf, NIL, abortable)) {
312: cl_eol();
313: UpdMesg = 0;
314: }
315: flusho();
316: }
317:
318: /* Goto the current position in the current window. Presumably redisplay()
319: has already been called, and curwind->{w_dotline,w_dotcol} have been set
320: correctly. */
321:
322: GotoDot()
323: {
324: if (InputPending)
325: return;
326: Placur(curwind->w_dotline, curwind->w_dotcol -
327: PhysScreen[curwind->w_dotline].s_offset);
328: flusho();
329: }
330:
331: private
332: UntilEqual(start)
333: register int start;
334: {
335: register struct scrimage *des_p = &DesiredScreen[start],
336: *phys_p = &PhysScreen[start];
337:
338: while ((start < ILI) && (des_p->s_id != phys_p->s_id)) {
339: des_p++;
340: phys_p++;
341: start++;
342: }
343:
344: return start;
345: }
346:
347: /* Calls the routine to do the physical changes, and changes PhysScreen to
348: reflect those changes. */
349:
350: AddLines(at, num)
351: register int at,
352: num;
353: {
354: register int i;
355: int bottom = UntilEqual(at + num);
356:
357: if (num == 0 || num >= ((bottom - 1) - at))
358: return 0; /* We did nothing */
359: v_ins_line(num, at, bottom - 1);
360:
361: /* Now change PhysScreen to account for the physical change. */
362:
363: for (i = bottom - 1; i - num >= at; i--)
364: PhysScreen[i] = PhysScreen[i - num];
365: for (i = 0; i < num; i++)
366: PhysScreen[at + i].s_id = 0;
367: return 1; /* We did something. */
368: }
369:
370: DelLines(at, num)
371: register int at,
372: num;
373: {
374: register int i;
375: int bottom = UntilEqual(at + num);
376:
377: if (num == 0 || num >= ((bottom - 1) - at))
378: return 0;
379: v_del_line(num, at, bottom - 1);
380:
381: for (i = at; num + i < bottom; i++)
382: PhysScreen[i] = PhysScreen[num + i];
383: for (i = bottom - num; i < bottom; i++)
384: PhysScreen[i].s_id = 0;
385: return 1;
386: }
387:
388: /* Update line linenum in window w. Only set PhysScreen to DesiredScreen
389: if the swrite or cl_eol works, that is nothing is interupted by
390: characters typed. */
391:
392: UpdLine(linenum)
393: register int linenum;
394: {
395: register struct scrimage *des_p = &DesiredScreen[linenum];
396: register Window *w = des_p->s_window;
397:
398: i_set(linenum, 0);
399: if (des_p->s_flags & MODELINE)
400: ModeLine(w);
401: else if (des_p->s_id) {
402: des_p->s_lp->l_dline &= ~DIRTY;
403: des_p->s_flags &= ~(DIRTY | L_MOD);
404: #ifdef ID_CHAR
405: if (!UseIC && w->w_numlines)
406: #else
407: if (w->w_numlines)
408: #endif
409: (void) swrite(sprint("%6d ", des_p->s_vln), NIL, YES);
410:
411: #ifdef ID_CHAR
412: if (UseIC) {
413: char outbuf[256],
414: *lptr;
415: int fromcol = w->w_numlines ? 8 : 0;
416:
417: if (w->w_numlines)
418: sprintf(outbuf, "%6d ", des_p->s_vln);
419: lptr = lcontents(des_p->s_lp);
420: DeTab(des_p->s_offset, lptr, outbuf + fromcol,
421: (sizeof outbuf) - 1 - fromcol,
422: des_p->s_window->w_visspace);
423: if (IDchar(outbuf, linenum, 0))
424: PhysScreen[linenum] = *des_p;
425: else if (i_set(linenum, 0), swrite(outbuf, NIL, YES))
426: do_cl_eol(linenum);
427: else
428: PhysScreen[linenum].s_id = -1;
429: } else
430: #endif ID_CHAR
431: if (BufSwrite(linenum))
432: do_cl_eol(linenum);
433: else
434: PhysScreen[linenum].s_id = -1;
435: } else if (PhysScreen[linenum].s_id) /* Not the same ... make sure */
436: do_cl_eol(linenum);
437: }
438:
439: do_cl_eol(linenum)
440: register int linenum;
441: {
442: cl_eol();
443: PhysScreen[linenum] = DesiredScreen[linenum];
444: }
445:
446: #ifdef ID_CHAR
447:
448: /* From here to the end of the file is code that tries to utilize the
449: insert/delete character feature on some terminals. It is very confusing
450: and not so well written code, AND there is a lot of it. You may want
451: to use the space for something else. */
452:
453: extern struct screenline *Screen;
454: int IN_INSmode = 0;
455:
456: int UseIC;
457:
458: int DClen,
459: MDClen,
460: IClen,
461: MIClen,
462: IMlen,
463: CElen;
464:
465: disp_opt_init()
466: {
467: DClen = DC ? strlen(DC) : 0;
468: MDClen = M_DC ? strlen(M_DC) : 9999;
469: IClen = IC ? strlen(IC) : 0;
470: MIClen = M_IC ? strlen(M_IC) : 9999;
471: IMlen = IM ? strlen(IM) : 0;
472: CElen = CE ? strlen(CE) : 0;
473:
474: UseIC = (IC || IM || M_IC);
475: }
476:
477: INSmode(on)
478: {
479: if (on && !IN_INSmode) {
480: putpad(IM, 1);
481: IN_INSmode++;
482: } else if (!on && IN_INSmode) {
483: putpad(EI, 1);
484: IN_INSmode = 0;
485: }
486: }
487:
488: private
489: DeTab(s_offset, buf, outbuf, limit, visspace)
490: register char *buf;
491: char *outbuf;
492: {
493: register char *phys_p = outbuf,
494: c;
495: register int pos = 0;
496: char *limitp = &outbuf[limit];
497:
498: #define OkayOut(ch) if ((pos++ >= s_offset) && (phys_p < limitp))\
499: *phys_p++ = ch;\
500: else
501:
502: while (c = *buf++) {
503: if (c == '\t') {
504: int nchars = (tabstop - (pos % tabstop));
505:
506: if (visspace) {
507: OkayOut('>');
508: --nchars;
509: }
510: while (--nchars >= 0)
511: OkayOut(' ');
512:
513: } else if (isctrl(c)) {
514: OkayOut('^');
515: OkayOut(c == 0177 ? '?' : c + '@');
516: } else {
517: if (visspace && c == ' ')
518: c = '_';
519: OkayOut(c);
520: }
521: if (pos - s_offset >= CO) {
522: phys_p = &outbuf[CO - 1];
523: *phys_p++ = '!';
524: break;
525: }
526: }
527: *phys_p = 0;
528: }
529:
530: /* ID character routines full of special cases and other fun stuff like that.
531: It actually works though ...
532:
533: Returns Non-Zero if you are finished (no differences left). */
534:
535: private
536: IDchar(new, lineno, col)
537: register char *new;
538: {
539: register int i;
540: int j,
541: oldlen,
542: NumSaved;
543: register struct screenline *sline = &Screen[lineno];
544:
545: oldlen = sline->s_length - sline->s_line;
546:
547: for (i = col; i < oldlen && new[i] != 0; i++)
548: if (sline->s_line[i] != new[i])
549: break;
550: if (new[i] == 0 || i == oldlen)
551: return (new[i] == 0 && i == oldlen);
552:
553: for (j = i + 1; j < oldlen && new[j]; j++) {
554: if (new[j] == sline->s_line[i]) {
555: NumSaved = IDcomp(new + j, sline->s_line + i,
556: strlen(new)) + NumSimilar(new + i,
557: sline->s_line + i, j - i);
558: if (OkayInsert(NumSaved, j - i)) {
559: InsChar(lineno, i, j - i, new);
560: return(IDchar(new, lineno, j));
561: }
562: }
563: }
564:
565: for (j = i + 1; j < oldlen && new[i]; j++) {
566: if (new[i] == sline->s_line[j]) {
567: NumSaved = IDcomp(new + i, sline->s_line + j,
568: oldlen - j);
569: if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) {
570: DelChar(lineno, i, j - i);
571: return(IDchar(new, lineno, j));
572: }
573: }
574: }
575: return 0;
576: }
577:
578: private
579: NumSimilar(s, t, n)
580: register char *s,
581: *t;
582: {
583: register int num = 0;
584:
585: while (n--)
586: if (*s++ == *t++)
587: num++;
588: return num;
589: }
590:
591: private
592: IDcomp(s, t, len)
593: register char *s,
594: *t;
595: {
596: register int i;
597: int num = 0,
598: nonspace = 0;
599: char c;
600:
601: for (i = 0; i < len; i++) {
602: if ((c = *s++) != *t++)
603: break;
604: if (c != ' ')
605: nonspace++;
606: if (nonspace)
607: num++;
608: }
609:
610: return num;
611: }
612:
613: private
614: OkayDelete(Saved, num, samelength)
615: {
616: /* If the old and the new are the same length, then we don't
617: * have to clear to end of line. We take that into consideration.
618: */
619: return ((Saved + (!samelength ? CElen : 0))
620: > min(MDClen, DClen * num));
621: }
622:
623: private
624: OkayInsert(Saved, num)
625: {
626: register int n = 0;
627:
628: if (IC) /* Per character prefixes */
629: n = min(num * IClen, MIClen);
630:
631: if (IM && !IN_INSmode) {
632: /* Good terminal. Fewer characters in this case */
633: n += IMlen;
634: }
635:
636: n += num; /* The characters themselves */
637:
638: return Saved > n;
639: }
640:
641: extern int CapCol;
642: extern char *cursend;
643: extern struct screenline *Curline;
644:
645: private
646: DelChar(lineno, col, num)
647: {
648: register char *from,
649: *to;
650: register int i;
651: struct screenline *sp = (&Screen[lineno]);
652:
653: Placur(lineno, col);
654: if (M_DC && num > 1) {
655: char minibuf[16];
656:
657: sprintf(minibuf, M_DC, num);
658: putpad(minibuf, num);
659: } else {
660: for (i = num; --i >= 0; )
661: putpad(DC, 1);
662: }
663:
664: to = sp->s_line + col;
665: from = to + num;
666:
667: byte_copy(from, to, sp->s_length - from + 1);
668: clrline(sp->s_length - num, sp->s_length);
669: sp->s_length -= num;
670: }
671:
672: private
673: InsChar(lineno, col, num, new)
674: char *new;
675: {
676: register char *sp1,
677: *sp2, /* To push over the array. */
678: *sp3; /* Last character to push over. */
679: int i;
680:
681: i_set(lineno, 0);
682: sp2 = Curline->s_length + num;
683:
684: if (sp2 >= cursend) {
685: i_set(lineno, CO - num - 1);
686: cl_eol();
687: sp2 = cursend - 1;
688: }
689: Curline->s_length = sp2;
690: sp1 = sp2 - num;
691: sp3 = Curline->s_line + col;
692:
693: while (sp1 >= sp3)
694: *sp2-- = *sp1--;
695:
696: new += col;
697: byte_copy(new, sp3, num);
698: /* The internal screen is correct, and now we have to do
699: the physical stuff. */
700:
701: Placur(lineno, col);
702: if (IM) {
703: if (!IN_INSmode)
704: INSmode(1);
705: } else if (M_IC && num > 1) {
706: char minibuf[16];
707:
708: sprintf(minibuf, M_IC, num);
709: putpad(minibuf, num);
710: } else if (IC) {
711: for (i = 0; i < num; i++)
712: putpad(IC, 1);
713: }
714: for (i = 0; i < num; i++) {
715: putchar(new[i]);
716: if (IN_INSmode)
717: putpad(IP, 1);
718: }
719: CapCol += num;
720: }
721:
722: #endif ID_CHAR
723:
724: /* chkmail() returns nonzero if there is new mail since the
725: last time we checked. */
726:
727: char Mailbox[128]; /* initialized in main */
728: int MailInt = 60; /* check no more often than 60 seconds */
729: #ifdef BIFF
730: int BiffChk = NO; /* whether or not to turn off biff while in JOVE */
731: #endif
732:
733: chkmail(force)
734: {
735: time_t now;
736: static time_t last_chk = 0;
737: static int value = FALSE;
738: static off_t last_size = 0;
739: struct stat stbuf;
740: int last_val;
741: extern time_t time0;
742:
743: time(&now);
744: if (!force && (now < last_chk + MailInt))
745: return value;
746: if (stat(Mailbox, &stbuf) < 0)
747: return FALSE;
748: last_val = value;
749: value = ((stbuf.st_mtime > time0) &&
750: (stbuf.st_size > 0) &&
751: (stbuf.st_size > last_size) &&
752: (stbuf.st_mtime + 5 > stbuf.st_atime));
753: last_chk = now;
754: last_size = stbuf.st_size;
755: if (value == TRUE && value != last_val)
756: dobell(3);
757: return value;
758: }
759:
760: /* Print the mode line. */
761:
762: private char *mode_p,
763: *mend_p;
764: int BriteMode = 1; /* modeline should standout */
765:
766: private
767: mode_app(str)
768: register char *str;
769: {
770: if (mode_p >= mend_p)
771: return;
772: while ((mode_p < mend_p) && (*mode_p++ = *str++))
773: ;
774: mode_p--; /* back over the null */
775: }
776:
777: char ModeFmt[120] = "%3c %[%sJOVE (%M) Buffer: %b \"%f\" %]%s%m %((%t)%s%)%e";
778:
779: ModeLine(w)
780: register Window *w;
781: {
782: extern int i_line;
783: int n,
784: ign_some = 0;
785: char line[132],
786: *fmt = ModeFmt,
787: tmp[16],
788: fillc,
789: c;
790: register Buffer *thisbuf = w->w_bufp;
791: register Buffer *bp;
792:
793: mode_p = line;
794: mend_p = &line[(sizeof line) - 1];
795:
796: if (BriteMode != 0 && SO == 0)
797: BriteMode = 0;
798: fillc = BriteMode ? ' ' : '-';
799:
800: while (c = *fmt++) {
801: if (c == '\\')
802: c = *fmt++;
803: if (c != '%') {
804: if (!ign_some)
805: *mode_p++ = c;
806: continue;
807: }
808: c = *fmt++; /* Character after the percent! */
809: if (ign_some && c != ')')
810: continue;
811: n = 1;
812: if (c >= '0' && c <= '9') {
813: n = 0;
814: while (c >= '0' && c <= '9') {
815: n = n * 10 + (c - '0');
816: c = *fmt++;
817: }
818: }
819: switch (c) {
820: case '(':
821: if (w->w_next != fwind) /* Not bottom window. */
822: ign_some++;
823: break;
824:
825: case ')':
826: ign_some = 0;
827: break;
828:
829: case 'c':
830: while (--n >= 0)
831: *mode_p++ = fillc;
832: break;
833:
834: case '[':
835: case ']':
836: {
837: char *strs = (c == '[') ? "[[[[[[[[[[" : "]]]]]]]]]]";
838:
839: mode_app(strs + 10 - RecDepth);
840: break;
841: }
842:
843: case 's':
844: if (mode_p[-1] == ' ')
845: continue;
846: *mode_p++ = ' ';
847: break;
848:
849: case 'M':
850: {
851: static char *mmodes[] = {
852: "Fundamental ",
853: "Text ",
854: "C ",
855: #ifdef LISP
856: "Lisp ",
857: #endif
858: 0
859: };
860:
861: mode_app(mmodes[thisbuf->b_major]);
862:
863: if (BufMinorMode(thisbuf, Fill))
864: mode_app("Fill ");
865: if (BufMinorMode(thisbuf, Abbrev))
866: mode_app("Abbrev ");
867: if (BufMinorMode(thisbuf, OverWrite))
868: mode_app("OvrWt ");
869: if (BufMinorMode(thisbuf, Indent))
870: mode_app("AI ");
871: if (KeyMacro.m_flags & DEFINE)
872: mode_app("Def ");
873: mode_p--; /* Back over the extra space. */
874: break;
875: }
876:
877: case 'b':
878: mode_app(thisbuf->b_name);
879: break;
880:
881: case 'f':
882: case 'F':
883: if (thisbuf->b_fname == 0)
884: mode_app("[No file]");
885: else {
886: if (c == 'f')
887: mode_app(pr_name(thisbuf->b_fname));
888: else
889: mode_app(basename(thisbuf->b_fname));
890: }
891: break;
892:
893:
894: case 'n':
895: for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++)
896: if (bp == thisbuf)
897: break;
898:
899: sprintf(tmp, "%d", n);
900: mode_app(tmp);
901: break;
902:
903: case 'm':
904: if (IsModified(w->w_bufp))
905: *mode_p++ = '*';
906: else
907: *mode_p++ = ' ';
908: break;
909:
910: case 't':
911: {
912: char timestr[12];
913:
914: mode_app(get_time((time_t *) 0, timestr, 11, 16));
915: break;
916: }
917:
918: #ifdef LOAD_AV
919: case 'l':
920: {
921: double theavg;
922: char minibuf[10];
923:
924: get_la(&theavg);
925: theavg += .005; /* round to nearest .01 */
926: sprintf(minibuf, "%d.%02d",
927: (int) theavg,
928: (int)((theavg - (int) theavg) * 100));
929: mode_app(minibuf);
930: }
931: break;
932: #endif
933:
934: case 'C': /* check mail here */
935: if (chkmail(NO))
936: mode_app("[New mail]");
937: break;
938:
939: #ifdef CHDIR
940: case 'd': /* print working directory */
941: mode_app(pr_name(pwd()));
942: break;
943: #endif
944:
945: case 'e':
946: {
947: /* 2 space pad pluss padding for magic cookies */
948: char *last_p = &line[CO - 2 - (2 * SG)];
949:
950: while (mode_p < last_p)
951: *mode_p++ = fillc;
952:
953: goto outahere; /* %e means we're done! */
954: }
955: }
956: }
957:
958: outahere:
959: *mode_p = 0;
960:
961: /* Highlight mode line. */
962: if (BriteMode) {
963: #ifdef ID_CHAR
964: if (IN_INSmode)
965: INSmode(0);
966: #endif
967: putpad(SO, 1);
968: }
969: if (swrite(line, BriteMode, YES))
970: do_cl_eol(i_line);
971: if (BriteMode)
972: putpad(SE, 1);
973: }
974:
975: RedrawDisplay()
976: {
977: Line *newtop = prev_line((curwind->w_line = curline), exp_p ?
978: exp : HALF(curwind));
979:
980: if (newtop == curwind->w_top)
981: v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind));
982: else
983: SetTop(curwind, newtop);
984: }
985:
986: v_clear(line1, line2)
987: register int line1;
988: {
989: register struct scrimage *phys_p, *des_p;
990:
991: phys_p = &PhysScreen[line1];
992: des_p = &DesiredScreen[line1];
993:
994: while (line1 <= line2) {
995: i_set(line1++, 0);
996: cl_eol();
997: phys_p->s_id = des_p->s_id = 0;
998: phys_p++, des_p++;
999: }
1000: }
1001:
1002: ClAndRedraw()
1003: {
1004: cl_scr(1);
1005: }
1006:
1007: NextPage()
1008: {
1009: Line *newline;
1010:
1011: if (Asking)
1012: return;
1013: if (exp < 0) {
1014: exp = -exp;
1015: PrevPage();
1016: return;
1017: }
1018: if (exp_p)
1019: UpScroll();
1020: else {
1021: if (in_window(curwind, curwind->w_bufp->b_last) != -1) {
1022: rbell();
1023: return;
1024: }
1025: newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1));
1026: SetTop(curwind, curwind->w_line = newline);
1027: if (curwind->w_bufp == curbuf)
1028: SetLine(newline);
1029: }
1030: }
1031:
1032: PrevPage()
1033: {
1034: Line *newline;
1035:
1036: if (Asking)
1037: return;
1038: if (exp < 0) {
1039: exp = -exp;
1040: NextPage();
1041: return;
1042: }
1043: if (exp_p)
1044: DownScroll();
1045: else {
1046: newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1));
1047: SetTop(curwind, curwind->w_line = newline);
1048: if (curwind->w_bufp == curbuf)
1049: SetLine(newline);
1050: }
1051: }
1052:
1053: UpScroll()
1054: {
1055: SetTop(curwind, next_line(curwind->w_top, exp));
1056: if ((curwind->w_bufp == curbuf) &&
1057: (in_window(curwind, curline) == -1))
1058: SetLine(curwind->w_top);
1059: }
1060:
1061: DownScroll()
1062: {
1063: SetTop(curwind, prev_line(curwind->w_top, exp));
1064: if ((curwind->w_bufp == curbuf) &&
1065: (in_window(curwind, curline) == -1))
1066: SetLine(curwind->w_top);
1067: }
1068:
1069: int VisBell = 0,
1070: RingBell = 0; /* So if we have a lot of errors ...
1071: ring the bell only ONCE */
1072: rbell()
1073: {
1074: RingBell++;
1075: }
1076:
1077: /* Message prints the null terminated string onto the bottom line of the
1078: terminal. */
1079:
1080: message(str)
1081: char *str;
1082: {
1083: if (InJoverc)
1084: return;
1085: UpdMesg++;
1086: errormsg = 0;
1087: if (str != mesgbuf)
1088: null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1);
1089: }
1090:
1091: /* End of Window */
1092:
1093: Eow()
1094: {
1095: if (Asking)
1096: return;
1097: SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 -
1098: min(SIZE(curwind) - 1, exp - 1)));
1099: if (!exp_p)
1100: Eol();
1101: }
1102:
1103: /* Beginning of Window */
1104:
1105: Bow()
1106: {
1107: if (Asking)
1108: return;
1109: SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, exp - 1)));
1110: }
1111:
1112: private int LineNo,
1113: last_col,
1114: DoAutoNL;
1115: private Window *old_wind; /* save the window we were in BEFORE
1116: before we were called, if UseBuffers
1117: is nonzero */
1118:
1119: int UseBuffers = FALSE;
1120: int TOabort = 0;
1121:
1122: /* This initializes the typeout. If send-typeout-to-buffers is set
1123: the buffer NAME is created (emptied if it already exists) and output
1124: goes to the buffer. Otherwise output is drawn on the screen and
1125: erased by TOstop() */
1126:
1127: TOstart(name, auto_newline)
1128: char *name;
1129: {
1130: if (UseBuffers) {
1131: old_wind = curwind;
1132: pop_wind(name, YES, B_SCRATCH);
1133: }
1134: TOabort = LineNo = last_col = 0;
1135: DoAutoNL = auto_newline;
1136: }
1137:
1138: /* VARARGS1 */
1139:
1140: Typeout(fmt, va_alist)
1141: char *fmt;
1142: va_dcl
1143: {
1144: if (TOabort)
1145: return;
1146:
1147: if (!UseBuffers && (LineNo == ILI - 1)) {
1148: register int c;
1149:
1150: LineNo = 0;
1151: last_col = 0;
1152: f_mess("--more--");
1153: if ((c = getchar()) != ' ') {
1154: TOabort++;
1155: if (c != CTL(G) && c != RUBOUT)
1156: Ungetc(c);
1157: return;
1158: }
1159: f_mess(NullStr);
1160: }
1161:
1162: if (fmt) {
1163: extern int i_col;
1164: char string[132];
1165: va_list ap;
1166:
1167: va_start(ap);
1168: format(string, sizeof string, fmt, ap);
1169: va_end(ap);
1170: if (UseBuffers)
1171: ins_str(string, NO);
1172: else {
1173: i_set(LineNo, last_col);
1174: (void) swrite(string, NIL, YES);
1175: last_col = i_col;
1176: }
1177: }
1178: if (!UseBuffers) {
1179: PhysScreen[LineNo].s_id = -1;
1180: if (fmt == 0 || DoAutoNL != 0) {
1181: cl_eol();
1182: flusho();
1183: LineNo++;
1184: last_col = 0;
1185: }
1186: } else if (fmt == 0 || DoAutoNL != 0)
1187: ins_str("\n", NO);
1188: }
1189:
1190: TOstop()
1191: {
1192: int c;
1193:
1194: if (UseBuffers) {
1195: ToFirst();
1196: SetWind(old_wind);
1197: } else {
1198: if (TOabort)
1199: return;
1200: if (last_col != 0)
1201: Typeout((char *) 0);
1202: Typeout("----------");
1203: cl_eol();
1204: flusho();
1205: c = getchar();
1206: if (c != ' ')
1207: Ungetc(c);
1208: }
1209: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.