v14i069: Jove, an emacs variant, version 4.9, Part13/21
Rich Salz
rsalz at bbn.com
Thu Apr 28 10:55:20 AEST 1988
Submitted-by: Jonathan Payne <jpayne at 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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list