|
|
researchv9-SUN3(old)
/* EMACS_MODES: c !fill */
#include "emacs_io.h"
#include "emacs_gb.h"
#include "emacs_disp.h"
#ifdef TERMINFO
#include <sys/types.h>
#include <sys/termio.h>
#define SGTTY struct termio
#include <term.h>
#endif
/* character insert */
/* inserts count occurances of the character c in the file */
insertc(count,c)
register char c;
register int count;
{
if (count < 0) return; /* Reject bad count */
while (count--) {
if ((OVERW) && (c != EOL) && (clptr[column] != EOL)) {
clptr[column] = c;
sputl(curln,column,curln); /* fix this line */
modify(curln);
column++;
} else {
if(put(c)==0) break;
}
}
}
/* insert one character into the file at current position */
put(c)
register char c;
/* Keywords: commands:10 insertion line-representation:50 */
{
register char tc;
register int xcol;
if (c == EOL) {
nl(1);
return(1);
}
xcol=column;
while (c!= EOL) {
tc = clptr[xcol];
clptr[xcol++] = c;
c = tc;
}
modify(curln);
clptr = ckline(curln,xcol);
if (clptr == NULL) {
clptr = mkline(curln);
*(clptr+xcol-1) = EOL;
return(0);
}
clptr[xcol] = EOL;
sputl(curln,column,curln); /* fix this line */
move(curln,column+1);
return(1);
}
/* tabc -- tab command */
/* inserts a tab unless notabs mode is on, in which case */
/* it inserts spaces up to next tabstop. */
tabc(count,arg)
register int count;
int arg;
/* Keywords: commands insertion */
{
if (infrn >= 0) { /* no dice in macro */
if (NOTABS) {
while (count--) {
do {
put(' ');
} while (column%TABSTOP);
}
} else {
insertc(count,arg);
}
}
return(1);
}
/* mvc -- move with checking for c<=length(l) */
mvc(l,c)
register int l;
register int c;
/* Keywords: commands:40 movement */
{
register int x;
if ((x = leng(l)) < c) move(l,x);
else move (l,c);
}
/* move to new position in the file */
move (newln,newcol)
register int newln;
register int newcol;
{
/* Keywords: movement buffer-allocation:20 */
if (newln < 1) newln = 1;
if (newln >= NPTRS) {
if (!growbuf(newln)) {
newln = NPTRS-1;
}
}
curln = newln;
clptr = mkline(curln);
column = newcol;
return;
}
/* move both the display matrix pointer and the actual display to the
* specified line and column */
mgo(x,y)
register int x,y;
{
sgo(mline = x,mcol = y);
}
/* move the display cursor to the specified destination. sgo attempts
* to optimize the movement, using single character or absolute
* positioning */
#ifdef PC
sgo(x,y)
register int x,y;
{
video(REG(POS_CUR,0),REG(PAGE_0,0),0,REG(x,y));
}
#else
sgo(x,y)
/* Keywords: screen-handling the-screen-cursor */
register int x,y;
{
int mx,my;
int xcost; /* cost with all relative movement */
int ycost; /* cost with carriage return */
/* acost is cost of absolute positioning */
/* calculate relative costs of various movements. cost functions */
/* automatically indicate that un-doable motions have infinite cost */
if (umode) unline(); /* out of "underline mode" */
/* calculate xcost and ycost */
mx = x-scrlin;
if (mx<0) {
mx = -mx;
xcost = mx*lUP;
} else xcost = mx*lDOWN;
ycost = y + xcost + lCR;
my = y-scrcol;
if (my<0) {
my = -my;
xcost +=my*lBAK;
} else xcost += my;
if (xcost == 0) return; /* Catch spurious calls to sgo */
if (acost < ycost) {
if (acost < xcost) {
/* do absolute positioning */
if (CURAD) {
absmove(x,y);
} else { /* have relative addrs */
if (x>scrlin) eprintf (RELDOWN,mx);
if (x<scrlin) eprintf (RELUP,mx);
if (y>scrcol) eprintf (RELFORW,my);
if (y<scrcol) eprintf (RELBACK,my);
}
scrlin=x;
scrcol=y;
return;
} /* else relative is cheap, do it */
} else {
if (osert && (MI == 0)) {
unsert(); /* LEAVE insert character mode */
}
if (ycost < xcost) {
/* do carriage return processing */
PUTS(CR); /* carriage return */
scrcol = 0;
/* fall through to finish with relative motion */
}
}
while (x != scrlin) {
if (x < scrlin) {
PUTS(UP);
scrlin--;
} else {
PUTS(DOWN);
scrlin++;
}
}
/* now correct row */
while (y != scrcol) {
if (y < scrcol) {
PUTS(BACK);
scrcol--;
} else {
if ((FORWARD == NULL)|| (FORWARD[1] && (osert==0))) {
if (osert) {
unsert();
}
x = cmap[scrlin] [scrcol];
if (x == 0) x=cmap[scrlin] [scrcol] = ' ';
if (x & 0200) pu(x); /* underlined character */
else {
if (umode) unline();
putchar(x); /* re-write to move; */
}
} else {
PUTS(FORWARD);
}
scrcol++;
}
};
return;
}
/* unsert -- LEAVE insert character mode */
unsert()
{
/* Keywords: screen-handling terminal-parameters insertion character-at-a-time */
PUTS(OSERTC); /* can't stay inserting */
osert = 0;
}
unline()
{
/* Keywords: screen-handling terminal-parameters underlining */
PUTS(UEND);
umode = 0;
}
/* vshift -- shift the display image from top to bottom (inclusive) by x */
vshift(top,bottom,x)
/* Keywords: scrolling the-screen-map terminal-parameters:20 display-update:80 */
int top;
int bottom;
int x;
{
register int i;
register int j;
char *cp1;
char *cp2;
int *jnkptr;
int *mapptr;
int start;
int stop;
register int off;
if (x > 0) {
off = 1;
start = top;
stop = bottom+1;
} else {
off = -1;
start = bottom;
stop = top-1;
}
for (i = start,mapptr = scrmap+i,jnkptr = scrjnk+i; i != stop-x; i+=off,mapptr+=off,jnkptr+=off) {
*jnkptr = *(jnkptr+x);
*mapptr = *(mapptr+x);
cp1 = cmap[i];
cp2 = cmap[i+x];
for (j = 0; j < *jnkptr; j++) {
*cp1++ = *cp2++;
}
}
while (i != stop) {
if (off > 0) {
*mapptr++ = *jnkptr++ = 0;
i++;
} else {
*mapptr-- = *jnkptr-- = 0;
i--;
}
}
}
/* adjust vertical position of line -- open (or close) lines on */
/* the screen argument is the number of lines to add (or drop). */
vadjust(x,xline)
register int x;
int xline;
/* Keywords: display-update:90 deletion:50 insertion:50 terminal-parameters:90 the-screen-map scrolling:20 screen-lines screen-handling */
{
register int i;
register int j;
int oldx;
oldx = xline;
TRACE(VADJUST);
TRACE(curln);
TRACE(x);
if (x<0) {
x = -x;
i = 1;
} else i = 0;
if (((j = lastln-xline-x) <= 0)||
((x*VCOST)>(j*ttywarp*CFILL))) return; /* nothing to save */
SREGION=SCRLINES-oldx; /* effected region */
if (i) { /* if deleting lines */
sgo(xline,0);
if (SCREG && CURAD) { /*if vt100 stype scrolling */
PUTS(TPARM(SCREG,oldx+XBASE,SCRLINES+XBASE-1)); /*define region*/
absmove(0,0);
sgo(SCRLINES-1,0);
do_n(CLSCROLL,SSCROLL,x); /* Scroll up x lines */
PUTS(TPARM(SCREG,XBASE,REALBOT+XBASE-1));
absmove(oldx,0);
} else {
do_n(CLDEL,LDEL,x);
sgo(SCRLINES-x,0);
do_n(CLOPEN,LOPEN,x);
}
sgo(oldx,0);
vshift (oldx,SCRLINES-1,x);
} else {
if (SCREG && CURAD && RSCROLL) { /* if vt100 style scrolling */
PUTS(TPARM(SCREG,oldx+XBASE,SCRLINES+XBASE-1)); /*define region */
absmove(xline,0);
do_n(CRSCROLL,RSCROLL,x);
PUTS(TPARM(SCREG,XBASE,REALBOT+XBASE-1));
absmove(oldx,0);
} else {
sgo(SCRLINES-x,0);
do_n(CLDEL,LDEL,x);
sgo(oldx,0);
do_n(CLOPEN,LOPEN,x);
}
mgo(oldx,0);
vshift(oldx,SCRLINES-1,-x);
}
SREGION=1;
}
do_n(mulcap,sincap,n)
char *mulcap;
register char *sincap;
register int n;
/* Keywords: scrolling:20 screen-lines:40 terminal-parameters argument-processing screen-handling */
{
if (mulcap && (n>1)) {
/* If we can do all at once */
#ifdef TERMINFO
putpad(tparm(mulcap,n));
#else
PUTS(mulcap,n);
#endif
} else {
while (n--) PUTS(sincap);
}
}
absmove(x, y)
int x;
int y;
{
/* Keywords: terminal-parameters the-screen-cursor screen-handling */
#ifdef TERMINFO
putpad(tparm(CURAD, x, y));
#else
#ifdef TERMCAP
putpad(tgoto(CURAD, y, x));
#else
if (SRCADD) {
eprintf(CURAD,x+XBASE,y+YBASE);
} else {
eprintf(CURAD,y+YBASE,x+XBASE);
}
#endif
#endif
scrlin=x;
scrcol=y;
}
/* sscroll -- try to fix display by scrolling */
sscroll(x)
register int x;
/* Keywords: terminal-parameters scrolling screen-handling */
{
register int i;
if (SSCROLL == NULL || twowind || (SCRLINES-x < 3) || (curbf != disbuf[cwind])) return;
sgo(REALBOT-1,0); /* to bottom */
SREGION=REALBOT; /* number of lines effected */
do_n(CLSCROLL,SSCROLL,x);
SREGION=1;
vshift (0,SCRNLIN-1,x);
if (timemd) disptime = 1; /* Wiped out time display */
}
#endif PC
/* delete chars -- delete characters starting at . */
/* all characters must be on the same line */
delc(count)
register int count;
/* Keywords: deletion line-representation killstack:50 stacking:50 commands:20 */
{
register char *cp1;
register char *cp2;
undel();
killstk(curln,column,curln,column+count); /* stack even on 0 */
if (count == 0) {
beep();
return(0); /* nothing to modify */
}
cp1 = clptr+column;
cp2 = cp1+count;
if (NODEL) {
while (cp1<cp2) *cp1++=' ';
} else {
while ((*cp1++ = *cp2++) != EOL);
}
sputl(curln,column,curln);
modify(curln);
move(curln,column);
return(1);
}
/* open up count blank lines in the file */
openl(count)
register int count;
/* Keywords: insertion line-representation memory-allocation:30 text-lines the-screen-map:20 screen-lines:50 */
{
register int i;
register char *lp;
char *lp1;
char *lp2;
int oldcol;
int oldln;
/* first fix the file */
if (nlines+count >= NPTRS) {
if (!growbuf(nlines+count)) {
return;
}
}
if (curln<nlines) {
for (i = fbkno; i < NBLOCK; i++) {
if (hipt[i]>curln) hipt[i]+=count;
if (lowpt[i]>curln) lowpt[i]+=count;
}
for (i = nlines; i > curln; i--) {
ptrs[i+count] = ptrs[i];
}
}
nlines += count;
for (i = curln+1; i <= curln+count; i++) ptrs[i] = 0;
if (clptr[column] != EOL) {
if(ckline(curln+count,leng(curln)-column)!=NULL) {
holdin(curln,curln+count);
lp1 = mkline(curln+count);
lp2 = lp = mkline(curln) + column;
while ((*lp1++ = *lp++)!= EOL);
*lp2 = EOL;
}
}
modify(curln);
modify(curln+count);
/* now fix the display */
oldln = curln;
oldcol = column;
if (TABMD && (RARE == 0)) {
tabjust(curln+count);
}
if (disbuf[cwind] == curbf) {
/* Adjust scrmap to reflect the change. All lines past oldln in the
* current buffer that show on the screen are bumped up by count. The
* current line is bumped only if the whole line moved */
for (i = wbase; i < SCRLINES; i++) {
if ((scrmap[i]) && ((nln = scrmap[i]&SCRMSK) >= oldln)) {
if ((nln != oldln) || (oldcol == 0)) scrmap[i] += count;
}
}
}
sputl(oldln,oldcol,REST);
move(oldln,oldcol);
}
/* getname prompts for a string, using ps, and inputs a string */
/* rubout and @ can be used to edit the string as enterred, and causes
* a quit, returning no input string
* ^Y causes the current buffer name to be brought out
*/
char *
getname(ps)
register char *ps;
/* Keywords: user-interface prompting key-bindings:50 reading:50 filenames:50 commands:20 text-lines:40 the-screen-cursor:30 macro-hooks:10 */
{
register int i;
register char c;
int cnt = 1;
char *xp;
if (infrn < 0) { /* if in macro */
if(retrvs(fnbuf,FNLEN)>=0){
return(fnbuf);
} else return(NULL);
}
if (hooks[Read_Name_Hook]) {
stkstr(ps);
if (hook(Read_Name_Hook) && (retrvs(fnbuf,FNLEN) >= 0)) {
return(fnbuf);
}else return(NULL);
}
fnbuf[i=0] = 0;
for (;;) {
if (infrn == 0 ){
prompt(ECHOL,"%s%s",ps,fnbuf); /* display prompt */
if (c=fnbuf[i]) { /* If there is stuff past the cursor */
/* UGH, To find out where the cursor goes, we must duplicate a lot */
/* of ugly code out of prompt! */
char pbuf[256];
mline = ECHOL;
mcol = 0;
fnbuf[i]=0;
seprintf(pbuf,"%s%s",ps,fnbuf);
fnbuf[i]=c;
xputl(pbuf,0);
}
mgo(mline,mcol);
}
cnt = 1;
getbak: donttime=1; /* Avoid time & mail */
c = getchar();
donttime=0; /* Restore time display */
switch(map_it[c]) {
case CQUOTE:
c = getchar();
goto regchar;
case CCTLU:
cnt*=4;
goto getbak; /* Bypass re-initilizing cnt! */
case CEQUIT:
case CEXIT:
beep();
unprompt();
return(NULL);
case CCTLX:
xp = mkline(curln);
goto wrdin;
case CYANK:
xp = fname();
wrdin: while ((*xp!= 0) && (*xp != EOL)&& (i<FNLEN-1)) {
cram(fnbuf,i++,*xp++);
}
continue;
default:
/* anything that isn't otherwise mapped comes here. Most just insert, */
/* but we do check for '@' */
if (c == '@') {
fnbuf[0]=0;
i = 0;
continue;
}
if (c>=' ') {
regchar: if (i<FNLEN-1) cram(fnbuf,i++,c);
continue;
} else {
if ((c != CTRLJ) && (c != CTRLM)) {
beep;
continue;
}
}
/* Fall through to handle newlines re-mapped by the user */
case CNEWLINE:
case CMETA:
unprompt();
if (infrn == 0) mflush(stdout); /* Indicate that we got it */
return(fnbuf);
case CREFRESH:
clear();
continue;
case CBDEL:
while (cnt--) {
if (i) {
i--;
mstrcpy(fnbuf+i,fnbuf+i+1);
} else beep();
}
continue;
case CFDEL:
while (cnt--) {
if (fnbuf[i]) {
mstrcpy(fnbuf+i,fnbuf+i+1);
} else beep();
}
continue;
case CXPOSE:
if (fnbuf[i] && fnbuf[i+1]) {
c = fnbuf[i];
fnbuf[i]=fnbuf[i+1];
fnbuf[++i] = c;
}
break;
case CFORW:
while (cnt--) {
if (fnbuf[i]) {
i++;
} else beep();
}
continue;
case CBEGIN:
i = 0;
continue;
case CENDL:
i = lng(fnbuf);
continue;
case CBACK:
i-=cnt;
if (i<0) {
beep();
i=0;
}
continue;
case CEKILL:
fnbuf[i]=0;
continue;
}
}
}
/* Cram character into the middle of a filename string */
cram(sp,pos,cchar)
register char *sp;
register int pos,cchar;
/* Keywords: user-interface prompting string-handling:40 */
{
int nc;
while (cchar) {
if (pos == FNLEN-1) {
beep();
break;
}
nc = sp[pos];
sp[pos]=cchar;
pos++;
cchar=nc;
}
sp[pos]=0;
}
/* gechar: get EMACS character: */
/* returns 0200+c for meta chars, 0400+c for ^X chars */
gechar(ps)
register char *ps;
/* Keywords: user-interface character-at-a-time prompting:40 ^-and-M-processing:70 */
{
register int c;
prompt1("%s: ",ps);
c = getchar();
if (map_it[c] == CMETA) {
prompt1("%s: M-",ps);
c = 0200+getchar();
}
if (map_it[c] == CCTLX) {
prompt1("%s: ^X",ps);
c = 0400+getchar();
}
unprompt();
return(c);
}
/* putout outputs a string (like eprintf) at the current position */
/* position is advanced by one line. If the position overflows the screen
* -MORE- is printed, and input is read. Any character except ^G
* continues the display, ^G quits by returning -1 */
/*VARARGS1*/
putout(string,arg1)
char *string;
/* Keywords: prompting:10 informational-displays MORE-processing */
{
if (mline>=SCRLINES) {
prompt1("-- MORE --");
if ((infrn == 0) && ((getchar()) == CTRLG)) return(-1);
unprompt();
mline=0; /* TOP */
}
prompt2(mline,string,&arg1);
clrl();
mgo(++mline,0);
return(0);
}
/* put out a string on ECHOL */
/*VARARGS1*/
prompt1(string,arg1)
char *string;
/* Keywords: prompting */
{
if (infrn) return; /* prompt only if input from stdin */
prompt2(ECHOL,string,&arg1);
if (mcol) sgo(mline,mcol); /* Move cursor only if something is there! */
}
/* Keywords: informational-displays time-processing:50 mail-processing:50 */
prompt3(string,arg1)
char *string;
{
if (infrn) return;
prompt2(ECHOL-1,string,&arg1);
scrmap[ECHOL-1] = ECHOHACK; /* Flag for next unprompt */
}
/* put out a string at a specified line */
/*VARARGS2*/
prompt(ecl,string,arg1)
int ecl;
char *string;
int arg1;
/* Keywords: informational-displays mode-line user-interface:20 */
{
prompt2(ecl,string,&arg1);
}
/* Internal subroutine for all prompting */
prompt2(ecl,string,argl)
char *string;
register int ecl;
unsigned int *argl;
/* Keywords: prompting informational-displays the-screen-map:40 */
{
char pbuf[256];
mline = ecl;
scrmap[mline] = 0; /* wipe out previous display */
mcol = 0;
sxprintf(pbuf,string,argl);
xputl(pbuf,0);
psx = mline;
psy = mcol;
clrl();
}
/* clear out prompt */
unprompt()
/* Keywords: prompting informational-displays the-screen-map:40 deletion:10 */
{
if (infrn) return; /* unprompt only if input from termial */
mline = ECHOL;
mcol = 0;
clrl();
if (scrmap[ECHOL-1] == ECHOHACK) {
mline = ECHOL-1;
clrl();
}
if (timemd) disptime = 1; /* put time back */
}
/* multi-line deleter */
/* deletes the text between current position, and kline, kcol */
/* all deleted text is stacked */
tkill()
/* Keywords: deletion picture-mode:50 killstack:50 stacking:50 the-screen-map:60 */
/* arguments are kline,kcol */
{
int oldcol;
register int x;
register int y;
register char *cp;
char *cp1;
if (kline < 1) kline = 1;
if (kline >nlines) {
kline = nlines;
kcol = leng(kline);
}
if ((kline < curln) || ((kline == curln) && (kcol < column))) {
x = curln;
y = column;
move (kline, kcol);
kcol = y;
kline = x;
}
if (kline == curln) {
return(delc (kcol-column)); /* cheap out */
}
oldcol = column;
undel();
killstk(curln,column,kline,kcol);
if (PICMODE) {
int mincol;
int maxcol;
int ln;
register int c;
ln = curln;
if (kcol<column) {
mincol=kcol;
maxcol=column;
} else {
mincol=column;
maxcol=kcol;
}
while (ln<=kline) {
cp = mkline(ln);
c = 0;
if (NODEL) {
while (c<maxcol) {
if (cp[c]==EOL) break;
if (c>=mincol) cp[c] = ' ';
c++;
}
} else {
int lln;
lln = leng(ln);
if (lln > mincol) {
if (lln < maxcol) {
cp[mincol]=EOL;
} else {
c = mincol;
while (1) {
cp[c]=(*(cp+c+maxcol-mincol));
if (*(cp+(c++))==EOL) break;
}
}
}
}
modify(ln);
ln++;
}
sputl(curln,column,REST);
mvc(curln,column);
return(1);
}
if(ckline(curln,column+leng(kline)-kcol) == NULL) return(0);
holdin(curln,kline);
cp1 = mkline(curln)+column;
cp = mkline(kline)+kcol;
while ((*cp1++ = *cp++)!= EOL) column++;
modify(curln);
/* current line is fixed, fix rest */
x = kline-curln;
/* Adjust block ranges to account for movement in lines. high point
* shifts if its above the deleted region. Low point shifts if it's
* in or above */
if (curln+x<nlines) {
for (y = fbkno; y < NBLOCK; y++) {
if (hipt[y]>curln+x) hipt[y]-=x;
if (lowpt[y]>curln) lowpt[y]-=x;
}
}
for (y = curln+1+x; y <= nlines; y++) {
ptrs[y-x] = ptrs[y];
}
nlines -= x;
if (disbuf[cwind] == curbf) {
/* Adjust scrmap to reflect the change. All lines past oldln in the
* current buffer that show on the screen are bumped up by count. The
* current line is bumped only if the whole line moved */
for (y = wbase; y < SCRLINES; y++) {
if ((scrmap[y]) && ((nln = scrmap[y]&SCRMSK) >= curln)) {
if ((nln == curln) && oldcol) continue; /* dont wipe out curln */
if (nln >= (curln+x)) scrmap[y]-=x; /* map down for lines past the deletion */
else scrmap[y] = 0; /* this line has been killed */
}
}
}
sputl(curln,oldcol,REST);
move(curln,oldcol);
return(1);
}
/* refresh the screen */
/* clear and force refresh */
refresh(arg)
register unsigned arg;
/* Keywords: display-update commands the-screen-cursor:40 windows:20 */
{
if (numarg) dspage(curln-arg,0);
else clear();
}
/* mark a region of the displayy for fixing. Arguments are the */
/* first line and (file) character position to fix, and the last line */
sputl(from, col, to)
int col;
register int from;
int to;
{
/* Keywords: screen-handling:60 commands:30 display-update:30 deletion:50 insertion:50 */
register int *fmp;
int wwid;
if (disbuf[cwind] != curbf) return; /* not in this window */
from -= minln;
wwid = SCRLINES-wbase;
fmp = fmap;
to -= minln;
if (to > wwid) to = wwid;
if ((from >= 0) && (from <= wwid)) {
if (fmp[from] > col) fmp[from]= col;
}
while (++from<=to) if (from >= 0) fmp[from]=0;
return;
}
/* Display output routines. This is probably less clean than the
* previous version, but handles underlining and also does a better
* job with insert/delete character. */
/* The functions are:
cflush(buf,n) -- put n-mcol characters starting at buf+mcol on the
screen at current mline,mcol. This is
assumed not to overflow one line.
xputl(line,flag,col) -- The hard work. Maps a string to one
or more screen lines. The exact nature of
the mapping is different for buffer lines
than for strings, as indicated by flag.
*/
/* Cflush is the main vehicle for the escape of characters. All
* charcters that actaually print (as opposed to terminal
* control) go through here. The general strategy is that if the
* desired character is by some odd chance there already, nothing
* happens. If the desired character is a space and the terminal is
* beyond the end of the line, nothing happens. If insert or delete
* characters will help bring cp into line with what's on the
* screen, then it will use them as necessary. Underlining is
* handled, including the pain of making it work on various
* brain-damaged terminals. */
/* These general principals followed in a way that is optimized for
* common cases, including: display of a whole line that is already
* on the screen. Display of a whole line that does not correspond
* to what's on the screen, and display of one new character. */
#ifdef PC
#define EOM 0 /* End of string marker */
#else
#define EOM '\337' /* End of line marker */
#endif PC
cflush(cp,n)
register char *cp;
int n;
/* Keywords: character-at-a-time:40 insertion:30 deletion:30 character-output screen-handling terminal-parameters:20 */
{
register char *mp;
register int x;
register int y;
int z;
int jnk;
int stop;
cp[n] = EOM; /* Mark end of line */
#ifdef PC
mcol += vout(mline,mcol,cp+mcol);
if (scrjnk[mline]< mcol) scrjnk[mline]=mcol;
#else
mp = cmap[mline]; /* character map pointer */
x = jnk = scrjnk[mline];
while (x < n) mp[x++] = BLANK; /* Clear out the spaces we will write */
x = mcol; /* Get mcol into a register */
stop = 0;
while (1) {
while (mp[x]== cp[x]) x++; /* skip rapidly over same stuff */
if ((mp[x] == 0) && (cp[x] == ' ')) {
x++;
continue;
}
if ((cp[x] == EOM)) {
mcol = x;
if (x < jnk) x = jnk;
scrjnk[mline] = x;
if ((scrcol > REALWID) && SCRWRAP) {
scrlin++;
scrcol=0;
}
return;
}
/* Character was not there, we must do some work here! */
nmput++; /* count for stats */
if ((x != scrcol) || (mline != scrlin)) sgo(mline,x);
/* First, see if we have enough left to worry about insert/delete */
if (jnk-x >= lDELC) {
if (stop == 0) {
/* Find the last matching position */
stop = n-1;
if (stop >= jnk) stop = jnk;
while ((mp[stop] == 0) && (cp[stop] == ' ')) stop--;
while (mp[stop] == cp[stop]) stop--;
stop++;
}
/* Try to use DELC. Must have at least lDELC characters match within
* DLOOK characters of the current position. */
/* Note: If there are ANY nulls in the characters to be deleted, we */
/* Can't use DELC, since the concept-style terminals won't delete*/
if (DELC&& mp[x]) {
y = 1;
while (y < DLOOK && mp[x+y]) {
if (mp[x+y] == cp[x] ) {
z = dccost * y;
if (y+z+x >stop) goto NoDEL;
if (strncmp(cp+x,mp+x+y,z)) goto NoDEL;
/* Should be next_del, but this is faster */
/* Delete y characters from under the cursor */
SREGION=SCRWID-x; /* number of char's gobbled */
if ((DELMODE==1) && (osert == 0)) {
PUTS(INSERTM); /* enter "delete mode, UGH!!!" */
osert = 1;
}
if ((DELMODE==2) && osert) {
unsert(); /* Must not be in insert mode */
}
if (x > jnk) jnk = x;
while (y--) {
PUTS(DELC); /*clobber next char */
jnk = lshift(scrlin,x,jnk-1);
}
stop = 0; /* Don't know where to stop any more */
SREGION=1;
x += z; /* This many matched */
goto donec; /* Process next character */
}
next_del: y++;
}
}
/* Now see if insertion will help. It will be used if lINSC
* characters can be matched within ILOOK characters of the cursor. */
NoDEL:
if ((INSERTC || INSERTM) && (stop > x+lINSC) && ((cp[x] & 0200) == 0)) {
y = 1;
while ((y<ILOOK) && (x+y < stop) && ((cp[x+y]&0200) == 0)) {
if (cp[x+y] == mp[x]) {
/* Found a match, now figure out how much we should have to see before inserting */
if (INSERTC) z = y * iccost;
/* If inserting is per-character, then each one costs iccost */
/* Otherwise, it costs iccost to go into and out of icmode */
else {
if (osert) z = 0;
else z = iccost;
}
/* After a successful insert, we will need cursor motion, so add that too. */
z += acost;
if ((x+y+z)>stop) goto NOINS;
if (strncmp(cp+x+y,mp+x,z)) goto NOINS;
/* Now insert y characters at point, taking from cp and putting out to
* screen. Note that underscores and overstrikes are rejected
* above, so that nothing here will overstrike. We just blast out
* the characters. */
if (x > jnk) jnk = x;
SREGION=jnk-x; /* number of char's moved */
if (umode) unline();
if ((osert == 0) && INSERTM) {
PUTS(INSERTM); /* insert mode */
osert++;
}
while (y--) {
if (INSERTC) PUTS(INSERTC); /* insert prepare */
putchar(cp[x]);
if (INSERTP) PUTS(INSERTP); /* insert pad */
jnk = rshift(scrlin,scrcol+1,mp[scrcol]);
mp[scrcol++] = cp[x++];
}
x+= z;
SREGION=1;
stop = 0; /* Stop is no good any more */
goto donec; /* process next character */
}
next_ins: y++;
}
}
}
NOINS: if (osert) {
unsert();
}
/* Underscore processing. relevant variables are EOVER and ULINE.
* EOVER should be one if writing over an underlined position clears
* it, otherwise, make it zero, and we will clear the line to get
* rid of unwanted underscores. ULINE is a string parameter that
* contains whatever is needed to print the character with an
* underline. If the terminal underscores naturally, then ULINE is
* %c<BS>_. If the terminal has an underscore character mode,
* then ULINE is underscore mode on, %c, underscore mode off. If
* the terminal has an underscore single character command, then
* ULINE is underscore character %c. This is inefficient in
* underscoring giant blocks of text, but this should be rare */
if (cp[x]&0200){
pu(cp[x]); /* underlined character */
} else {
if (umode) unline();
if ((mp[x]&0200)&& (!EOVER)) { /* If re-writing won't erase */
PUTS(CLINE); /* wipe line */
while (jnk > scrcol) mp[--jnk] = BLANK; /* Wipeout array */
}
putchar(cp[x]);
}
mp[scrcol++] = cp[x++];
donec: continue;
}
}
/* print an underscored character. */
pu(c)
register char c;
{
/* Keywords: screen-handling:20 underlining character-output:40 */
register int oc;
if (osert) unsert();
c &= 0177;
if ((c == 0)|| (c == 040)) {
/* bare underscore */
oc = cmap[mline][mcol]&0137; /* Map space to null */
if (EOVER && (UEND || (oc == 0))) {
if (umode) unline();
putchar ('_');
return; /* just put out the underscore */
}
c = ' '; /* make sure that we blank over whats there */
}
if (UEND == 0) {
eprintf(ULINE,c);
} else {
if (umode == 0) eprintf(ULINE); /* enter "underscore mode" */
putchar(c);
umode = 1;
}
}
/* lshift -- left shift the screen to account for delete character */
lshift (line,col,limit)
int line;
register int col;
register int limit;
/* Keywords: character-output the-screen-map deletion */
{
register char *lp;
int x;
lp = cmap[line];
while (col < limit) {
if ((lp[col]=lp[col+1]) == 0) break;
col++;
}
lp[col] = 0;
if (IN && (col == SCRWID)) {
x = lp[col] = cmap[++line] [0];
limit++;
if (x) scrjnk[line] = lshift(line,0,scrjnk[line]-1);
}
return(limit);
}
/* rshift -- right shift the screen to account for insert character */
rshift (line,col,x)
int line; /* effected line */
int col; /* column to start in */
register int x; /* displaced character that goes in col */
{
/* Keywords: character-output the-screen-map insertion */
int y;
int jnk;
register char *stop;
register char *lp;
lp = cmap[line];
jnk = scrjnk[line];
if (jnk <=SCRWID) lp[jnk] = 0;
stop = lp+SCRWID;
lp += col;
while (x && (lp<= stop)) {
y = *lp;
*lp++ = x;
x = y;
}
if (IN) {
y = lp - cmap[line];
if (y > jnk) jnk = y;
if (x) rshift(line+1,0,x);
} else {
if (jnk < SCRWID) jnk++;
}
scrjnk[line] = jnk;
return(jnk);
#endif
}
/* put a "logical line" of characters on the screen at the current position */
/* NOTE: This is not very clean, but seems necessary to handle all of the
* various strange possibilities for displaying characters. We must
* process a line at a time in order to handle things like
* underscoring, by which multiple characters map to a single
* display position. The general principals here are: that there
* two ways of calling it, one with a C string to be printed, and
* one with a buffer string to be printed. C strings end in nulls,
* and cause a special character to be mapped to embedded newlines.
* Buffer strings end in newlines, and map normally. Underscoring
* is inidicated by the presence of the meta (0200) bit on
* characters in the display map, so that mapping is done here. To
* do this, a whole line is buffered for cput. Underscoring will
* work fine so long as the underscores are done one at a time, or
* the underscores don't wrap lines. Control and meta characters
* map to their special emacs equivalents.
*/
xputl(cp,flg,col)
register char *cp; /* string pointer */
int flg; /* disposition flag */
int col;
/* Keywords: character-output the-screen-map:20 screen-handling conversions:50 underlining:20 the-screen-cursor:10 ^-and-M-processing:40 */
{
char cbuf[256]; /* line buffer */
register int i;
register int b;
int mb;
int a;
mb = b = mcol; /* buffer pointer */
while (1) {
if (b > mb) mb = b;
if (b > SCRWID) {
/* Line has wrapped. Put a ! on the end, and wrap anything that is left
* over to the next line */
i = cbuf[SCRWID];
a = cbuf[SCRWID+1];
/* i is the character overwritten by the !, a is the character */
/* overwritten by the EOM in cflush */
if (mline>=SCRNLIN-1) {
/* Wrap from last line on screen, fold back up and don't write in
* the last position! */
cflush(cbuf,SCRWID);
mline--; /* don't run overboard */
} else {
cbuf[SCRWID]='!';
cflush(cbuf,SCRWID+1);
if (flg && PICMODE) {
if (col>0) hrem = 1+column-col;
return;
}
mline++;
scrmap[mline] = scrow+SCRCNL; /* mark continuation */
}
mcol = 0;
b = 0;
while(b < LNOMOD*LNOWID) cbuf[b++] = ' ';
cbuf[b++] = i;
i = SCRWID+2;
if (SCRWID+1<mb) cbuf[b++] = a;
while (i < mb) {
cbuf[b++] = cbuf[i++];
}
mb = b; /* RESET */
}
/* Process Next character */
i = (*cp++)&0377; /* next char */
if (flg) { /* if buffer invocation */
if (col++ == column) {
nln = mline;
ncol = b;
}
if (i == EOL) {
cflush(cbuf,mb);
return; /* done */
}
} else {
if (i == 0) {
cflush(cbuf,mb);
return; /* done */
}
if (i == NEWLINE) { /* embedded newline */
cflush(cbuf,b);
clrl();
mb = b = 0;
if (mline < SCRNLIN) mline++; /* don't overflow */
scrmap[mline] = 0;
mcol = 0;
continue; /* re-loop */
}
}
if ((i & META)&& (bit8== 0)) {
cbuf[b++] ='M';
cbuf[b++] = '-';
if (b>mb) mb=b;
i-= META;
}
reswitch: switch(ctype[i&0177]) {
case UL:
if (ULINE) i = 0200; /* terminal underlines */
/* else just a plain old character */
case PLAIN:
if ((b < mb) && ((i & 0200) || (cbuf[b] & 0200))){
i |= cbuf[b]; /* overstrike */
}
cbuf[b++] = i;
break;
case BACKSP:
if (b>mcol) b--;
break;
/*Fall through to handle backspace in normal mode */
case CONTRL:
cbuf[b++] = '^';
i = i^0100;
goto reswitch; /* Handle things like ^_ correctly! */
case TAB:
i = TABSTOP-((b-(LNOMOD*LNOWID))%TABSTOP);
while (i--) {
cbuf[b++] = ' ';
}
break;
}
}
}
/* cput -- put a character in the file, like xputl */
cput(c)
register int c;
/* Keywords: insertion help-messages ^-and-M-processing */
{
c &= 0377;
if (c & META) {
put('M');
put('-');
c-= META;
}
switch(ctype[c]) {
case UL:
case PLAIN:
put(c);
break;
default:
put('^');
put(c^0100);
break;
}
}
/* clear the rest of the line, checking to see if the line previously
* displayed corresponds to the one displayed here now */
clrl()
/* Keywords: prompting:10 display-format:20 informational-displays:30 screen-lines clearing */
{
register int x;
register int y;
register int z;
char *xln;
int xcol;
#ifdef PC
char buf[130];
#endif
x = mline;
z = mcol;
y = scrjnk[mline] - mcol;
if (y > 0) {
#ifdef PC
buf[y]=0;
for (x = 0; x < y; x++) buf[x] = ' ';
x = mline;
vout(mline,mcol,buf);
#else
sgo(mline,mcol); /* go for real */
if (CLINE) {
PUTS(CLINE);
} else {
xln = cmap[mline];
xcol = mcol;
while (y--) {
if (xln[xcol] && xln[xcol] != ' ') {
sgo(mline,xcol);
putchar(' '); /* wipe line */
if ((scrcol++ >= REALWID) && SCRWRAP) {
scrlin++;
scrcol=0;
}
}
xcol++;
}
}
#endif
scrjnk[x] = z;
}
}
/* findline -- find a line on the screen */
/* findline makes no judgement as to whether or not the line is correct */
/* whether or not the screen is OK up to the line */
findline(line)
register int line;
/* Keywords: the-screen-cursor screen-lines screen-handling the-screen-map:10 */
{
register int i;
if (disbuf[cwind] == curbf) {
for (i = wbase; i < SCRLINES; i++) {
if (scrmap[i] == line) {
nln = i;
return(1);
}
}
}
return(0);
}
/* find the screen address of a file */
/* The result is to set mcol and mline and return 1 if found
* found, otherwise 0 is returned */
findpos(line,col)
register char *line;
register int col;
/* Keywords: the-screen-cursor ^-and-M-processing:50 screen-lines screen-handling the-screen-map:10 picture-mode:10 */
{
register int i;
char c;
mcol = LNOMOD*LNOWID;
i = 0;
while (i < hcol) if (line[i++] == EOL) return(0);
for (i = hcol; i < col; i++) {
if ((c= line[i]) == EOL) return(0);
if (c & META) mcol += metal;
switch(ctype[c&0177]) {
case PLAIN:
case UL:
mcol++;
break;
case BACKSP:
if (mcol) mcol--;
break;
case CONTRL:
mcol+=2;
break;
case TAB:
mcol = mcol+TABSTOP-((mcol-(LNOMOD*LNOWID))%TABSTOP);
break;
}
if (mcol>SCRWID) {
if (PICMODE) {
hrem = col-i;
return(0);
}
if (++mline>SCRLINES) return(0);
mcol = mcol-SCRWID;
if (LNOMOD) mcol+= LNOWID;
}
}
return(1);
}
/* The following function scans the text above "line" to compute
* it's physical size. The scan continues until either hstop physical
* screen lines are found or the line lstop is reached. The line at
* which the scan stopped is returned, and the screen area is left
* in the global "dsize" */
areal(line,hstop,lstop)
/* Keywords: screen-lines display-update:30 screen-handling */
int line;
int hstop;
int lstop;
{
register char *lp;
register int col;
register int c;
dsize = 0;
while ((line > lstop) && (dsize < hstop)) {
--line;
dsize++;
if (PICMODE) continue; /* Picture mode gets one line/line */
lp = mkline(line);
col = LNOMOD*LNOWID;
while ((c = *lp++) != EOL) {
if (c & META) col += metal;
switch(ctype[c&0177]) {
case PLAIN:
case UL:
col++;
break;
case BACKSP:
if (col) col--;
break;
case CONTRL:
col+=2;
break;
case TAB:
col = col+TABSTOP-((col-(LNOMOD*LNOWID))%TABSTOP);
break;
}
if (col>SCRWID) {
dsize++;
col = col-SCRWID;
if (LNOMOD) col+= LNOWID;
}
}
}
return(line);
}
/* print a line number(x) */
lnumb(x)
/* Keywords: line-numbers informational-displays screen-handling */
{
register int i;
char tbuf[8];
for (i=0; i<8; i++) tbuf[i]=0;
seprintf(tbuf,"%d",x);
mcol = 0; /* make sure were at start of line */
for (i=0; i<LNOWID; i++) {
if (tbuf[i] == 0) tbuf[i] = ' ';
}
cflush(tbuf,LNOWID); /* output to terminal */
}
/* putin -- insert string into file */
putin(xp)
register char *xp;
/* Keywords: informational-displays help-messages:50 error-messages:50 screen-handling */
{
register int c;
RARE = 1;
while (c = *xp++) {
if (c == NEWLINE) { /* Note that NEWLINE != '\n' */
nl(1);
put(' ');
}
else put(c);
}
RARE = 0;
}
/* dspage -- re-position display with (line) first. If */
/* the move argument is non-zero, the cursor is moved into the middle */
/* of the new display */
dspage(line,moves)
int line;
int moves;
/* Keywords: commands display-update:30 the-screen-cursor scrolling */
{
if (line<1) {
if (minln > 1) line=1;
else {
beep();
return(0);
}
}
if (line > nlines) {
if (maxln < nlines) line = nlines;
else {
beep();
return(0);
}
}
fclear(); /* just blew up file */
if (disbuf[cwind] != curbf) {
/* NOTE: This is a pain! display is out of date because we were
* called from a macro, If we don't do something here, disup will pick
* a new window when we change buffers. What we do is not very
* good, but it works?
*/
if (junked || ((twowind == 0) && (CLINE == 0))) {
clear(); /* dumb terminal or command */
} else {
xclear(); /* others, just clobber map */
}
disbuf[cwind] = curbf; /* avoid reset in disup */
}
minln = line;
maxln = line+SCRLINES-wbase; /* This is just a guess, but should make it to disup all right. */
if (maxln > nlines) maxln = nlines;
if (moves) move((minln+maxln)/2,0);
return(0);
}
/* nxtpag -- move to next page */
nxtpage(count)
register int count;
/* Keywords: display-update:20 the-screen-cursor:30 movement commands forwards paging */
{
return(dspage((maxln+1+((count-1)*(SCRLINES-wbase)))-keepg,1));
}
/* move to top of page (current line becomes first line) */
toppage()
/* Keywords: display-update:20 the-screen-cursor:30 movement scrolling commands backwards */
{
dspage(curln,0);
}
/* move to previous page */
lstpage(count)
register int count;
/* Keywords: display-update:20 the-screen-cursor:30 movement commands backwards upward-movement:50 paging */
{
return(dspage((minln-count*(SCRLINES-wbase))+keepg,1));
}
clear()
/* Keywords: clearing screen-handling the-screen-map:40 terminal-parameters:20 terminal-initialization:30 */
{
register int i;
#ifdef PC
video(REG(SCRL_UP,0),REG(NORMATB,0),0,REG(SCRNLIN,SCRWID));
#else
PUTS(CLEAR);
#endif
for (i = 0; i < SCRNLIN; i++) scrmap[i] = scrjnk[i] = 0;
scrlin = scrcol = mline = mcol = 0;
disbuf[0]=disbuf[1]= -1;
junked = minln = maxln = 0;
if (timemd) disptime = 1; /* Wiped out time display */
}
/* didle (display idle) update display and idle for the specified time */
didle(count)
int count;
{
/* Keywords: macro-programming display-update:10 time-processing:20 screen-handling */
if (count > 100) count = 100; /* limit to 10 seconds */
pushin(NULL); /* make sure we will update */
disup();
mflush(stdout);
#ifndef PC
while (count--) PUTS (WAIT1);
#endif
inpop();
}
/* disup() update display. disup should be called whenever you want the */
/* to be up to date. disup does not update if there is more input */
/* available from the current input source. */
/* This is the high level display algorithm, which translates the
* buffer into a screen image. The pparameters affecting the algorithm are
*
* scrmap[SCRNLIN] map from the display line to the file line on
* that line of the display.
* fmap[SCRNLIN] map from the file indicating what the smallest
* column in the file containing undisplayed changes
* is. A special value (LGOOD) indicates that
* the whole line is good. This avoids looking at
* the lines in the file that are known to be ok.
* minln The file line appearing at the top of the current
* window.
* maxln The last file line appearing in this window.
* lastln The screen line on which maxln is displayed.
* curbf[2] The buffer displayed in each window.
* dahead Flag indicating that we are displaying the line
* with the cursor ahead of schedule.
*
* The basic algorithm is to firsst check to see if the window is properly
* positioned to hold the cursor. If not, a new window is chosen and minln
* reset. Then, each line that should be displayed is examined for
* changes. Any lines needing updating are redisplay. A side effect of
* the scan is to find the screen address of the current line. If the
* screen address is found, the mode line and window splitting line are
* updated (if necessary), and any other lines are blanked. If the cursor
* wasn't found, it tries once again to display starting with the current
* line. This can happen only if the line before the current line or the
* current line is gigantic, wrapping lots of times around the screen.
* Repeated failures signal a fatal error and indicate a bug or an
* enormous current line.
*/
/* status display */
char mdchar[2] = {'=', '>'};
disup() /* force update display */
{
/* Keywords: clearing:5 screen-handling display-update scrolling:10 insertion:10 deletion:10 */
/* Keywords: lookahead:20 the-screen-cursor:20 the-screen-map:20 screen-lines:10 mode-line:20 macro-hooks:10 */
register int col;
int fixed;
register char *cp;
long pm;
int *fmp;
int dahead;
char pmbuf[10];
char hcbuf[10];
char smap[NSCRLIN];
int smapped;
if (MOREIN) return;
fixed = smapped = 0 ;
dahead = 0;
nln = ncol = hrem = -1;
/* Check to see if what is on the screen is from the same buffer. If
* not, don't try to re-use it
*/
if (disbuf[cwind] != curbf) {
minln = 0; /* force repositioning */
if (CLINE || twowind) {
xclear(); /* force redisplay */
} else {
clear(); /* try to optimize dumb terminal */
}
disbuf[cwind] = curbf; /* mark buffer up to date */
}
/* See if the current line is on the screen. The check is not absolutely
* perfect. If the current line is not on the screen, a new position
* is picked. Mis-guessing will be caught eventually.
*/
if ((minln == 0) ||(curln <minln) || ((curln> maxln) && (curln-maxln+lastln>=SCRLINES))) {
/* display position is bad */
if (junked) {
clear();
disbuf[cwind] = curbf; /* mark buffer up to date */
}
badpos:
if (hrem>0) {
hcol = hcol+4+(hrem-hrem%4);
hrem = -1;
fclear();
goto retry;
}
if(fixed++) {
if (fixed > 2) error(FATAL,42); /* can't find cursor */
minln = curln;
} else {
minln = areal(curln,(SCRLINES-wbase)/2,1);
}
fclear(); /* file bad */
if (SCREG || LOPEN) {
if ((minln > 1) && (minln < curln)) dahead = wbase+dsize;
}
maxln = curln;
}
if (column<hcol) {
hcol = column-column%4;
dispmod();
fclear();
}
/* Now for the real work, check all of the lines. A line can be bad if
* scrmap indicates that its not in the right place on the display
* or if fmap indicates that it may have changed since being put up.
*/
retry: fmp = &fmap[-minln];
mcol = 0;
for (scrow = minln, mline = wbase; (scrow <= nlines) && (mline < SCRLINES);scrow++) {
if (scrmap[mline] != scrow) {
/* line is bad, first try to bring it into position by scrolling or by
* inserting/deleting lines. This could result in the display being
* corrected.
*/
#ifndef PC
if ((smapped == 0) && (LOPEN || (SSCROLL && (mline == 0)))) {
/* There is some hope for scrolling, build the display map. */
/* We scan remaining screen lines for ones that may be of use. */
/* smap[line-minln] = screen line (if any) */
/* scrmap[line] = 0 if known to be useless */
register int x;
for (x = 0; x < SCRLINES; x++) smap[x] = 0;
smapped = scrow+SCRLINES-mline-1;
for (x = mline+1; x < SCRLINES; x++) {
col = scrmap[x];
if ((col & SCRCNL) == 0) {
if ((col<scrow) || (col > smapped)) {
scrmap[x] = 0; /* Useless */
} else {
smap[col-minln] = x;
}
}
}
}
/* try to scroll the screen up with newlines */
if ((mline == 0) && SSCROLL && (col=smap[scrow-minln])) {
sscroll(col);
smapped = 0;
} else if(LOPEN) {
/* try to adjust screen by
* opening and closing lines */
if (col=smap[scrow-minln]) {
vadjust(mline-col,mline);
smapped = 0;
} else if (((col=scrmap[mline]&SCRMSK)>scrow) && (col <= nlines)) {
smapped = areal(col,SCRLINES-mline,scrow);
vadjust(dsize,mline);
smapped = 0;
}
}
#endif
goto fixline;
}
if (fmp[scrow] < LGOOD) {
fixline:
/* Check for display-ahead. If we are on the first line, jump ahead
* to the current line and show it first, being careful to return
* when appropriate */
if (dahead>0) {
/* Pick line for display ahead. Note that in some cases, the
* current line is on the screen, in which case we just use it. If
* not, we try the middle of the screen. If this is marked as
* belonging to some other line, we just ignore dahead. */
if (findline(curln)) mline = nln;
else {
if (scrmap[dahead]) {
dahead = 0;
goto disline;
}
if ((scrmap[dahead-1]&SCRMSK) != curln-1) {
mgo(dahead-1,0);
scrmap[mline]=0;
clrl();
}
if ((scrmap[dahead+1]&SCRMSK) != curln+1) {
mgo(dahead+1,0);
scrmap[mline]=0;
clrl();
}
mline = dahead;
}
dahead = -1;
scrow = curln;
}
disline:
/* Now fix the display of this line. fmap indicates where we start */
cp = mkline(scrow);
if ((scrmap[mline] == scrow) && (col =fmp[scrow])) {
if (col == LGOOD) goto skipit;
if ((scrow == curln) && (col > column)) {
col = column;
}
/* Note that if we have backspace mode on, then we can't start the
* line in the middle, because the line may have backspaces that
* span the cursor, or have had them in its previous form. The only
* safe thing to do is re-format the whole thing and let cflush
* throw most of it away. */
if ((col == 0) || BACKP) goto numbline;
if (col<hcol) col=hcol;
if (findpos(cp,col)==0) goto badpos;
cp +=col;
} else {
scrmap[mline] = scrow; /* mark line */
numbline: if(LNOMOD) lnumb(scrow);
col = 0;
while (col < hcol) {
if (*cp==EOL) break;
cp++;
col++;
}
}
xputl(cp,1,((curln==scrow)?col:-1000)); /* process line */
clrl();
mline++;
mcol = 0;
fmp[scrow] = LGOOD;
/* if we have NDELAY I/O available, see if there is any type ahead */
if (((int) _stdout._cnt *ttywarp) > PATIENCE) {
ttfill(); /* try to fill tty buffer */
if (MOREIN) {
clptr = mkline(curln);
if (maxln < scrow) maxln = scrow;
return;
}
}
} else {
/* line on the screen is OK, see if the current cursor position is in it */
skipit: if (scrow == curln) {
cp = mkline(curln);
if (findpos(cp,column)) {
nln = mline;
ncol = mcol;
} else {
goto badpos;
}
}
mline++;
while ((scrmap[mline]) == (scrow|SCRCNL)) mline++;
mcol = 0;
}
if (dahead<0) {
dahead = 0;
nln = -1; /* Make sure we find this line later */
mline = wbase;
scrow = minln;
goto disline; /* If displaying ahead, return to finish display */
}
/* done re-creating the display, now clean up the rest of the lines */
}
maxln = scrow-1; /* last line on the screen */
wminln[cwind] = minln;
wmaxln[cwind] = maxln;
lastln = mline-1; /* last display line used */
if (twowind && (mline == SCRLINES) && (cwind == 0)) {
prompt(mline,endput);
scrmap[mline]=0;
}
if ((scrow > nlines) || (mline == SCRLINES)) {
while (mline < SCRLINES+1) {
if ((twowind == 0) || (mline < SCRLINES) || cwind) {
if (scrjnk[mline])clrl();
scrmap[mline++]=0;
} else mline++;
}
}
if (nln < 0) {
goto badpos; /* oops, blew it agaiin */
}
if ((scrmap[MODLN] != MODHACK)||PMODE) {
/* Pre-format sections for display-percent mode and horizontal scrolling */
if (hcol) {
seprintf(hcbuf,"<%d ",hcol);
} else hcbuf[0] = 0;
if (PMODE) {
pm = (nlines == 1)?1:nlines-1;
pm = (100L*((long) curln-1))/pm;
seprintf (pmbuf," %D%%",pm);
} else pmbuf[0] = 0;
if (hooks[Mode_Line_Hook]) {
hook(Mode_Line_Hook);
retrvs(fnbuf,FNLEN);
prompt(MODLN,"%s",fnbuf);
} else {
prompt(MODLN,"%s%s %s (%d) %s %c %s%s",hcbuf,myname,version,bfnumb(),bname(),mdchar[modded()], fname(),pmbuf);
}
if (lgripe && (infrn == 0)) {
prompt(ECHOL,"I can only use %d lines by %d columns of your screen",SCRNLIN,SCRWID+1);
lgripe = 0;
}
scrmap[MODLN] = MODHACK;
if (twowind) {
col = w1base-1;
prompt(col,endput);
scrmap[col] = 0; /* SPPML */
}
mgo(nln,ncol); /* Restore cursor */
}
clptr = mkline(curln); /* make sure we get this one */
mgo(nln,ncol);
}
/* Initialize screen size */
setsize()
/* Keywords: modes:50 screen-handling display-format terminal-initialization:10 */
{
/* Set safe defaults for height and width, and set dependent parameters */
if (SCRNLIN<=4) SCRNLIN=5;
if (SCRNLIN>NSCRLIN) {
SCRNLIN=NSCRLIN;
lgripe++;
}
if (SCRWID>NSCRCOL-1) {
lgripe++;
SCRWID=NSCRCOL-1;
}
if (SCRWID > REALWID) {
lgripe++;
SCRWID = REALWID;
}
SCRLINES=SCRNLIN-4;
ECHOL = SCRNLIN-1;
MODLN = SCRNLIN-3;
}
/* display the mode line */
dispmod()
/* Keywords: mode-line */
{
scrmap[MODLN] = 0;
}
ttype() /* set terminal type */
{
/* Keywords: commands terminal-initialization terminal-modes:20 terminal-parameters:50 */
register char *mp;
#ifndef PC
mp = expenv(getname("Terminal Type? "));
if (mp == NULL) return;
sttype(mp);
#endif
}
#if defined(TERMCAP) || defined(TERMINFO)
/* Like putchar but a function which can be passed to putpad */
pchar(c)
{
putchar(c);
}
/*
* Print out string str with padding.
*/
putpad(str)
char *str;
{
if (str) {
tputs(str, SREGION, pchar);
}
}
#endif
#if defined(TERMINFO)
sttype(mp)
register char *mp;
{
#ifndef SINGLE
extern struct term _first_term; /* statically allocated terminal structure */
#endif
char tbuf[1024];
static char bufspace[512];
char *xp;
char *pt = bufspace;
int rc = 1;
cur_term = 0; /* Force setupterm to use default */
if (mp == NULL) mp = dumbterm;
setupterm(mp, 1, &rc);
if (rc != 1) {
if (mp == dumbterm) {
write(1,"\n\r\n\rI Can't understand your terminal type\n\r",43);
quit();
}
cur_term = & _first_term; /* Restore terminal pointer */
IGNORE(error(WARN,86,mp,em_dir));
return;
}
UP = cursor_up;
RELUP = parm_up_cursor;
DOWN = cursor_down;
if (DOWN == NULL)
DOWN = "\n";
RELDOWN = parm_down_cursor;
BACK = cursor_left;
RELBACK = parm_left_cursor;
FORWARD = cursor_right;
RELFORW = parm_right_cursor;
CLEAR = clear_screen;
CLINE = clr_eol;
BELL = bell;
CURAD = cursor_address;
NOP = pad_char;
LOPEN = insert_line;
CLOPEN = parm_insert_line;
LDEL = delete_line;
CLDEL = parm_delete_line;
INSERTC = insert_character;
INSERTM = enter_insert_mode;
OSERTC = exit_insert_mode;
INSERTP = insert_padding;
IN = insert_null_glitch;
/*
DELMODE = enter_delete_mode; /* Note that DM is a flag in emacs * /
*/
DELC = delete_character;
RSCROLL = scroll_reverse;
SSCROLL = scroll_forward;
CLSCROLL= parm_index;
CRSCROLL= parm_rindex;
if ((SSCROLL == NULL) && (!eat_newline_glitch)) SSCROLL = "\n";
SCREG = change_scroll_region;
/* UNDERLINING */
if (transparent_underline) {
ULINE = "%c_"; /* underline this way */
EOVER = erase_overstrike;
}
else if (underline_char) {
/* underscore by magic word */
ULINE = pt;
pt = strcpy(pt,"%c");
pt = strcpy(pt,underline_char);
EOVER = !ceol_standout_glitch;
pt++;
} else if (xp = enter_underline_mode) { /* underscore mode */
ULINE=xp;
UEND= exit_underline_mode;
EOVER = !ceol_standout_glitch;
}
CR = carriage_return;
SCINIT = enter_ca_mode;
VEXIT = exit_ca_mode;
MI = move_insert_mode;
if ((CURAD == NULL) && (CURAD = cursor_mem_address)) SSCROLL=NULL;
/* Use memory addressing and no scrolling if forced */
SCRWID = columns - 1;
SCRNLIN = lines;
SCRWRAP = auto_right_margin;
#ifdef JWINSIZE
/*
* Courtesy of Mark Horton - CDB
*
* ioctls for Blit - you may need to #include <jioctl.h>
* This ioctl defines the window size and overrides what
* it says in the terminal description file.
*/
{
struct jwinsize w;
if (ioctl(1, JWINSIZE, &w) != -1) {
SCRNLIN = w.bytesy;
SCRWID = w.bytesx - 1;
}
}
if (getenv ("LINES"))
IGNORE (nscan (getenv ("LINES"), &SCRNLIN));
if (getenv ("COLUMNS"))
{
IGNORE (nscan (getenv ("COLUMNS"), &SCRWID));
SCRWID--;
}
#endif
REALWID=SCRWID;
REALBOT=SCRNLIN;
setsize();
if (IN) BLANK= 0;
else BLANK= ' ';
if (VCOST == 0) VCOST = 1;
if (CURAD) {
acost = dcost(CURAD);
} else {
acost = dcost(RELUP)+dcost(RELFORW);
}
dccost = dcost(DELC);
if (INSERTM) iccost = dcost(INSERTM)+dcost(OSERTC);
else iccost = dcost (INSERTC);
lUP = dcost(UP);
lDOWN = dcost(DOWN);
lBAK = dcost(BACK);
lCR = dcost(CR);
if ((NOP == NULL) || (*NOP == 0)) NOP = "\200"; /* null pads get lost */
if (ULINE) BACKP = 1; /* Set backspace mode if terminal underscores */
vinit();
TERMIQ = 0; /* Compute terminal's IQ */
if (CURAD) TERMIQ += 1;
if (CLINE) TERMIQ += 2;
if (LOPEN || SCREG) TERMIQ += 4;
if (INSERTC || INSERTM) TERMIQ += 8;
clear();
}
/* for costing out terminfo capabilities */
static int TIcount;
/*ARGSUSED*/
int TIcost(c)
char c;
{
++TIcount;
}
#else
#ifdef TERMCAP
char PC;
char *BC;
char *TE;
sttype(mp)
register char *mp;
{
char tbuf[1024];
static char bufspace[512];
char *xp;
char *pt = bufspace;
char *tgetstr();
if (mp == NULL) mp = dumbterm;
if (tgetent(tbuf, mp) < 1) {
if (mp == dumbterm) {
write(1,"\n\r\n\rI Can't understand your terminal type\n\r",43);
quit();
}
IGNORE(error(WARN,86,mp,em_dir));
return;
}
UP = tgetstr("up", &pt);
DOWN = tgetstr("do", &pt);
if (DOWN == NULL)
DOWN = "\n";
BACK = tgetstr("bc", &pt);
if (BACK == NULL && tgetflag("bs"))
BACK = "\b";
BC = BACK;
FORWARD = tgetstr("nd", &pt);
CLEAR = tgetstr("cl", &pt);
CLINE = tgetstr("ce", &pt);
BELL = "\7";
CURAD = tgetstr("cm", &pt);
NOP = tgetstr("pc", &pt);
if(NOP != NULL) PC = *NOP;
LOPEN = tgetstr("al", &pt);
CLOPEN = tgetstr("AL", &pt);
LDEL = tgetstr("dl", &pt);
CLDEL = tgetstr("DL", &pt);
INSERTC = tgetstr("ic", &pt);
INSERTM = tgetstr("im", &pt);
OSERTC = tgetstr("ei", &pt);
INSERTP = tgetstr("ip", &pt);
IN = tgetflag("in", &pt);
DELMODE = (tgetstr("dm", &pt)==NULL); /* Note that DM is a flag in emacs */
DELC = tgetstr("dc", &pt);
RSCROLL = tgetstr("sr", &pt);
SSCROLL = tgetstr("nl", &pt);
CLSCROLL = tgetstr("SF", &pt);
if (SSCROLL == NULL) SSCROLL = tgetstr("sf",&pt);
if ((SSCROLL == NULL) && (tgetflag("xn")== NULL)) SSCROLL = "\n";
SCREG = tgetstr("cs", &pt);
/* UNDERLINING */
if (tgetflag("ul")) {
ULINE = "%c_"; /* underline this way */
EOVER = tgetflag("eo");
}
else if (xp = tgetstr("uc",&pt)) {
/* underscore by magic word */
ULINE = pt;
pt = mstrcpy(pt,"%c");
pt = mstrcpy(pt,xp);
EOVER = (tgetflag("xs") == 0);
pt++;
} else if (xp = tgetstr("us",&pt)) { /* underscore mode */
ULINE=xp;
UEND= tgetstr("ue",&pt);
EOVER = (tgetflag("xs") == 0);
}
CR = tgetstr("cr", &pt);
if (CR == NULL) {
if (tgetflag("nc") == 0) CR = "\015";
}
SCINIT = tgetstr("ti", &pt);
TE = tgetstr("up", &pt);
MI = tgetflag("mi", &pt);
SCRWID = tgetnum("co") - 1;
SCRNLIN = tgetnum("li");
SCRWRAP = tgetflag("am");
#ifdef JWINSIZE
/*
* Courtesy of Mark Horton - CDB
*
* ioctls for Blit - you may need to #include <jioctl.h>
* This ioctl defines the window size and overrides what
* it says in the terminal description file.
*/
{
struct jwinsize w;
if (ioctl(1, JWINSIZE, &w) != -1) {
SCRNLIN = w.bytesy;
SCRWID = w.bytesx - 1;
}
}
if (getenv ("LINES"))
IGNORE (nscan (getenv ("LINES"), &SCRNLIN));
if (getenv ("COLUMNS"))
{
IGNORE (nscan (getenv ("COLUMNS"), &SCRWID));
SCRWID--;
}
#endif
REALWID=SCRWID;
REALBOT=SCRNLIN;
setsize();
if (VCOST == 0) VCOST = 1;
if (IN) BLANK= 0;
else BLANK= ' ';
if (CURAD) {
acost = dcost(CURAD);
} else {
acost = dcost(RELUP)+dcost(RELFORW);
}
dccost = dcost(DELC);
if (INSERTM) iccost = dcost(INSERTM)+dcost(OSERTC);
else iccost = dcost (INSERTC);
lUP = dcost(UP);
lDOWN = dcost(DOWN);
lBAK = dcost(BACK);
lCR = dcost(CR);
if (SCREG) LOPEN = SCREG; /* make sure we use SCREG */
if ((NOP == NULL) || (*NOP == 0)) NOP = "\200"; /* null pads get lost */
if (ULINE) BACKP = 1; /* Set backspace mode if terminal underscores */
vinit(); /* Initialize screen */
TERMIQ = 0; /* Compute terminal's IQ */
if (CURAD) TERMIQ += 1;
if (CLINE) TERMIQ += 2;
if (LOPEN || SCREG) TERMIQ += 4;
if (INSERTC || INSERTM) TERMIQ += 8;
clear();
}
#else
#ifndef PC
/* terminal description file parser: */
/* terminal description file contains lines with
parameter=data
* where data is either a number of a string */
ttyparse(mp)
char *mp;
/* Keywords: conversions:20 terminal-parameters terminal-initialization reading */
{
register FILE *file;
char xbuf[128];
FILE ttyfile[1];
#define OPTSIZE 256
char optbuf[OPTSIZE];
register char *cp;
register int c;
#ifdef PORTEXT
int parmp;
#else
int *parmp;
#endif
int parm;
/* find the terminal file and open it */
if (mp) {
seprintf(xbuf,"%s/terminals/%s",em_dir,mp); /* terminal file */
file = xopen(ttyfile,xbuf,"r");
if (file == NULL) {
file = xopen(ttyfile,mp,"r"); /* Try full pathname */
}
if (file == NULL) {
badterm: error (WARN,43,mp,em_dir);
return(0);
}
} else {
/* This code restores the terminal to a "sane" default */
file = ttyfile;
ttyfile[0]._frn = open("/dev/null",0);
ttyfile[0]._cnt = lng(nulltty);
ttyfile[0]._ptr = nulltty;
}
/* first find what option we are setting */
nextparm: cp = optbuf;
while ((c = getc(file)) != '=') {
if (c == '\n') goto nextparm; /* comment line */
if (c == EOF) {
mclose(file);
return(1); /* abort during option scan */
}
if (cp-optbuf >= OPTSIZE) goto badterm; /* OOPS! */
*cp++=c;
}
*cp = 0;
/* look up parameter in parameter table */
#ifdef PORTEXT
for (parmp = 0, cp = ttydata; *cp; parmp++,cp+=2) {
#else
for (parmp = ((int * )&UP), cp = ttydata; *cp; parmp++,cp+=2) {
#endif
if ((optbuf[0]==cp[0])&& (optbuf[1]==cp[1])) {
c = getc(file);
if ((c >= '0') && (c <= '9')) {
parm = 0;
while ((c >= '0') && (c <= '9')) {
parm = 10*parm + (c-'0');
c = getc(file);
}
#ifdef PORTEXT
*(parmptr[parmp]) = parm;
#else
*parmp = parm;
#endif
if (c != EOF) goto nextparm;
mclose(file);
return(1);
}
#ifdef PORTEXT
*(parmptr[parmp]) = ((int) &ttystrings[ttyptr]);
#else
*parmp = ((int) &ttystrings[ttyptr]);
#endif
while ((c != EOF) && (c != EOL)) {
if (c == '\\') {
c = getc(file);
if (c == 'n') c = '\n';
}
ttystrings[ttyptr++] = c;
c = getc(file);
}
ttystrings[ttyptr++] = 0;
if (c != EOF) goto nextparm;
}
}
/* error(WARN,68,optbuf); Don't complain about non-existent capabilities */
goto nextparm;
}
#endif
sttype(mp)
register char *mp;
/* Keywords: terminal-parameters terminal-initialization terminal-modes:20 string-handling:20 statistics:10 */
{
#ifdef PORTEXT
int parmp;
#else
int *parmp;
#endif
/* First, initialize the tty data */
ttyptr = 0;
#ifdef PORTEXT
for (parmp = 0; parmptr[parmp]; parmp++) {
*(parmptr[parmp])=0;
}
#else
for (parmp = ( (int *) &UP); parmp <= &DELMODE; parmp++) {
*parmp=0;
}
#endif
#ifdef PC
SCRWID = 79;
SCRNLIN = 24;
ECHOL = 23;
MODLN = 21;
SCRLINES = 20;
CLINE = "";
clear();
#else
if (ttyparse(mp)) {
#ifdef JWINSIZE
/*
* Courtesy of Mark Horton - CDB
*
* ioctls for Blit - you may need to #include <jioctl.h>
* This ioctl defines the window size and overrides what
* it says in the terminal description file.
*/
{
struct jwinsize w;
if (ioctl(1, JWINSIZE, &w) != -1) {
SCRNLIN = w.bytesy;
SCRWID = w.bytesx;
}
}
/*
if (getenv ("LINES"))
IGNORE (nscan (getenv ("LINES"), &SCRNLIN));
if (getenv ("COLUMNS"))
{
IGNORE (nscan (getenv ("COLUMNS"), &SCRWID));
}
*/
#endif
SCRWID--;
REALWID=SCRWID;
REALBOT=SCRNLIN;
setsize();
if (IN) BLANK= 0;
else BLANK= ' ';
if (VCOST == 0) VCOST = 1;
if (CURAD) {
acost = dcost(CURAD);
} else {
acost = dcost(RELUP)+dcost(RELFORW);
}
dccost = dcost(DELC);
if (INSERTM) iccost = dcost(INSERTM)+dcost(OSERTC);
if (INSERTM) iccost = 1;
else iccost = dcost (INSERTC);
lUP = dcost(UP);
lDOWN = dcost(DOWN);
lBAK = dcost(BACK);
lCR = dcost(CR);
if (ULINE) BACKP = 1; /* Set backspace mode if terminal underscores */
if (OSERTC && (INSERTM == 0)) {
INSERTM=INSERTC; /* old style insert modes */
INSERTC=0;
}
if (SCREG) LOPEN = SCREG; /* make sure we use SCREG */
if ((NOP == NULL) || (*NOP == 0)) NOP = "\200"; /* null pads get lost */
vinit();
TERMIQ = 0; /* Compute terminal's IQ */
if (CURAD) TERMIQ += 1;
if (CLINE) TERMIQ += 2;
if (LOPEN || SCREG) TERMIQ += 4;
if (INSERTC || INSERTM) TERMIQ += 8;
clear();
}
#endif
}
#endif
#endif
#ifndef PC
/* dcost -- calculate display cost of a string */
dcost(sp)
register char *sp;
{
/* Keywords: terminal-parameters terminal-initialization */
register int dc;
char dcbuf[512]; /* buffer for string */
if (sp == NULL) return(1000); /* infinite cost for missing capability */
#ifdef TERMINFO
TIcount=0;
tputs(tparm(sp,10,10),10,TIcost);
return(TIcount);
#else
#ifdef TERMCAP
dc = 0;
while (*sp) {
if (*sp++ != '%') dc++;
}
return(dc);
#else
seprintf(dcbuf,sp,10,10); /* expand a 'typical' example */
return(lng(dcbuf)); /* return its length */
#endif
#endif
}
#endif
/* yes or no question */
/*VARARGS1*/
int
gyn(string,arg1)
char *string;
char *arg1;
{
/* Keywords: prompting user-interface yes-no-questions */
register char c;
while (1) {
prompt2(ECHOL,string,&arg1);
sgo(mline,mcol);
if (infrn < 0) {
pushin(NULL);
c = getchar();
inpop();
} else c = getchar();
donttime = 0; /* Re-enable time mode */
switch(c) {
case 'y':
case 'Y':
case ' ':
return(1);
case CTRLZ: /* This is necessary to insure exit */
case 'n':
case 'N':
case RUBOUT:
unprompt();
return(0);
case CTRLG:
unprompt();
return(-1);
default:
donttime = 1; /* Avoid time mode */
prompt3("y for yes, n for no, ^G to quit");
}
}
};
/* beep -- obvious */
beep()
{
/* Keywords: bell-ringing terminal-parameters:20 commands:20 error-messages:10 */
#ifdef PC
if (!NOBEL) video(REG(WR_TTY,BELL),REG(PAGE_0,NORMATB),0,0);
#else
if (!NOBEL) PUTS(BELL); /* print a bell */
#endif
}
/* mtop -- move to top of display for message output */
mtop()
{
/* Keywords: the-screen-cursor informational-displays MORE-processing */
mgo(0,0); /* for messages */
}
/* fclear -- declare the contents of the file invalid */
fclear()
/* Keywords: screen-handling the-screen-map clearing terminal-initialization:20 */
{
register int i;
scrmap[MODLN] = 0; /* wipe out mode line */
for (i = 0; i < NSCRLIN; i++) fmap[i] = 0;
}
/* dclear-- cause screen to be cleared at next refresh */
dclear()
{
/* Keywords: screen-handling clearing break-handling:20 */
junked++;
minln=0;
}
/* xclear -- declare the contents of the screen as junk */
xclear()
{
/* Keywords: screen-handling the-screen-map clearing terminal-initialization:20 */
register int i;
for(i = 0; i < SCRNLIN; i++) scrmap[i]=0;
}
/* two window mode -- enter two window mode, prompt user for buffer */
twind()
{
/* Keywords: windows commands screen-handling:20 */
if (twowind) return;
twowind = 1;
wscrlines = SCRLINES; /* remember real size */
w1base = (wscrlines/2)-woff; /* Compute start of window 2 */
cwind = 0;
owind(); /* enter second window */
cpbuf(1); /* and go to buffer */
}
onewind()
{
/* Keywords: windows commands screen-handling:20 */
if (twowind) {
fclear(); /* file map bad */
twowind = 0;
cwind = 0; /* in window 0 */
wbase = 0;
SCRLINES = wscrlines;
}
}
/* Return buffer in other window or -1 */
windbuf()
/* Keywords: windows commands buffers killing: */
{
if (twind) return(windb[1-cwind]);
else return(-1);
}
owind() /* switch windows */
/* returns -1 if not in two window mode, 0 if different buffer,
and 1 if same buffer */
/* Keywords: windows commands screen-handling:20 */
{
if (!twowind) return(-1);
fclear();
windb[cwind] = curbf;
wminln[cwind] = minln;
wmaxln[cwind] = maxln;
switch(cwind) {
case 0:
cwind = 1;
wbase = w1base;
SCRLINES = wscrlines;
break;
case 1:
cwind = 0;
wbase = 0;
SCRLINES=w1base-1;
break;
}
minln = wminln[cwind];
maxln = wmaxln[cwind];
lastln = SCRLINES-1; /* This is not accurate, but shouldn't matter much */
chbuf(windb[cwind]);
if (windb[0]==windb[1]) return(1);
return(0) ;
}
wgrow(arg)
register int arg;
/* Keywords: windows screen-lines commands insertion:50 screen-handling:20 */
{
fclear(); /* file map bad */
if (twowind) {
if (cwind) w1base -= arg;
else w1base += arg;
if (w1base < 2) w1base = 2;
if (w1base > wscrlines-1) w1base = wscrlines-1;
woff = (wscrlines/2)-w1base;
if (cwind) {
wbase = w1base;
} else {
SCRLINES = w1base-1;
}
} else {
arg += SCRLINES;
if ((arg > 0) && (arg < MODLN)) SCRLINES = arg;
}
}
/* Mousing Specials */
/* Goto screen position at line x, collumn y. arg is decoded as:
* x = arg mod 128.
* y = arg /128.
(128 is more lines than I can imagine on a screen.)
* Will switch windows, but fails if x is an illegal position. */
go_xy(arg)
int arg;
/* Keywords: screen-positioning commands macro-programming:40 */
{
register int x,y,c;
int linpos;
x = arg&127;
y = ((unsigned) arg) >>7;
if ((x <wbase) || (x>= SCRLINES)) {
if (twowind) {
if ((x >= 0) && (x < wscrlines)) {
owind();
} else return(0); /* Can't mouse out of the display */
} else return(0);
}
linpos = scrmap[x]&SCRMSK;
if (linpos== 0) {
if (PICMODE && (maxln == nlines)) {
linpos = maxln+x-lastln;/* If nothing there, punt to end of file */
move(linpos,0);
} else if (x > lastln) {
linpos = maxln;
} else return(0); /* PUNT */
}
if (findline(linpos)) mline = nln;
else mline = x;
column = 0;
mcol = LNOMOD*LNOWID-hcol;
if (y<mcol) y = mcol;
clptr=mkline(linpos);
while ((mline < x) || ((mline == x) && (mcol <= y))) {
c = (clptr[column++]&0377);
if (c == EOL) {
if (PICMODE) {
curln=linpos;
column--;
insertc(y-mcol+1,' ');
}
break;
}
if (c & META) mcol+= metal;
switch(ctype[c& 0177]) {
case PLAIN:
case UL:
mcol++;
break;
case BACKSP:
if (mcol) mcol--;
break;
case CONTRL:
mcol += 2;
break;
case TAB:
mcol+= TABSTOP-((mcol-(LNOMOD*LNOWID))%TABSTOP);
break;
}
if (mcol>SCRWID) {
mline++;
mcol = mcol-SCRWID;
if (LNOMOD) mcol+= LNOWID;
}
}
move(linpos,column-1);
return(1);
}
vinit()
/* Keywords: terminal-parameters terminal-initialization character-output */
{
#ifndef PC
#ifdef COMPRESS
DOCOMP=CMPON;
#endif
#ifdef TERMINFO
if (cur_term == NULL) return; /* Catch if called too soon */
if (enter_ca_mode) {
putpad(enter_ca_mode);
}
if (keypad_xmit) {
putpad(keypad_xmit);
}
#else
if (SCINIT) PUTS(SCINIT);
#endif
#endif
}
vexit ()
{
/* Keywords: terminal-parameters exit-processing character-output */
#ifndef PC
#ifdef COMPRESS
DOCOMP=0;
#endif
#ifdef TERMINFO
if (exit_ca_mode) {
putpad(exit_ca_mode);
}
if (keypad_local) {
putpad(keypad_local);
}
#else
if (VEXIT) PUTS(VEXIT);
#endif
#endif
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.