rsalz@bbn.com (Rich Salz) (04/28/88)
Submitted-by: Jonathan Payne <jpayne@cs.rochester.edu> Posting-number: Volume 14, Issue 69 Archive-name: jove4.9/part13 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 13 (of 21)." PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f './disp.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./disp.c'\" else echo shar: Extracting \"'./disp.c'\" \(28346 characters\) sed "s/^X//" >'./disp.c' <<'END_OF_FILE' X/*************************************************************************** X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * X * is provided to you without charge, and with no warranty. You may give * X * away copies of JOVE, including sources, provided that this notice is * X * included in all the files. * X ***************************************************************************/ X X#include "jove.h" X#include "ctype.h" X#include "termcap.h" X X X#ifdef MAC X# include "mac.h" X#else X# include <varargs.h> X# include <sys/stat.h> X#endif X X#include <signal.h> X X#ifdef MAC X# undef private X# define private X#endif X X#ifdef LINT_ARGS private void X#ifdef ID_CHAR X DeTab(int, char *, char *, int, int), X DelChar(int, int, int), X InsChar(int, int, int, char *), X#endif X DoIDline(int), X do_cl_eol(int), X ModeLine(Window *), X mode_app(char *), X GotoDot(void), X UpdLine(int), X UpdWindow(Window *, int); X private int X AddLines(int, int), X DelLines(int, int), X UntilEqual(int); X#else private void X#ifdef ID_CHAR X DeTab(), X DelChar(), X InsChar(), X#endif X DoIDline(), X do_cl_eol(), X GotoDot(), X ModeLine(), X mode_app(), X UpdLine(), X UpdWindow(); private int X AddLines(), X DelLines(), X UntilEqual(); X#endif /* LINT_ARGS */ X X#ifdef MAC X# undef private X# define private static X#endif X int DisabledRedisplay = NO; X X/* Kludge windows gets called by the routines that delete lines from the X buffer. If the w->w_line or w->w_top are deleted and this procedure X is not called, the redisplay routine will barf. */ X void ChkWindows(line1, line2) Line *line1; register Line *line2; X{ X register Window *w = fwind; X register Line *lp; X X do { X for (lp = line1->l_next; lp != line2->l_next; lp = lp->l_next) { X if (lp == w->w_top) X w->w_flags |= W_TOPGONE; X if (lp == w->w_line) X w->w_flags |= W_CURGONE; X } X w = w->w_next; X } while (w != fwind); X} X extern int RingBell; X void redisplay() X{ X extern int AbortCnt; X register Window *w = fwind; X int lineno, X done_ID = NO, X i; X register struct scrimage *des_p, X *phys_p; X X if (DisabledRedisplay == YES) X return; X curwind->w_line = curwind->w_bufp->b_dot; X curwind->w_char = curwind->w_bufp->b_char; X#ifdef MAC X InputPending = 0; X#else X if (InputPending = charp()) /* calls CheckEvent, which could */ X return; /* result in a call to rediplay(). We don't want that. */ X#endif X#ifdef JOB_CONTROL X if (UpdFreq) X sighold(SIGALRM); X#endif X if (RingBell) { X dobell(1); X RingBell = 0; X } X AbortCnt = BufSize; /* initialize this now */ X if (UpdMesg) X DrawMesg(YES); X X for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) { X UpdWindow(w, lineno); X lineno += w->w_height; X } X X UpdModLine = 0; /* Now that we've called update window, we can X assume that the modeline will be updated. But X if while redrawing the modeline the user types X a character, ModeLine() is free to set this on X again so that the modeline will be fully drawn X at the next redisplay. */ X X des_p = DesiredScreen; X phys_p = PhysScreen; X for (i = 0; i < ILI; i++, des_p++, phys_p++) { X if (!done_ID && (des_p->s_id != phys_p->s_id)) { X DoIDline(i); X done_ID = YES; X } X if ((des_p->s_flags & (DIRTY | L_MOD)) || X (des_p->s_id != phys_p->s_id) || X (des_p->s_vln != phys_p->s_vln) || X (des_p->s_offset != phys_p->s_offset)) X UpdLine(i); X if (InputPending) X goto ret; X } X X X if (Asking) { X Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, Asking))); X /* Nice kludge */ X flusho(); X } else X GotoDot(); ret: X#ifdef JOB_CONTROL X if (UpdFreq) X sigrelse(SIGALRM); X#else X ; /* yuck */ X#endif X#ifdef MAC X if(Windchange) docontrols(); X#endif /* MAC */ X} X X#ifndef IBMPC private void dobell(n) X{ X while (--n >= 0) { X#ifndef MAC X if (VisBell && VB) X putstr(VB); X else X putpad(BL, 1); X#else X SysBeep(5); X#endif X } X flusho(); X} X#endif /* IBMPC */ X X/* find_pos() returns the position on the line, that C_CHAR represents X in LINE */ X int find_pos(line, c_char) Line *line; X{ X return calc_pos(lcontents(line), c_char); X} X int calc_pos(lp, c_char) register char *lp; register int c_char; X{ X register int pos = 0; X register int c; X X X while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) { X if (c == '\t') X pos += (tabstop - (pos % tabstop)); X else if (isctrl(c)) X pos += 2; X else X pos += 1; X } X return pos; X} X int UpdModLine = 0, X UpdMesg = 0, X CanScroll = 0; X private void DoIDline(start) X{ X register struct scrimage *des_p = &DesiredScreen[start]; X struct scrimage *phys_p = &PhysScreen[start]; X register int i, X j; X X /* Some changes have been made. Try for insert or delete lines. X If either case has happened, Addlines and/or DelLines will do X necessary scrolling, also CONVERTING PhysScreen to account for the X physical changes. The comparison continues from where the X insertion/deletion takes place; this doesn't happen very often, X usually it happens with more than one window with the same X buffer. */ X X if (!CanScroll) X return; /* We should never have been called! */ X X for (i = start; i < ILI; i++, des_p++, phys_p++) X if (des_p->s_id != phys_p->s_id) X break; X X for (; i < ILI; i++) { X for (j = i + 1; j < ILI; j++) { X des_p = &DesiredScreen[j]; X phys_p = &PhysScreen[j]; X if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id) X break; X if (des_p->s_id == PhysScreen[i].s_id) { X if (des_p->s_id == 0) X continue; X if (AddLines(i, j - i)) { X DoIDline(j); X return; X } X break; X } X if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) { X if (des_p->s_id == 0) X continue; X if (DelLines(i, j - i)) { X DoIDline(i); X return; X } X break; X } X } X } X} X X/* Make DesiredScreen reflect what the screen should look like when we are done X with the redisplay. This deals with horizontal scrolling. Also makes X sure the current line of the Window is in the window. */ X int ScrollAll = NO; X private void UpdWindow(w, start) register Window *w; X{ X Line *lp; X int i, X upper, /* top of window */ X lower, /* bottom of window */ X strt_col, /* starting print column of current line */ X ntries = 0; /* # of tries at updating window */ X register struct scrimage *des_p, X *phys_p; X Buffer *bp = w->w_bufp; X retry: X if (w->w_flags & W_CURGONE) { X w->w_line = bp->b_dot; X w->w_char = bp->b_char; X } X if (w->w_flags & W_TOPGONE) X CentWind(w); /* reset topline of screen */ X w->w_flags &= ~(W_CURGONE | W_TOPGONE); X X /* make sure that the current line is in the window */ X upper = start; X lower = upper + w->w_height - 1; /* don't include modeline */ X for (i = upper, lp = w->w_top; i < lower && lp != 0; lp = lp->l_next, i++) X if (lp == w->w_line) X break; X if (i == lower || lp == 0) { X ntries += 1; X if (ntries == 1) { X CalcWind(w); X goto retry; X } else if (ntries == 2) { X w->w_top = w->w_line = w->w_bufp->b_first; X printf("\rERROR in redisplay: I got hopelessly lost!"); X dobell(2); X goto retry; X } else if (ntries == 3) { X printf("\n\rOops, still lost, quitting ...\r\n"); X finish(1); X } X } X X /* first do some calculations for the current line */ X { X int diff = (w->w_flags & W_NUMLINES) ? 8 : 0, X end_col; X X strt_col = (ScrollAll == YES) ? w->w_LRscroll : X PhysScreen[i].s_offset; X end_col = strt_col + (CO - 2) - diff; X /* Right now we are displaying from strt_col to X end_col of the buffer line. These are PRINT X columns, not actual characters. */ X w->w_dotcol = find_pos(w->w_line, w->w_char); X /* if the new dotcol is out of range, reselect X a horizontal window */ X if ((PhysScreen[i].s_offset == -1) || X (w->w_dotcol < strt_col) || X (w->w_dotcol >= end_col)) { X if (w->w_dotcol < ((CO - 2) - diff)) X strt_col = 0; X else X strt_col = w->w_dotcol - (CO / 2); X if (ScrollAll == YES) { X if (w->w_LRscroll != strt_col) X UpdModLine = YES; X w->w_LRscroll = strt_col; X } X } X w->w_dotline = i; X w->w_dotcol += diff; X } X X des_p = &DesiredScreen[upper]; X phys_p = &PhysScreen[upper]; X for (i = upper, lp = w->w_top; lp != 0 && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) { X des_p->s_window = w; X des_p->s_lp = lp; X des_p->s_id = lp->l_dline & ~DIRTY; X des_p->s_flags = isdirty(lp) ? L_MOD : 0; X if (w->w_flags & W_NUMLINES) X des_p->s_vln = w->w_topnum + (i - upper); X else X des_p->s_vln = 0; X X if (lp == w->w_line) X des_p->s_offset = strt_col; X else X des_p->s_offset = w->w_LRscroll; X } X X /* Is structure assignment faster than copy each field separately? */ X if (i < lower) { X static struct scrimage dirty_plate = { 0, DIRTY, 0, 0, 0, 0 }, X clean_plate = { 0, 0, 0, 0, 0, 0 }; X X for (; i < lower; i++, des_p++, phys_p++) X if (phys_p->s_id != 0) X *des_p = dirty_plate; X else X *des_p = clean_plate; X } X X des_p->s_window = w; X des_p->s_flags = 0; X if (((des_p->s_id = (int) w->w_bufp) != phys_p->s_id) || UpdModLine) X des_p->s_flags = MODELINE | DIRTY; X#ifdef MAC X if(UpdModLine) Modechange = 1; X if(w == curwind && w->w_control) SetScrollBar(w->w_control); X#endif X} X X/* Write whatever is in mesgbuf (maybe we are Asking, or just printed X a message). Turns off the UpdateMesg line flag. */ X void DrawMesg(abortable) X{ X#ifndef MAC /* same reason as in redisplay() */ X if (charp()) X return; X#endif X i_set(ILI, 0); X if (swrite(mesgbuf, NO, abortable)) { X cl_eol(); X UpdMesg = 0; X } X flusho(); X} X X/* Goto the current position in the current window. Presumably redisplay() X has already been called, and curwind->{w_dotline,w_dotcol} have been set X correctly. */ X private void GotoDot() X{ X if (InputPending) X return; X Placur(curwind->w_dotline, curwind->w_dotcol - X PhysScreen[curwind->w_dotline].s_offset); X flusho(); X} X private int UntilEqual(start) register int start; X{ X register struct scrimage *des_p = &DesiredScreen[start], X *phys_p = &PhysScreen[start]; X X while ((start < ILI) && (des_p->s_id != phys_p->s_id)) { X des_p += 1; X phys_p += 1; X start += 1; X } X X return start; X} X X/* Calls the routine to do the physical changes, and changes PhysScreen to X reflect those changes. */ X private int AddLines(at, num) register int at, X num; X{ X register int i; X int bottom = UntilEqual(at + num); X X if (num == 0 || num >= ((bottom - 1) - at)) X return NO; /* we did nothing */ X v_ins_line(num, at, bottom - 1); X X /* Now change PhysScreen to account for the physical change. */ X X for (i = bottom - 1; i - num >= at; i--) X PhysScreen[i] = PhysScreen[i - num]; X for (i = 0; i < num; i++) X PhysScreen[at + i].s_id = 0; X return YES; /* we did something */ X} X private int DelLines(at, num) register int at, X num; X{ X register int i; X int bottom = UntilEqual(at + num); X X if (num == 0 || num >= ((bottom - 1) - at)) X return NO; X v_del_line(num, at, bottom - 1); X X for (i = at; num + i < bottom; i++) X PhysScreen[i] = PhysScreen[num + i]; X for (i = bottom - num; i < bottom; i++) X PhysScreen[i].s_id = 0; X return YES; X} X X/* Update line linenum in window w. Only set PhysScreen to DesiredScreen X if the swrite or cl_eol works, that is nothing is interupted by X characters typed. */ X private void UpdLine(linenum) register int linenum; X{ X register struct scrimage *des_p = &DesiredScreen[linenum]; X register Window *w = des_p->s_window; X X i_set(linenum, 0); X if (des_p->s_flags & MODELINE) X ModeLine(w); X else if (des_p->s_id) { X des_p->s_lp->l_dline &= ~DIRTY; X des_p->s_flags &= ~(DIRTY | L_MOD); X#ifdef ID_CHAR X if (!UseIC && (w->w_flags & W_NUMLINES)) X#else X if (w->w_flags & W_NUMLINES) X#endif X (void) swrite(sprint("%6d ", des_p->s_vln), NO, YES); X X#ifdef ID_CHAR X if (UseIC) { X char outbuf[MAXCOLS], X *lptr; X int fromcol = (w->w_flags & W_NUMLINES) ? 8 : 0; X X if (w->w_flags & W_NUMLINES) X sprintf(outbuf, "%6d ", des_p->s_vln); X lptr = lcontents(des_p->s_lp); X DeTab(des_p->s_offset, lptr, outbuf + fromcol, X (sizeof outbuf) - 1 - fromcol, X des_p->s_window->w_flags & W_VISSPACE); X if (IDchar(outbuf, linenum, 0)) X PhysScreen[linenum] = *des_p; X else if (i_set(linenum, 0), swrite(outbuf, NO, YES)) X do_cl_eol(linenum); X else X PhysScreen[linenum].s_id = -1; X } else X#endif /* ID_CHAR */ X if (BufSwrite(linenum)) X do_cl_eol(linenum); X else X PhysScreen[linenum].s_id = -1; X } else if (PhysScreen[linenum].s_id) /* not the same ... make sure */ X do_cl_eol(linenum); X} X private void do_cl_eol(linenum) register int linenum; X{ X cl_eol(); X PhysScreen[linenum] = DesiredScreen[linenum]; X} X X#ifdef ID_CHAR X X/* From here to the end of the file is code that tries to utilize the X insert/delete character feature on some terminals. It is very confusing X and not so well written code, AND there is a lot of it. You may want X to use the space for something else. */ X extern struct screenline *Screen; int IN_INSmode = 0; X int UseIC; X int DClen, X MDClen, X IClen, X MIClen, X IMlen, X CElen; X void disp_opt_init() X{ X DClen = DC ? strlen(DC) : 0; X MDClen = M_DC ? strlen(M_DC) : 9999; X IClen = IC ? strlen(IC) : 0; X MIClen = M_IC ? strlen(M_IC) : 9999; X IMlen = IM ? strlen(IM) : 0; X CElen = CE ? strlen(CE) : 0; X X UseIC = (IC || IM || M_IC); X} X void INSmode(on) X{ X if (on && !IN_INSmode) { X putpad(IM, 1); X IN_INSmode = YES; X } else if (!on && IN_INSmode) { X putpad(EI, 1); X IN_INSmode = NO; X } X} X private void DeTab(s_offset, buf, outbuf, limit, visspace) register char *buf; char *outbuf; X{ X register char *phys_p = outbuf, X c; X register int pos = 0; X char *limitp = &outbuf[limit]; X X#define OkayOut(ch) if ((pos++ >= s_offset) && (phys_p < limitp))\ X *phys_p++ = ch;\ X else X X while (c = *buf++) { X if (c == '\t') { X int nchars = (tabstop - (pos % tabstop)); X X if (visspace) { X OkayOut('>'); X nchars -= 1; X } X while (--nchars >= 0) X OkayOut(' '); X X } else if (isctrl(c)) { X OkayOut('^'); X OkayOut(c == 0177 ? '?' : c + '@'); X } else { X if (visspace && c == ' ') X c = '_'; X OkayOut(c); X } X if (pos - s_offset >= CO) { X phys_p = &outbuf[CO - 1]; X *phys_p++ = '!'; X break; X } X } X *phys_p = 0; X} X X/* ID character routines full of special cases and other fun stuff like that. X It actually works though ... X X Returns Non-Zero if you are finished (no differences left). */ X private int IDchar(new, lineno, col) register char *new; X{ X register int i; X int j, X oldlen, X NumSaved; X register struct screenline *sline = &Screen[lineno]; X X oldlen = sline->s_length - sline->s_line; X X for (i = col; i < oldlen && new[i] != 0; i++) X if (sline->s_line[i] != new[i]) X break; X if (new[i] == 0 || i == oldlen) X return (new[i] == 0 && i == oldlen); X X for (j = i + 1; j < oldlen && new[j]; j++) { X if (new[j] == sline->s_line[i]) { X NumSaved = IDcomp(new + j, sline->s_line + i, X strlen(new)) + NumSimilar(new + i, X sline->s_line + i, j - i); X if (OkayInsert(NumSaved, j - i)) { X InsChar(lineno, i, j - i, new); X return(IDchar(new, lineno, j)); X } X } X } X X for (j = i + 1; j < oldlen && new[i]; j++) { X if (new[i] == sline->s_line[j]) { X NumSaved = IDcomp(new + i, sline->s_line + j, X oldlen - j); X if (OkayDelete(NumSaved, j - i, new[oldlen] == 0)) { X DelChar(lineno, i, j - i); X return(IDchar(new, lineno, j)); X } X } X } X return 0; X} X private int NumSimilar(s, t, n) register char *s, X *t; X{ X register int num = 0; X X while (n--) X if (*s++ == *t++) X num += 1; X return num; X} X private int IDcomp(s, t, len) register char *s, X *t; X{ X register int i; X int num = 0, X nonspace = 0; X char c; X X for (i = 0; i < len; i++) { X if ((c = *s++) != *t++) X break; X if (c != ' ') X nonspace++; X if (nonspace) X num += 1; X } X X return num; X} X private int OkayDelete(Saved, num, samelength) X{ X /* If the old and the new are the same length, then we don't X * have to clear to end of line. We take that into consideration. X */ X return ((Saved + (!samelength ? CElen : 0)) X > min(MDClen, DClen * num)); X} X private int OkayInsert(Saved, num) X{ X register int n = 0; X X if (IC) /* Per character prefixes */ X n = min(num * IClen, MIClen); X X if (IM && !IN_INSmode) { X /* Good terminal. Fewer characters in this case */ X n += IMlen; X } X X n += num; /* The characters themselves */ X X return Saved > n; X} X extern int CapCol; extern char *cursend; extern struct screenline *Curline; X private void DelChar(lineno, col, num) X{ X register char *from, X *to; X register int i; X struct screenline *sp = (&Screen[lineno]); X X Placur(lineno, col); X if (M_DC && num > 1) { X char minibuf[16]; X X sprintf(minibuf, M_DC, num); X putpad(minibuf, num); X } else { X for (i = num; --i >= 0; ) X putpad(DC, 1); X } X X to = sp->s_line + col; X from = to + num; X X byte_copy(from, to, sp->s_length - from + 1); X clrline(sp->s_length - num, sp->s_length); X sp->s_length -= num; X} X private void InsChar(lineno, col, num, new) char *new; X{ X register char *sp1, X *sp2, /* To push over the array. */ X *sp3; /* Last character to push over. */ X int i; X X i_set(lineno, 0); X sp2 = Curline->s_length + num; X X if (sp2 >= cursend) { X i_set(lineno, CO - num - 1); X cl_eol(); X sp2 = cursend - 1; X } X Curline->s_length = sp2; X sp1 = sp2 - num; X sp3 = Curline->s_line + col; X X while (sp1 >= sp3) X *sp2-- = *sp1--; X X new += col; X byte_copy(new, sp3, num); X /* The internal screen is correct, and now we have to do X the physical stuff. */ X X Placur(lineno, col); X if (IM) { X if (!IN_INSmode) X INSmode(1); X } else if (M_IC && num > 1) { X char minibuf[16]; X X sprintf(minibuf, M_IC, num); X putpad(minibuf, num); X } else if (IC) { X for (i = 0; i < num; i++) X putpad(IC, 1); X } X for (i = 0; i < num; i++) { X putchar(new[i]); X if (IN_INSmode) X putpad(IP, 1); X } X CapCol += num; X} X X#endif /* ID_CHAR */ X X#ifdef UNIX /* obviously ... no mail today if not Unix*/ X X/* chkmail() returns nonzero if there is new mail since the X last time we checked. */ X char Mailbox[FILESIZE]; /* initialized in main */ int MailInt = 60; /* check no more often than 60 seconds */ X#ifdef BIFF int BiffChk = NO; /* whether or not to turn off biff while in JOVE */ X#endif X int chkmail(force) X{ X time_t now; X static time_t last_chk = 0; X static int value = FALSE; X static off_t last_size = 0; X struct stat stbuf; X int last_val; X static time_t last_time = 0; X X time(&now); X if (!force && (now < last_chk + MailInt)) X return value; X last_chk = now; X if (force) X last_time = now; X if (stat(Mailbox, &stbuf) < 0) { X value = FALSE; X return FALSE; X } X last_val = value; X value = ((stbuf.st_mtime > last_time) && X (stbuf.st_size > 0) && X (stbuf.st_size >= last_size) && X (stbuf.st_mtime + 5 > stbuf.st_atime)); X if (value == TRUE && X ((value != last_val) || (stbuf.st_size != last_size))) X dobell(3); X if (stbuf.st_size < last_size) X last_time = now; X last_size = stbuf.st_size; X return value; X} X X#endif /* UNIX */ X X/* Print the mode line. */ X private char *mode_p, X *mend_p; int BriteMode = 1; /* modeline should standout */ X private void mode_app(str) register char *str; X{ X if (mode_p >= mend_p) X return; X while ((mode_p < mend_p) && (*mode_p++ = *str++)) X ; X mode_p -= 1; /* back over the null */ X} X char ModeFmt[120] = "%3c %w %[%sJOVE (%M) Buffer: %b \"%f\" %]%s%m*- %((%t)%s%)%e"; X private void ModeLine(w) register Window *w; X{ X extern int i_line; X extern char *pwd(); X int n, X ign_some = NO; X char line[MAXCOLS], X *fmt = ModeFmt, X fillc, X c; X register Buffer *thisbuf = w->w_bufp; X register Buffer *bp; X X mode_p = line; X mend_p = &line[(sizeof line) - 1]; X X#if defined(UNIX) || (defined (MSDOS) && !defined(IBMPC)) X if (BriteMode != 0 && SO == 0) X BriteMode = 0; X fillc = BriteMode ? ' ' : '-'; X#endif /* UNIX */ X#ifdef IBMPC /* very subtle - don't mess up attributes too much */ X fillc = '-'; /*BriteMode ? ' ' : '-';*/ X#endif /* IBMPC */ X#ifdef MAC X fillc = '_'; /* looks better on a Mac */ X#endif /* MAC */ X X while (c = *fmt++) { X if (c != '%') { X if (c == '\\') X if ((c = *fmt++) == '\0') X break; X if (!ign_some) X *mode_p++ = c; X continue; X } X if ((c = *fmt++) == '\0') /* char after the '%' */ X break; X if (ign_some && c != ')') X continue; X n = 1; X if (c >= '0' && c <= '9') { X n = 0; X while (c >= '0' && c <= '9') { X n = n * 10 + (c - '0'); X c = *fmt++; X } X } X switch (c) { X case '(': X if (w->w_next != fwind) /* Not bottom window. */ X ign_some = YES; X break; X X case ')': X ign_some = NO; X break; X X case '[': X case ']': X { X char *strs = (c == '[') ? "[[[[[[[[[[" : "]]]]]]]]]]"; X X mode_app(strs + 10 - RecDepth); X break; X } X X#ifdef UNIX X case 'C': /* check mail here */ X if (chkmail(NO)) X mode_app("[New mail]"); X break; X X#endif /* UNIX */ X X case 'M': X { X static char *mmodes[] = { X "Fundamental ", X "Text ", X "C ", X#ifdef LISP X "Lisp ", X#endif X 0 X }; X X mode_app(mmodes[thisbuf->b_major]); X X if (BufMinorMode(thisbuf, Fill)) X mode_app("Fill "); X if (BufMinorMode(thisbuf, Abbrev)) X mode_app("Abbrev "); X if (BufMinorMode(thisbuf, OverWrite)) X mode_app("OvrWt "); X if (BufMinorMode(thisbuf, Indent)) X mode_app("AI "); X if (InMacDefine) X mode_app("Def "); X mode_p -= 1; /* Back over the extra space. */ X break; X } X X case 'c': X while (--n >= 0) X *mode_p++ = fillc; X break; X X#ifdef CHDIR X case 'd': /* print working directory */ X mode_app(pr_name(pwd(), YES)); X break; X#endif X X case 'e': X { X /* 2 space pad pluss padding for magic cookies */ X char *last_p = &line[CO - 2 - (2 * SG)]; X X while (mode_p < last_p) X *mode_p++ = fillc; X X goto outahere; /* %e means we're done! */ X } X X case 'b': X mode_app(thisbuf->b_name); X break; X X case 'f': X case 'F': X if (thisbuf->b_fname == 0) X mode_app("[No file]"); X else { X if (c == 'f') X mode_app(pr_name(thisbuf->b_fname, YES)); X else X mode_app(basename(thisbuf->b_fname)); X } X break; X X#ifdef LOAD_AV X case 'l': X { X double theavg; X char minibuf[10]; X X get_la(&theavg); X theavg += .005; /* round to nearest .01 */ X sprintf(minibuf, "%d.%02d", X (int) theavg, X (int)((theavg - (int) theavg) * 100)); X mode_app(minibuf); X break; X } X#endif X X case 'm': X if (IsModified(w->w_bufp)) X *mode_p++ = fmt[0]; X else X *mode_p++ = fmt[1]; X fmt += 2; /* skip two characters */ X break; X X case 'n': X { X char tmp[16]; X for (bp = world, n = 1; bp != 0; bp = bp->b_next, n++) X if (bp == thisbuf) X break; X X sprintf(tmp, "%d", n); X mode_app(tmp); X break; X } X X#ifdef IPROCS X case 'p': X if (thisbuf->b_type == B_PROCESS) { X char tmp[40]; X X sprintf(tmp, "(%s)", (thisbuf->b_process == 0) ? X "No process" : X pstate(thisbuf->b_process)); X mode_app(tmp); X break; X } X#endif X X case 's': X if (mode_p[-1] == ' ') X continue; X *mode_p++ = ' '; X break; X X case 't': X { X char timestr[12]; X X mode_app(get_time((time_t *) 0, timestr, 11, 16)); X break; X } X X case 'w': X if (w->w_LRscroll > 0) X mode_app(">"); X } X } X outahere: X *mode_p = 0; X X /* Highlight mode line. */ X if (BriteMode) { X#ifdef ID_CHAR X if (IN_INSmode) X INSmode(0); X#endif X#ifdef TERMCAP X putpad(SO, 1); X#else X SO_on(); X#endif /* TERMCAP */ X } X if (swrite(line, BriteMode, YES)) X do_cl_eol(i_line); X else X UpdModLine = 1; X if (BriteMode) X#ifdef TERMCAP X putpad(SE, 1); X#else X SO_off(); X#endif /* TERMCAP */ X} X X/* This tries to place the current line of the current window in the X center of the window, OR to place it at the arg'th line of the window. X This also causes the horizontal position of the line to be centered, X if the line needs scrolling, or moved all the way back to the left, X if that's possible. */ void RedrawDisplay() X{ X int line; X Line *newtop = prev_line((curwind->w_line = curline), is_an_arg() ? X arg_value() : HALF(curwind)); X X if ((line = in_window(curwind, curwind->w_line)) != -1) X PhysScreen[line].s_offset = -1; X if (newtop == curwind->w_top) X v_clear(FLine(curwind), FLine(curwind) + SIZE(curwind)); X else X SetTop(curwind, newtop); X} X void v_clear(line1, line2) register int line1; X{ X register struct scrimage *phys_p, *des_p; X X phys_p = &PhysScreen[line1]; X des_p = &DesiredScreen[line1]; X X while (line1 <= line2) { X i_set(line1, 0); X cl_eol(); X phys_p->s_id = des_p->s_id = 0; X phys_p += 1; X des_p += 1; X line1 += 1; X } X} X void ClAndRedraw() X{ X cl_scr(YES); X} X void NextPage() X{ X Line *newline; X X if (Asking) X return; X if (arg_value() < 0) { X negate_arg_value(); X PrevPage(); X return; X } X if (arg_type() == YES) X UpScroll(); X else { X if (in_window(curwind, curwind->w_bufp->b_last) != -1) { X rbell(); X return; X } X newline = next_line(curwind->w_top, max(1, SIZE(curwind) - 1)); X SetTop(curwind, curwind->w_line = newline); X if (curwind->w_bufp == curbuf) X SetLine(newline); X } X} X X#ifdef MSDOS /* kg */ X void PageScrollUp() X{ X int i, n; X X n = max(1, SIZE(curwind) - 1); X for (i=0; i<n; i++) { X UpScroll(); X redisplay(); X } X} X void PageScrollDown() X{ X int i, n; X X n = max(1, SIZE(curwind) - 1); X for (i=0; i<n; i++) { X DownScroll(); X redisplay(); X } X} X#endif /* MSDOS */ X void PrevPage() X{ X Line *newline; X X if (Asking) X return; X if (arg_value() < 0) { X negate_arg_value(); X NextPage(); X return; X } X if (arg_type() == YES) X DownScroll(); X else { X newline = prev_line(curwind->w_top, max(1, SIZE(curwind) - 1)); X SetTop(curwind, curwind->w_line = newline); X if (curwind->w_bufp == curbuf) X SetLine(newline); X } X} X void UpScroll() X{ X SetTop(curwind, next_line(curwind->w_top, arg_value())); X if ((curwind->w_bufp == curbuf) && X (in_window(curwind, curline) == -1)) X SetLine(curwind->w_top); X} X void DownScroll() X{ X SetTop(curwind, prev_line(curwind->w_top, arg_value())); X if ((curwind->w_bufp == curbuf) && X (in_window(curwind, curline) == -1)) X SetLine(curwind->w_top); X} X int VisBell = NO, X RingBell = NO; /* So if we have a lot of errors ... X ring the bell only ONCE */ void rbell() X{ X RingBell = YES; X} X X/* Message prints the null terminated string onto the bottom line of the X terminal. */ X void message(str) char *str; X{ X if (InJoverc) X return; X UpdMesg = YES; X errormsg = NO; X if (str != mesgbuf) X null_ncpy(mesgbuf, str, (sizeof mesgbuf) - 1); X} X X/* End of Window */ X void Eow() X{ X if (Asking) X return; X SetLine(next_line(curwind->w_top, SIZE(curwind) - 1 - X min(SIZE(curwind) - 1, arg_value() - 1))); X if (!is_an_arg()) X Eol(); X} X X/* Beginning of Window */ X void Bow() X{ X if (Asking) X return; X SetLine(next_line(curwind->w_top, min(SIZE(curwind) - 1, arg_value() - 1))); X} X private int LineNo, X last_col, X DoAutoNL; private Window *old_wind; /* save the window we were in BEFORE X before we were called, if UseBuffers X is nonzero */ X int UseBuffers = FALSE; int TOabort = 0; X X/* This initializes the typeout. If send-typeout-to-buffers is set X the buffer NAME is created (emptied if it already exists) and output X goes to the buffer. Otherwise output is drawn on the screen and X erased by TOstop() */ X void TOstart(name, auto_newline) char *name; X{ X if (UseBuffers) { X old_wind = curwind; X pop_wind(name, YES, B_SCRATCH); X } else X DisabledRedisplay = YES; X TOabort = LineNo = last_col = 0; X DoAutoNL = auto_newline; X} X X/* VARARGS1 */ X void Typeout(fmt, va_alist) char *fmt; va_dcl X{ X if (TOabort) X return; X X if (!UseBuffers && (LineNo == ILI - 1)) { X register int c; X X LineNo = 0; X last_col = 0; X f_mess("--more--"); X if ((c = getchar()) != ' ') { X TOabort = YES; X if (c != AbortChar && c != RUBOUT) X Ungetc(c); X f_mess(NullStr); X return; X } X f_mess(NullStr); X } X X if (fmt) { X extern int i_col; X char string[132]; X va_list ap; X X va_start(ap); X format(string, sizeof string, fmt, ap); X va_end(ap); X if (UseBuffers) X ins_str(string, NO); X else { X i_set(LineNo, last_col); X (void) swrite(string, NO, YES); X last_col = i_col; X } X } X if (!UseBuffers) { X PhysScreen[LineNo].s_id = -1; X if (fmt == 0 || DoAutoNL == YES) { X cl_eol(); X flusho(); X LineNo += 1; X last_col = 0; X } X } else if (fmt == 0 || DoAutoNL != 0) X ins_str("\n", NO); X} X void TOstop() X{ X int c; X X if (UseBuffers) { X ToFirst(); X SetWind(old_wind); X } else { X if (TOabort) { X DisabledRedisplay = NO; X return; X } X if (last_col != 0) X Typeout((char *) 0); X Typeout("----------"); X cl_eol(); X flusho(); X c = getchar(); X if (c != ' ') X Ungetc(c); X DisabledRedisplay = NO; X } X} END_OF_FILE if test 28346 -ne `wc -c <'./disp.c'`; then echo shar: \"'./disp.c'\" unpacked with wrong size! fi # end of './disp.c' fi echo shar: End of archive 13 \(of 21\). cp /dev/null ark13isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 21 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.