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