TVX: PD Editor (2 of 7)
wampler at unmvax.UUCP
wampler at unmvax.UUCP
Tue Jan 14 07:39:04 AEST 1986
#--------CUT---------CUT---------CUT---------CUT--------#
#########################################################
# #
# This is a shell archive file. To extract files: #
# #
# 1) Make a directory (like tvx) for the files. #
# 2) Write a file, such as "filen.shar", containing #
# this archive file into the directory. #
# 3) Type "sh file.shar". Do not use csh. #
# #
#########################################################
#
#
echo Extracting tvx_1.c:
sed 's/^X//' >tvx_1.c <<\SHAR_EOF
X/* ------------------------ tvx_1.c ------------------------------------- */
X/* ========================================================================
X
X TVX - A full screen editor in C
X
X Originally developed by:
X
X Dr. Bruce E. Wampler
X University of New Mexico
X Department of Computer Science
X Farris Engineering Center
X Albuquerque, NM 87131
X
X uucp: ..{ucbvax | gatech | ihnp4!lanl}!unmvax!wampler
X
X Public Domain version released July 1, 1985
X Direct comments, bug reports, suggestions to
X Bruce Wampler at above address.
X
X Converted from Ratfor to C January 1981 (note: since the editor
X was originally in Ratfor, there are certain remnants of the
X original structure left over. There are a lot of things that
X could have been done better if written in C originally.
X Note also that this editor was originally designed in
X 1979 when TECO was state of the art. The influence of
X TECO on this editor will be apparent to anyone who has
X used TECO.
X
X So it goes.
X
X
X PLEASE! If you are making additional modifications, use the
X indentation scheme used here (line up {,}'s!!!) instead
X of the unmaintainable indentation used by K&R!.
X Also, please mark your changes with initials and date!
X
X Description of files required: (names lower case on unix)
X
X TVX_1.C - main part of code (part 1), mostly os/terminal independent
X TVX_2.C - main part of code (part 2), mostly os/terminal independent
X TVX_LEX.C - defaults, some os dependent stuff in here. Major
X changes in defaults can be fixed by recompiling this file.
X TVX_IO.C - almost all I/O, including screen, confined to this file.
X TVX_LIB.C - misc library routines needed by TVX.
X TVX_IBM.C - IBM-PC specific code, specifically the screen driver
X (TVX_IBM.ASM - hand optimized version of TVX_IBM.C)
X TVX_UNIX.C - contains unix specific code, including termcap driver
X TVX_CFG.C - used to build CONFIG.TVX file for -c switch
X TVX_PTCH.C - used to permanently patch tvx with config file
X
X TVX_DEFS.IC - #define's for version, os, terminal, defaults
X TVX_GLBL.IC - global data structures
X TVX_TERM.IC - definitions for various terminals and systems
X
X Most distributions will contain other useful files as well.
X
X============================================================================ */
X
X#include "tvx_defs.ic" /* note tv_defs.ic will #include stdio.h */
X#include "tvx_glbl.ic"
X
X/* =============================>>> MAIN <<<============================= */
X main (argc,argv)
X int argc;
X char *argv[];
X {
X
X checkos(); /* check operating system version */
X force_tty = FALSE; /* won't usually force tty mode */
X
X tvinit();
X ttinit(); /* initialize tt: */
X trmini(); /* init terminal if needed */
X csrcmd(); /* make cursor command cursor */
X
X fopenx(argc,argv); /* open the file, maybe change switches */
X
X tvidefs(); /* set defaults */
X opnbak(); /* may or may not be null routine */
X
X edit(); /* edit the file */
X
X clobak(); /* may be null routine */
X
X file_exit(); /* clean up files */
X
X ttymode = FALSE;
X
X if (*dest_file)
X remark(dest_file); /* echo final file name */
X else
X {
X prompt("R/O, no changes: ") ; remark(orig_file);
X }
X
X reset(); /* reset anything necessary */
X quit();
X }
X
X/* =============================>>> ASK <<<============================= */
X ask(msg,rply,rcnt)
X char *msg,*rply;
X int rcnt;
X { /* get a reply, via tty if necessary */
X int oldtty;
X
X oldtty = ttymode;
X ttymode = FALSE; /* force echo on */
X prompt(msg);
X reply(rply,rcnt);
X ttymode = oldtty; /* back how it was */
X }
X
X/* =============================>>> BEGLIN <<<============================= */
X beglin()
X { /* beglin - move cursor to beginning of current line */
X
X SLOW int xf;
X
X curchr = *(lines+curlin) + 1; /* point to current character */
X xf = findx(); /* this line needed to make the next */
X /* call eval order independent, if you wondered */
X tvxy(xf,tvy); /* and move cursor */
X }
X
X/* =============================>>> BOTPAG <<<============================= */
X botpag()
X { /* botpag - move cursor to bottom of current page (buffer) */
X
X curlin = nxtlin-1; /* the last real line of text */
X curchr = *(lines+curlin) + 1; /* the first char of that line */
X endlin(); /* goto end of the line */
X newscr(); /* update the screen */
X }
X
X/* ============================>>> CHK_RPT_NR <<<============================ */
X chk_rpt_nr(val)
X int val;
X { /* see if val is in valid range */
X
X if (val < 0 || val > REPEATBUFS) /* out of range */
X {
X tverrb("Bad rpt buff # ");
X return (FALSE);
X }
X else
X return (TRUE);
X }
X
X/* =============================>>> CMDERR <<<============================= */
X cmderr(chr)
X char chr;
X { /* cmderr - invalid command entered */
X
X static char badcmd[] = "Bad command: ";
X
X if (chr >= ' ')
X {
X badcmd[13] = chr; /* stick in after : */
X badcmd[14] = ' ';
X }
X else
X {
X badcmd[13] = '^';
X badcmd[14] = chr + '@';
X }
X tverrb(badcmd);
X }
X
X/* =============================>>> COMBIN <<<============================= */
X combin()
X { /* combin - combine current line with next line
X update screen - cursor assumed to be on curlin */
X
X SLOW int to,from,xf;
X SLOW BUFFINDEX newl,k1,k2;
X
X if (curlin+1 >= nxtlin) /* can't combine */
X return (FALSE);
X if (nxtsav-nxtchr < ALMOSTOUT) /* check if need g.c. */
X if (! gbgcol())
X return (FALSE);
X newl = nxtchr; /* where next char goes */
X stcopy(buff,*(lines+curlin),buff,&nxtchr); /* copy over current line */
X curchr = nxtchr; /* update the curchr */
X k1 = *(lines+curlin); /* we will kill this line */
X *(lines+curlin) = newl; /* remember where it is */
X stcopy(buff,*(lines+curlin+1)+1,buff,&nxtchr); /* append the next line */
X ++nxtchr; /* fix nxtchr */
X to = curlin+1;
X k2 = *(lines+to); /* we will kill this line */
X for (from=curlin+2; from < nxtlin ; ) /* copy line to end */
X {
X *(lines+to++) = *(lines+from++);
X }
X --nxtlin; /* update line ptr */
X kline(k1); /* kill the old lines now */
X kline(k2);
X if (tvdlin <= dsplin) /* not at end of buffer */
X {
X tvescr(); /* erase rest of screen */
X tvxy(1,tvy); /* fix it up */
X tvtype(curlin,min(tvlins-tvdlin+1,nxtlin-curlin));
X }
X else /* at end of buffer */
X newscr();
X
X xf = findx();
X tvxy(xf,tvy); /* home cursor */
X
X return (TRUE);
X }
X
X/* =============================>>> CTRLCH <<<============================= */
X ctrlch(chr)
X char chr;
X { /* ctrlch - echoes a control character for search and lex */
X
X if (chr >= ' ')
X tvcout(chr); /* echo as is */
X else if (chr == CR) /* carriage return may be special */
X {
X tvcout(CR);
X#ifdef USELF
X tvcout(LF); /*$$$ some machines need LF */
X#endif
X }
X else if (chr == ESC) /* escape as $ */
X tvcout('$');
X else /* echo most chars as '^x' */
X {
X tvcout('^');
X tvcout(chr+'@');
X }
X }
X
X/* =============================>>> DELNXT <<<============================= */
X int delnxt(cnt)
X int cnt;
X { /* delnxt - delete next n characters */
X
X char clower();
X static char chdel;
X SLOW int abscnt,newx;
X SLOW BUFFINDEX to;
X SLOW char ans[2];
X FAST int i;
X
X abscnt = cnt; /* remember absolute value of cnt */
X if (cnt > 100 || cnt < -100) /* make sure about this! */
X {
X tvclr();
X ask("Kill that many for sure? (y/n) ",ans,1);
X verify(1);
X if (clower(ans[0]) != 'y')
X return (TRUE);
X }
X
X if (cnt > 0) /* deleting forewards */
X {
X chdel = *(buff+curchr); /* remember the char we are deleting */
X for (i=1; curlin < nxtlin && i <= cnt; ++i) /* don't pass end of buff */
X {
X if (*(buff+curchr)==ENDLINE) /* combine when end of line */
X {
X if (! combin())
X {
X return (FALSE);
X }
X }
X else /* deleting one character */
X {
X to=curchr; /* overwrite current line */
X stcopy(buff,curchr+1,buff,&to); /* copy the rest of the line */
X for (++to; *(buff+to) != BEGLINE && to < nxtchr; ++to)
X *(buff+to)=GARBAGE; /* mark the garbage characters */
X }
X }
X }
X else if (cnt < 0) /* deleting backwards */
X {
X abscnt=(-cnt);
X chdel = *(buff+curchr-1); /* remember the char we are deleting */
X for (i=cnt; curlin >= 1 && i<0; ++i) /* don't go past start */
X {
X if (*(buff+curchr-1)==BEGLINE) /* deleting line separator */
X {
X if (curlin > 1) /* not past beginning */
X {
X dwnlin(-1); /* go up one line */
X endlin(); /* get end of the line */
X if (!combin()) /* and combine */
X {
X return (FALSE);
X }
X }
X }
X else /* killing a normal character */
X {
X to=curchr-1; /* overwrite in place */
X stcopy(buff,curchr,buff,&to); /* copy the rest of the line */
X for (++to; *(buff+to)!=BEGLINE && to < nxtchr; ++to)
X *(buff+to)=GARBAGE; /* mark the garbage characters */
X --curchr;
X }
X }
X }
X newx=findx(); /* where cursor will go */
X tvxy(newx,tvy); /* reposition cursor */
X if (chdel < ' ' || abscnt != 1)
X tvelin(); /* erase rest of the line */
X else /* need to check for tabs following */
X {
X for (i = curchr ; *(buff+i)!=ENDLINE ; ++i)
X if (*(buff+i) < ' ')
X {
X tvelin(); /* need to erase the line */
X break;
X }
X }
X tvtyln(curchr); /* retype the rest */
X if (chdel >= ' ' && abscnt == 1 && last_col_out < tvcols)
X tvcout(' '); /* "erase" last char on line */
X tvxy(newx,tvy); /* restore the cursor */
X
X return (TRUE);
X }
X
X/* =============================>>> DWNCOL <<<============================= */
X dwncol(cnt)
X int cnt;
X { /* dwncol - move down in column */
X
X SLOW int curcol,l,oldef,needns;
X
X needns = FALSE;
X if (leftmg > 1) /* handle right virtual screen different */
X {
X oldef=echof;
X needns = TRUE;
X echof = FALSE;
X }
X
X if (oldlex==VDOWNCOL || oldlex==VUPCOL) /* several in a row? */
X curcol=oldcol; /* pick up old value */
X else
X {
X curcol = curchr - *(lines+curlin); /* calculate the current column */
X oldcol = curcol;
X }
X dwnlin(cnt); /* go down given lines */
X if (curlin>=1 && curlin<nxtlin && curcol>1) /* not at ends? */
X {
X l = strlen(buff + ((*(lines+curlin)) + 1) );
X right(min(curcol-1,l));
X }
X
X if (needns) /* needed new screen */
X {
X echof=oldef;
X newscr();
X }
X }
X
X/* =============================>>> DWNLIN <<<============================= */
X dwnlin(cnt)
X int cnt;
X { /* dwnlin - move dot down cnt lines */
X
X SLOW int oldlin,change;
X
X if (curlin==nxtlin-1 && cnt > 0) /* down from last line? */
X {
X endlin();
X return;
X }
X oldlin=curlin; /* remember where we started from */
X curlin=max(min(curlin+cnt,nxtlin-1),1); /* move down lines */
X curchr = *(lines+curlin)+1; /* point to the current character */
X change=curlin-oldlin; /* calculate how many lines changed */
X update(change); /* update the screen */
X
X }
X
X/* =============================>>> EDIT <<<============================= */
X edit()
X { /* edit - main editing routine */
X
X SLOW int lexval,lexcnt,succ, lastln, itmp;
X SLOW int noteloc[10], ni, lex_def;
X
X static int ins_set[] =
X {
X VINSERT, VOPENLINE, VQUIT, VABORT, VFBEGIN, VGET, VYANK, 0
X };
X
X static int jump_set[] = /* commands to not reset jump memory */
X {
X VJUMP, VMEMORY, VHELP, VNOTELOC, VPRINTS, 0
X };
X
X static char lexchr;
X
X startm();
X remark("Reading file...");
X
X rdpage(); /* read a page into the buffer */
X
X tvclr(); /* clear the screen */
X
X if (curlin >= 1)
X tvtype(curlin,tvlins); /* type out lines */
X
X tvxy(1,1); /* and rehome the cursor */
X waserr = FALSE; /* no errors to erase yet */
X
X if (curlin<1)
X tverr("Buffer empty");
X
X lexval = UNKNOWN; /* so can remember 1st time through */
X useprint = FALSE; /* not to printer */
X succ=TRUE; /* assume success initially */
X
X lastln = curlin; /* remember where we were */
X for (ni = 0 ; ni < 10 ; noteloc[ni++] = curlin)
X ; /* init noteloc */
X do
X {
X oldlex = lexval; /* remember last command */
X if (! succ)
X echof = TRUE; /* resume echo when error */
X lex_def = lex(&lexval,&lexcnt,&lexchr,succ); /* get command input */
X if (waserr)
X fixend();
X waserr=FALSE;
X succ=TRUE;
X if (lexval == UNKNOWN)
X {
X cmderr(lexchr);
X succ = FALSE; /* announce failure to lex */
X }
X else
X {
X if (curlin < 1) /* make sure legal command for empty buffer */
X {
X
X if (!inset(lexval,ins_set))
X {
X tverrb("Can't, buffer empty. Insert 1st ");
X succ=FALSE;
X continue;
X }
X }
X if (!inset(lexval,jump_set))
X lastln=curlin; /* let user look at help w/o changing */
X
X switch (lexval)
X {
Xcase 1: /* right */
X right(lexcnt);
X break;
Xcase 2: /* left */
X right(-lexcnt);
X break;
Xcase 3: /* down line */
X dwnlin(lexcnt);
X break;
Xcase 4: /* up line */
X dwnlin(-lexcnt);
X break;
Xcase 5: /* down in column */
X dwncol(lexcnt);
X break;
Xcase 6: /* up in column */
X dwncol(-lexcnt);
X break;
Xcase 7: /* delete last character */
X succ = delnxt(-lexcnt);
X break;
Xcase 8: /* delete next character */
X succ = delnxt(lexcnt);
X break;
Xcase 9: /* insert */
X succ = insert(lexcnt,lex_def);
X break;
Xcase 10: /* kill a line */
X killin(lexcnt);
X break;
Xcase 11: /* kill rest of line */
X krest();
X break;
Xcase 12: /* kill previous part of line */
X kprev();
X break;
Xcase 13: /* move to beginning of line */
X beglin();
X break;
Xcase 14: /* move to end of the line */
X endlin();
X break;
Xcase 15: /* search for a pattern */
X succ = search(lexcnt,TRUE);
X break;
Xcase 16: /* search for next part of a pattern */
X succ = snext(lexcnt,TRUE);
X break;
Xcase 17: /* flip screen */
X dwnlin(min(lexcnt*tvlins,nxtlin-curlin+1));
X break;
Xcase 18: /* goto top of page */
X toppag();
X break;
Xcase 19: /* goto to bottom of page */
X botpag();
X break;
Xcase 20: /* goto real beginning of the file */
X succ = fbeg();
X break;
Xcase 21: /* verify */
X verify(lexcnt);
X break;
Xcase 22: /* open new line */
X openln(lexcnt);
X succ = insert(1,TRUE); /* go into insert mode, insert mode */
X break;
Xcase 23: /* delete last thing manipulated */
X succ = rmvlst();
X break;
Xcase 24: /* save lines in move buffer */
X succ = save(lexcnt,FALSE);
X break;
Xcase 25: /* get move buffer */
X succ = getsav();
X break;
Xcase 26: /* read in next page of file */
X wtpage(lexcnt); /* write out the current page */
X succ = rdpage(); /* read in the next */
X tvclr();
X if (succ || lexcnt < 0)
X verify(1);
X break;
Xcase 27: /* append external file to save buffer */
X succ = addfil(lexcnt);
X break;
Xcase 28: /* quit */
X tvclr();
X remark("Exit");
X goto lquit;
Xcase 29: /* search again */
X succ = search(lexcnt,FALSE); /* FALSE => don't read search string */
X break;
Xcase 30: /* execute repeat buffer again */
X if (lexcnt != 1)
X echof=FALSE; /* turn off echo */
X rptcnt[rptuse] = lexcnt > 0 ? lexcnt : (-lexcnt);
X break;
Xcase 31: /* print memory status, etc. */
X memory();
X break;
Xcase 32: /* change a parameter */
X setpar(lexcnt);
X break;
Xcase 33: /* remove last and enter insert mode */
X if ((succ = rmvlst()))
X succ = insert(1,TRUE);
X break;
Xcase 34: /* unkill last line killed */
X succ = unkill();
X break;
Xcase 35: /* jump over a word */
X wordr(lexcnt);
X break;
Xcase 36: /* neg jump over word */
X wordr(-lexcnt);
X break;
Xcase 37: /* append to save buffer */
X succ = save(lexcnt,TRUE);
X break;
Xcase 38: /* print screen */
X scrprint();
X break;
Xcase 39: /* show repeat buffer + help*/
X shoset();
X break;
Xcase 40: /* flip screen half page */
X dwnlin( min((lexcnt*tvlins)/2 , nxtlin-curlin+1) );
X break;
Xcase 41: /* abort */
X abort();
X break;
Xcase 42: /* change characters */
X if ((succ = delnxt(lexcnt)))
X succ = insert(1,TRUE);
X break;
Xcase 43: /* jump back to last location */
X itmp = curlin;
X curlin = lastln;
X curchr = *(lines+curlin)+1; /* point to the current character */
X verify(1);
X lastln = itmp;
X break;
Xcase 44: /* tidy up screen */
X succ = neaten(lexcnt);
X break;
Xcase 45: /* save current location */
X if (lexcnt < 1 || lexcnt > 9)
X lexcnt = 0;
X noteloc[lexcnt] = curlin;
X break;
Xcase 46: /* return to noted location */
X itmp = curlin;
X if (lexcnt < 1 || lexcnt > 9)
X lexcnt = 0;
X if (noteloc[lexcnt] >= nxtlin)
X {
X tverrb("Line no longer there ");
X noteloc[lexcnt] = curlin;
X }
X else
X {
X curlin = noteloc[lexcnt];
X curchr = *(lines+curlin)+1; /* point to the current character */
X verify(1);
X lastln = itmp;
X }
X break;
X
Xcase 47:
X opsystem(); /* call operating system */
X break;
X
Xcase 48:
X if (lex_def) /* default 1 passed */
X lexcnt = rptuse + 1; /* use current repeat loop */
X succ = edit_rpt(lexcnt); /* edit repeat buffer */
X break;
X
Xcase 49:
X succ = store_rpt(lexcnt); /* store repeat buffer */
X break;
X
Xcase 50:
X succ = exec_rpt(lexcnt); /* execute repeat buffer */
X break;
X
Xcase 51:
X succ = ins_pat(lexcnt);
X break;
Xcase 52:
X succ = user_1(lexcnt); /* user function 1 */
X break;
X
Xcase 53:
X succ = user_2(lexcnt); /* user function 2 */
X break;
X } /* end of switch */
X continue; /* next iteration of do loop */
X } /* end of else */
X } /* end of do loop */
X while (1);
X
Xlquit:
X for ( wtpage(1) ; rdpage() ; wtpage(1) ) /* write whole file */
X ;
X tvclr();
X }
X
X/* =============================>>> EDIT_RPT <<<============================= */
X edit_rpt(val)
X int val;
X { /* copy repeat buffer val into buffer for editing */
X
X SLOW char *cp;
X SLOW int start_line;
X
X if (val == 0)
X val = rptuse+1;
X
X if (!chk_rpt_nr(val))
X return FALSE;
X
X --val; /* change to relative */
X
X beglin(); /* start by moving to beginning of current line */
X start_line = curlin; /* where we started */
X
X
X ins_chr('#'); ins_chr(val+'1'); ins_chr(':');
X /* start with number */
X ins_chr('<'); /* insert start of repeat loop */
X
X for (cp = &rptbuf[val][0] ; *cp ; ++cp)
X ins_chr(*cp);
X ins_chr(27); ins_chr(27); /* make a way for store_rpt to find end */
X
X ins_chr(CR); /* terminate line */
X curlin = start_line;
X curchr = *(lines+curlin)+1;
X verify(1);
X
X return (TRUE);
X
X }
X
X/* =============================>>> ENDLIN <<<============================= */
X endlin()
X { /* endlin - move cursor to end of the line */
X
X FAST int cnt;
X SLOW BUFFINDEX i;
X
X cnt=0;
X for (i=curchr; *(buff+i)!=ENDLINE; ++i) /* find end of line */
X ++cnt;
X right(cnt); /* move to end of line */
X }
X
X/* =============================>>> EXEC_RPT <<<============================= */
X exec_rpt(knt)
X int knt;
X { /* this is combination of k:r,n& */
X static char chr;
X static int val;
X
X if (! grptch(&chr)) /* get buffer # (k) to use */
X return (FALSE);
X
X val = chr - '0'; /* convert to 0 to 9 */
X
X if (!chk_rpt_nr(val))
X return FALSE;
X
X if (val > 0) /* change to specific buffer */
X rptuse=val-1; /* adjust for 0 index int */
X
X if (knt != 1)
X echof = FALSE; /* turn off echo */
X
X rptcnt[rptuse] = knt > 0 ? knt : (-knt);
X
X return (TRUE);
X }
X
X/* =============================>>> FINDDL <<<============================= */
X finddl(ibeg,cnt)
X int *ibeg,*cnt;
X { /* finddl - find the display line
X known: current line, calculate where it would go on the screen */
X
X if (curlin <= dsplin)
X { /* it is in first part of the display */
X *ibeg = 1;
X *cnt = min(tvlins,nxtlin-1);
X tvdlin = curlin; /* update the display line */
X }
X else if (nxtlin-curlin <= tvlins-dsplin) /* at bottom of display */
X {
X *ibeg = max(1,nxtlin-tvlins);
X *cnt = min(tvlins,nxtlin-1);
X tvdlin=min(curlin,tvlins-(nxtlin-curlin)+1);
X }
X else /* normal case: in middle */
X {
X *ibeg=max(1,curlin-dsplin+1);
X *cnt=min(tvlins,nxtlin-(*ibeg));
X tvdlin=dsplin;
X }
X }
X
X/* =============================>>> FINDX <<<============================= */
X int findx()
X { /* findx - find the x position of the current character
X handles spacing for tabs, control characters etc */
X
X SLOW BUFFINDEX i;
X SLOW int pos,lmold;
X
X pos = 0;
X for (i = *(lines+curlin)+1; i<=curchr; ++i)
X if (*(buff+i-1)<' ' && *(buff+i-1)>0) /* cur pos depends on last chr */
X if (*(buff+i-1)==TAB) /* handle tabs */
X for (++pos ; ((pos-1) % 8)!=0; ++pos)
X ;
X else /* control characters (echoed as ^X) */
X pos += 2; /* 2 spaces for other control character */
X else /* normal character */
X ++pos;
X
X lmold = leftmg; /* old left margin */
X for (;;)
X {
X if (pos < leftmg) /* won't fit on screen */
X leftmg -= 16; /* shift left */
X else if (pos >= tvcols+leftmg)
X leftmg += 16;
X else
X break;
X }
X
X if (leftmg != lmold) /* this handles screen shift */
X newscr();
X
X return (pos-leftmg+1);
X }
X
X/* =============================>>> FIXEND <<<============================= */
X fixend()
X { /* fixend - fix the error message line */
X
X SLOW int lastl;
X
X lastl = curlin+(tvlins-tvdlin); /* the last line on the display */
X tvxy(1,tvhardlines); /* get to last line */
X tvelin();
X if (lastl < nxtlin && tvlins == tvhardlines) /* only if really there */
X tvtype(lastl,1); /* write it out */
X if (curlin >= 1)
X tvhdln(); /* restore cursor */
X else
X tvxy(1,1);
X }
X
X/* =============================>>> GBGCOL <<<============================= */
X int gbgcol()
X { /* gbgcol - retrieve unused space in buff */
X
X FAST int i;
X SLOW int lastln;
X SLOW BUFFINDEX nxtbad, nxtgud, to, from, whfrom, offset, newlin;
X
X tverrb("Compacting buffer "); /* let the user know, it might take a while */
X offset = curchr - *(lines+curlin); /* need to reset curchr later */
X
X for (nxtbad=1 ; *(buff+nxtbad)!=GARBAGE && nxtbad < nxtchr; ++nxtbad)
X ; /* find first space to free */
X nxtgud=nxtbad;
X lastln = 1; /* where to start search */
X do
X {
X to=nxtbad;
X for (from=nxtgud; *(buff+from)==GARBAGE && from<nxtchr; ++from)
X ; /* find the next non-garbage character */
X
X/* nxtbad pts to first junk character,
X nxtgud pts to next possibly good character */
X
X if (from >= nxtchr)
X break; /* at the end of the buffer */
X whfrom=from; /* where it came from */
X newlin = to; /* remember start */
X do
X {
X *(buff+to) = *(buff+from++); /* copy good stuff up */
X }
X while (*(buff+to++)!=ENDLINE);
X
X nxtbad=to ; nxtgud=from;
X
X/* now find the old line
X following algorithm assumes next line is likely to
X be near the previous line */
X
X for (i=lastln ; i<nxtlin ; ++i) /* start where last looked */
X if (*(lines+i)==whfrom)
X {
X *(lines+i)=newlin; /* point to new position */
X if (curlin==i)
X curchr=newlin+offset; /* fix curchr if need be */
X break;
X }
X
X if (i >= nxtlin) /* not found in second half */
X {
X for (i=1 ; i < lastln ; ++i)
X if (*(lines+i)==whfrom)
X {
X *(lines+i)=newlin; /* point to new position */
X if (curlin==i)
X curchr=newlin+offset; /* fix curchr if need be */
X break;
X }
X if (i >= lastln) /* make sure we really found it */
X {
X tverrb("Compactor lost. Quit NOW! ");
X for (i=1 ; i < 32000 ; ++i)
X ;
X return (FALSE);
X }
X }
X lastln = i; /* start at next line down */
X }
X while (nxtgud < nxtchr);
X
X for (to=nxtbad ; to<=nxtchr ; )
X *(buff+to++)=GARBAGE;
X
X nxtchr=nxtbad; /* update the next free character */
X tverr("Compactor done");
X return (nxtsav-nxtchr >= 50);
X }
X
X/* =============================>>> GETSAV <<<============================= */
X int getsav()
X { /* ## getsav - get text from save buffer */
X
X FAST int to,from;
X SLOW BUFFINDEX fromch;
X SLOW int newlin;
X
X if (mxbuff-nxtsav+savlin >= nxtsav-nxtchr) /* g.c. */
X if (!gbgcol())
X {
X tverrb("No get room ");
X return (FALSE);
X }
X
X if (nxtsav==mxbuff) /* nothing to save */
X {
X return (TRUE);
X }
X
X if (mxbuff-nxtsav+savlin >= nxtsav-nxtchr || mxline-nxtlin <= savlin)
X { /* room to get save buffer? */
X tverrb("No get room ");
X return (FALSE); /* no room to save */
X }
X
X/* check if in middle of line */
X if (curchr > lines[curlin]+1)
X ins_chr(CR);
X
X/* # move down line to make space for new */
X from=nxtlin-1;
X nxtlin=nxtlin+savlin;
X to=nxtlin-1;
X while (from >= curlin) /* copy line ptrs down right amnt. */
X *(lines+(to--)) = *(lines+(from--));
X
X newlin=curlin; /* will insert new lines here */
X curlin=to+1;
X fromch = mxbuff; /* where taking saved stuff from */
X for ( ; newlin < curlin; ++newlin)
X {
X *(buff+nxtchr)=BEGLINE; /* insert begline character */
X *(lines+newlin) = nxtchr++; /* update line ptrs to new line */
X do /* copy stuff from save buffer */
X {
X *(buff+nxtchr++) = *(buff+fromch);
X }
X while (*(buff+fromch--));
X }
X oldlen=0;
X savlen=savlin;
X newscr();
X return (TRUE);
X }
X
X/* =============================>>> GRPTCH <<<============================= */
X int grptch(chr)
X char *chr;
X { /* grptch - gets a char from repeat buffer or gkbd */
X
X SLOW char tmpchr;
X
X if (rptcnt[rptuse]>0) /* need to fetch from repeat buffer */
X if (nxtrpt[rptuse] > lstrpt[rptuse])
X {
X return (FALSE);
X }
X else
X {
X *chr=rptbuf[rptuse][nxtrpt[rptuse]];
X ++nxtrpt[rptuse];
X }
X else
X {
X gkbd(&tmpchr); /* read the character from the keyboard */
X *chr=tmpchr;
X }
X return (TRUE);
X }
X
X/* =============================>>> ins_pat <<<============================= */
X ins_pat(lexcnt)
X int lexcnt;
X {
X SLOW char *chrp;
X
X if (!*pat_buff)
X return (FALSE);
X for (chrp = pat_buff ; *chrp ; ) /* simply insert pattern buffer */
X {
X if (!ins_chr(*chrp++)) /* make sure it works */
X return (FALSE);
X }
X
X return (TRUE);
X }
X
X/* =============================>>> save_pat <<<============================= */
X save_pat()
X { /* save the find pattern, based on oldlen */
X
X SLOW int i;
X SLOW char *chrp;
X
X
X if (oldlen <= 0)
X {
X pat_buff[0] = 0;
X return; /* nothing to save */
X }
X
X for (i = 1 ; i <= oldlen ; ++i) /* first, move left */
X {
X --curchr;
X if (*(buff+curchr) == BEGLINE)
X {
X if (curlin > 1)
X {
X --curlin;
X for (curchr = *(lines+curlin) ; *(buff+curchr)!=ENDLINE ;
X ++curchr)
X ; /* bump curchr to end of the line */
X }
X else
X {
X ++curchr;
X break;
X }
X }
X }
X
X /* now save, go back right */
X
X chrp = pat_buff; /* put in pattern buffer */
X
X for (i = 1 ; i <= oldlen ; ++i)
X {
X if (*(buff+curchr)==ENDLINE)
X {
X if (curlin+1 >= nxtlin)
X break; /* don't go beyond end! */
X ++curlin;
X curchr = *(lines+curlin)+1;
X *chrp++ = CR; /* make a cr */
X }
X else
X {
X if ((chrp - 100) < pat_buff) /* make sure enough room */
X *chrp++ = *(buff+curchr);
X ++curchr;
X }
X }
X *chrp = 0; /* terminate */
X }
X
X/* =============================>>> INSET <<<============================= */
X inset(val,set)
X int val,*set;
X {
X /* return true if val is in set set */
X
X while (*set)
X if (val == *set++)
X return TRUE;
X return FALSE;
X }
X
X/* =============================>>> ins_chr <<<============================= */
X ins_chr(ival)
X int ival;
X {
X return insert(ival,FALSE); /* force insert */
X }
X
X/* =============================>>> INSERT <<<============================= */
X insert(ival,how)
X int ival,how;
X { /* insert - insert a character
X
X if how is TRUE, then read characters from keyboard until
X get an escape, otherwise insert ival */
X
X SLOW BUFFINDEX from,to;
X SLOW BUFFINDEX curbuf,curend;
X SLOW int lenins, nocins, ityp, xf;
X SLOW BUFFINDEX abvchr;
X
X SLOW char chr;
X
X
X static int ins_msg = TRUE; /* own variable */
X
X if (ins_msg)
X csrins(); /* change cursor */
X
X if (how) /* how = 1 regular insert mode */
X {
X if (! grptch(&chr)) /* get char using grptch */
X goto l9999;
X if (chr == ESC) /* esc means done */
X {
X goto l1000;
X }
X }
X else
X chr = ival; /* use the passed value */
X
X if (chr==ENDLINE || chr==BEGLINE || chr==GARBAGE || (chr==ENDFILE && usecz))
X goto l9998; /* don't allow this case! */
X
X if (curlin < 1)
X { /* buffer empty? */
X curlin=1; /* init for initial insert */
X *(lines+1)=nxtchr;
X curchr=nxtchr+1;
X *(buff+nxtchr)=BEGLINE;
X *(buff+nxtchr+1)=ENDLINE;
X nxtchr += 2;
X nxtlin = 2;
X }
X
X lenins=0; /* remember length of insert for rmvlst */
X
X do
X {
X if (nxtsav-nxtchr < ALMOSTOUT)
X if (!gbgcol())
X goto l9999; /* collect garbage if necessary */
X curbuf = *(lines+curlin); /* pick up the pointer to current line */
X for (curend=curbuf; *(buff+curend)!=ENDLINE; ++curend)
X ; /* get line length */
X if (curend+1 < nxtchr) /* not using last part of buffer */
X {
X if (curend-curbuf >= nxtsav-nxtchr)
X goto l9998; /* no more room! */
X curchr=nxtchr+(curchr-curbuf); /* where curchr will be */
X *(lines+curlin)=nxtchr; /* new line goes here */
X stcopy(buff,curbuf,buff,&nxtchr); /* copy the line to the end */
X curend=nxtchr++; /* reset end pointer */
X kline(curbuf); /* kill off the line */
X curbuf = *(lines+curlin); /* update beginning pointer */
X }
X
X/* # to here, ready to insert the new character at the end of the line */
X
X if (chr==' ' && wraplm > 1 && (tvx >= wraplm || leftmg > 1)) /* auto wrap? */
X chr = CR;
X#ifdef FILELF
X if (chr == LF && how)
X ; /* don't insert lfs in CR/LF systems, echo? */
X else if (chr == CR) /* inserting a new line */
X#else
X if (chr == CR) /* inserting a new line */
X#endif
X {
X if (nxtlin >= mxline) /* any room? */
X {
X tverrb("No more free lines for insert ");
X goto l9999;
X }
X
X for (from=curend; from >= curchr; --from)
X *(buff+from+2) = *(buff+from); /* copy chars down */
X nxtchr += 2; /* bump nxtchr to free space */
X
X *(buff+curchr) = ENDLINE; /* mark as endline */
X *(buff+curchr+1) = BEGLINE; /* beginning of line */
X ++lenins;
X
X to=nxtlin; /* move lines down */
X for (from = nxtlin-1; from > curlin; )
X { /* bump the lines down */
X *(lines+to--) = *(lines+from--);
X }
X ++nxtlin; /* bump to next free line */
X
X *(lines+curlin+1)=curchr+1; /* remember where */
X
X if (ins_msg)
X fixend(); /* fix last line */
X tvelin(); /* erase stuff after cr */
X
X nocins = (leftmg > 1); /* ciline no good if left marg > 1 */
X
X dwnlin(1); /* go down one line */
X
X if (ciline[0] == 0 || nocins)
X {
X tvescr(); /* erase the rest of the screen */
X ityp = min(tvlins-tvdlin+1,nxtlin-curlin);
X }
X else
X {
X tvinsl(); /* insert a line */
X ityp = 1;
X }
X
X tvtype(curlin,ityp);
X tvhdln();
X if (ins_msg)
X csrins(); /* change cursor */
X
X if (autoin && curlin > 2) /* automatic indentation! */
X {
X ins_msg = FALSE; /* turn off insert message */
X abvchr = *(lines+curlin-1)+1; /* prevous line */
X while (*(buff+abvchr)==' ' || *(buff+abvchr)==TAB)
X if (!insert(*(buff+abvchr++),FALSE) )
X {
X ins_msg = TRUE;
X goto l9999;
X }
X else if (ttymode) /* hmm, now what? */
X {
X ttymode = FALSE;
X ttwt(*(buff+abvchr-1));
X ttymode = TRUE;
X }
X ins_msg = TRUE;
X fixend();
X csrins(); /* change cursor */
X }
X }
X else if (chr == delkey && how)
X {
X if (!delnxt(-1)) /* rubbing out last character */
X goto l9999;
X --lenins;
X }
X else /* inserting on the current line */
X {
X to = nxtchr; /* will move to nxtchr */
X for (from = curend ; from >= curchr; )
X {
X *(buff+to--) = *(buff+from--);
X }
X curend=nxtchr++; /* end is now at curchr, bump nxtchr */
X *(buff+curchr)=chr; /* stick in the current character */
X ++lenins;
X if (tvlins < tvhardlines - 10)
X {
X tvelin();
X ctrlch(chr);
X ctrlch('+');
X }
X else
X tvtyln(curchr); /* retype rest of the line */
X ++curchr; /* reset the curchr pointer */
X xf = findx();
X tvxy(xf,tvy); /* reset the cursor */
X }
X
X/* the character has been inserted and displayed, get another maybe */
X
X if (how)
X if (!grptch(&chr))
X goto l9999;
X }
X while (how && chr != ESC); /* end of do */
X
X if (tvlins < tvhardlines - 10) /* fix for slow baud */
X {
X tvelin();
X tvtyln(curchr); /* retype rest of the line */
X xf = findx();
X tvxy(xf,tvy); /* reset the cursor */
X }
X
X oldlen = lenins;
X savlen = (-1); /* haven't saved lines */
X goto l1000;
X
Xl9998:
X tverrb("Can't insert that char ");
Xl9999:
X csrcmd();
X return FALSE;
Xl1000:
X
X if (ins_msg)
X fixend();
X csrcmd();
X return TRUE;
X }
X/* ------------------------ tvx_1.c ------------------------------------- */
SHAR_EOF
echo Extracting tvx_2.c:
sed 's/^X//' >tvx_2.c <<\SHAR_EOF
X/* -------------------------------- tvx_2.c ------------------------------- */
X/* ========================================================================
X
X tvx_2.c - Part 2 of main TVX code
X
X============================================================================ */
X
X#include "tvx_defs.ic" /* note tv_defs will #include stdio.h */
X#include "tvx_glbl.ic"
X
X/* =============================>>> KILLIN <<<============================= */
X killin(cnt)
X int cnt;
X { /* ## killin - kill cnt lines */
X
X SLOW int i,lim;
X SLOW int from,to,ityp,istrt;
X
X if (cnt+curlin >= nxtlin || (curlin == nxtlin-1 && cnt >= 0))
X { /* special case: deleting rest of buffer */
X svklin(nxtlin-1);
X for (i = curlin ; i <= nxtlin-1 ; )
X kline(*(lines+i++));
X nxtlin = curlin--;
X if (curlin > 0)
X {
X curchr = *(lines+curlin)+1;
X newscr();
X }
X else
X {
X curchr=0;
X tvclr();
X }
X return;
X }
X
X if (cnt < 0) /* negative kill */
X {
X cnt = min(-cnt,curlin-1); /* all upwards? */
X dwnlin(-cnt); /* go up that far */
X }
X
X if (cnt != 0)
X {
X range(cnt,&to,&from); /* calculate the line numbers to kill */
X
X curlin=to; /* remember new current line */
X
X svklin(from); /* save one line */
X for (i = to ; i <= from ; ) /* mark lines deleted */
X kline(*(lines+i++));
X
X lim = min(nxtlin-1,mxline);
X for (++from ; from <= lim ; )
X {
X *(lines+to++) = *(lines+from++); /* copy next line number */
X }
X
X nxtlin=to;
X if (nxtlin == curlin)
X --curlin; /* don't go past end */
X curchr = *(lines+curlin)+1; /* remember new current character */
X
X if (cnt >= 0 && curlin+(tvlins-tvdlin) < nxtlin &&
X tvdlin < tvlins) /* killing down */
X {
X tvxy(1,tvy); /* get to start of line */
X ityp=min(tvlins-tvdlin+1,nxtlin-curlin);
X if (cnt!=1 || !ckline[0])
X {
X tvescr(); /* erase the screen */
X istrt=curlin;
X }
X else
X {
X sendcs(ckline);
X istrt=curlin+ityp-1;
X tvxy(1,tvlins);
X ityp=1;
X }
X tvtype(istrt,ityp);
X tvhdln(); /* home to display line */
X }
X else if ( cnt != 1) /* neg and > 1 too complicated */
X newscr(); /* kill up, just retype whole screen */
X else if (nxtlin < tvlins) /* top part of screen */
X {
X if (*ckline) /* kill line defined */
X {
X tvxy(1,tvy); /* get to start of line */
X sendcs(ckline); /* just need to kill the line */
X tvhdln();
X }
X else
X newscr(); /* rewrite it all */
X }
X else if (tvdlin < tvlins) /* must be in last part of buffer */
X {
X if (*ckline && *ctopb) /* kill line & topb defined */
X {
X tvxy(1,tvy); /* get to start of line */
X sendcs(ckline); /* kill the line */
X if (curlin-tvdlin > 0) /* something to scroll */
X {
X tvtopb(1); /* scroll down one line */
X tvtype(curlin-tvdlin,1); /* type the offscreen line */
X tvdlin++; /* will start display on next line */
X }
X tvhdln();
X }
X else
X newscr(); /* rewrite it all */
X }
X else /* if all else fails */
X newscr();
X }
X }
X
X/* =============================>>> KLINE <<<============================= */
X kline(ptr)
X BUFFINDEX ptr;
X { /* kline - kill off the line beginning at buff position ptr */
X
X SLOW BUFFINDEX i;
X
X for (i=ptr; *(buff+i) != ENDLINE ; ) /* insert GARBAGE to kill */
X *(buff+i++)=GARBAGE;
X
X *(buff+i)=GARBAGE; /* kill the endline */
X }
X
X/* =============================>>> KPREV <<<============================= */
X kprev()
X { /* kprev - kill from cursor to beginning of line */
X
X FAST int chrs;
X
X svklin(curlin); /* save one line */
X chrs = curchr - *(lines+curlin) - 1; /* how much to delete */
X if (chrs > 0)
X delnxt(-chrs); /* won't cause a combine, so don't worry */
X }
X
X/* =============================>>> KREST <<<============================= */
X krest()
X { /* krest - kill the rest of the line, not including cursor and ENDLINE */
X
X SLOW int chrs;
X SLOW BUFFINDEX i;
X
X svklin(curlin); /* save one line */
X chrs=0;
X for (i=curchr; *(buff+i)!=ENDLINE; ++i)
X ++chrs; /* count how much to delete */
X if (chrs > 0)
X delnxt(chrs); /* won't cause combine, so don't worry */
X }
X
X/* =============================>>> NEATEN <<<============================= */
X int neaten(count)
X int count;
X { /* neaten - fill lines to current margin */
X
X SLOW int oldef, i;
X SLOW BUFFINDEX linbeg;
X SLOW int retval;
X
X retval = TRUE;
X oldef = echof;
X if (count > 1)
X echof = FALSE;
X if (wraplm <= 1 || curlin >= nxtlin-1)
X goto l900; /* work only if wrap limit turned on */
X
X for (i=1 ; i<=count ; ++i)
X {
X beglin(); /* start at beginning of line */
X if (curlin >= nxtlin-1)
X goto l900;
X
X /* don't neaten leading space, cr, period or tab */
X
X if (*(buff+curchr) == '.')
X {
X dwnlin(1);
X continue; /* skip dot commands */
X }
X
X while (*(buff+curchr)== ' ' || *(buff+curchr)==ENDLINE
X || *(buff+curchr) == 9)
X {
X right(1); /* skip this line */
X }
X
X do
X {
X if (*(buff+curchr) == ENDLINE)
X {
X if (tvx+leftmg < wraplm) /* combine lines! */
X {
X linbeg = *(lines+curlin+1)+1;
X /* pt to first char of next line */
X if (*(buff+linbeg) == ' ' || *(buff+linbeg) == ENDLINE
X || *(buff+linbeg) == 9 || *(buff+linbeg) == '.')
X {
X dwnlin(1);
X break; /* no more combining */
X }
X if (! neat1(1,32))
X goto l990;
X goto NEATNEXT; /* tab over another word */
X }
X else
X {
X dwnlin(1); /* no more combining on line */
X break;
X }
X }
X
XNEATNEXT:
X if (*(buff+curchr-1)==' ' && tvx+leftmg >= wraplm) /* change to cr */
X {
X if (! neat1(-1,CR)) /* delete the blank */
X goto l990;
X break;
X }
X wordr(1);
X } /*# end of the repeat */
X while (1);
X } /*# end of the for */
Xl900:
X echof = oldef;
X if (oldef && count > 1)
X newscr();
X return (retval);
X
Xl990: /* failure return */
X retval = FALSE;
X goto l900;
X }
X
X/* =============================>>> NEAT1 <<<============================= */
X neat1(dir, val)
X int dir, val;
X { /* change character dir to val */
X
X SLOW int oldwrp;
X
X oldwrp = wraplm;
X wraplm = 0;
X if (! delnxt(dir))
X goto l900;
X if (! ins_chr(val))
X goto l900;
X wraplm = oldwrp;
X return (TRUE);
Xl900:
X wraplm = oldwrp;
X return (FALSE);
X }
X
X/* =============================>>> NEWSCR <<<============================= */
X newscr()
X { /* newscr - retype entire screen, updating cursor position if necessary */
X
X SLOW int ibeg,cnt;
X
X if (tvlins != tvhardlines || nxtlin-1 <= tvlins)
X /* two kinds of screen rewrite */
X tvclr(); /* clear the screen and home */
X else
X tvxy(1,1);
X
X finddl(&ibeg,&cnt); /* calculate where it will go */
X tvtype(ibeg,cnt); /* type it out */
X tvhdln(); /* home to display line */
X }
X
X/* =============================>>> OPENLN <<<============================= */
X openln(cnt)
X int cnt;
X { /* openln - open a new line */
X
X FAST int i;
X SLOW int pcnt, oldauto;
X
X oldauto = autoin; autoin = FALSE; /* don't allow autoindent */
X pcnt = cnt >= 0 ? cnt : (-cnt); /* only allow positive opens */
X for (i=1; i<=pcnt; ++i)
X ins_chr(CR); /* insert right number of newlines */
X dwnlin(-pcnt); /* and goto beginning of the opened line */
X endlin();
X autoin = oldauto;
X }
X
X/* =============================>>> RANGE <<<============================= */
X range(cnt,lbeg,lend)
X int cnt,*lbeg,*lend;
X { /* determine a legal line number range given cnt */
X
X if (cnt <= 0)
X {
X *lbeg=max(curlin+cnt,1);
X *lend=curlin;
X if (cnt < 0)
X *lend = (*lend)-1;
X }
X else
X {
X *lbeg=curlin;
X *lend=min(nxtlin-1,curlin+cnt-1);
X }
X }
X
X/* =============================>>> RIGHT <<<============================= */
X right(cnt)
X int cnt;
X { /* move cursor right cnt characters
X newlines count as one character */
X
X FAST int change,i;
X
X change=0; /* nochange yet */
X if (cnt > 0)
X {
X for (i = 1 ; i <= cnt ; ++i)
X {
X if (*(buff+curchr)==ENDLINE)
X {
X if (curlin+1 >= nxtlin)
X break; /* don't go beyond end! */
X ++curlin;
X ++change; /* we've gone down one line */
X curchr = *(lines+curlin)+1;
X }
X else
X ++curchr;
X }
X }
X else if (cnt < 0)
X {
X cnt=(-cnt);
X for (i = 1 ; i <= cnt ; ++i)
X {
X --curchr;
X if (*(buff+curchr) == BEGLINE)
X {
X if (curlin > 1)
X {
X --curlin;
X --change;
X for (curchr = *(lines+curlin) ; *(buff+curchr)!=ENDLINE ;
X ++curchr)
X ; /* bump curchr to end of the line */
X }
X else
X {
X ++curchr;
X break;
X }
X }
X }
X }
X if (change != 0) /* don't do unnecessary change */
X update(change);
X tvhdln();
X }
X
X/* =============================>>> RMVLST <<<============================= */
X int rmvlst()
X { /* rmvlst - delete the previous thing found or manipulated
X length of oldlen is set by insert, find, and save
X may also use savlen if set by save */
X
X SLOW int oldech;
X static int rmv_set[] =
X {
X VSEARCH, VNEXT, VSAVE, VGET, VSAGAIN, VSAPPEND, VSAPPEND,
X VMVWORD, VMVBWORD, 0
X };
X
X if (!inset(oldlex,rmv_set))
X return (FALSE);
X
X if (savlen > 0)
X {
X if (curlin == nxtlin-1 && slastl != 0)
X {
X --savlen; /* reduce the count */
X if (savlen > 0)
X {
X oldech = echof;
X echof = FALSE;
X killin(-savlen); /* kill off previous lines */
X echof = oldech;
X }
X killin(1); /* kill the last line */
X }
X else
X killin(-savlen); /* kill off savlen lines */
X }
X else if (oldlen != 0)
X {
X if (! delnxt(-oldlen))
X return (FALSE);
X }
X oldlen = 0; /* don't allow multiple deletes! */
X savlen = (-1);
X return (TRUE);
X }
X
X/* =============================>>> SAVE <<<============================= */
X int save(cnt,app)
X int cnt,app;
X { /* save - save cnt lines in save buffer */
X
X SLOW int l,lend;
X SLOW BUFFINDEX from;
X
X if (curlin == nxtlin-1 && slastl!=0)
X {
X tverrb("Can't save last line twice! ");
X return (FALSE);
X }
X if (cnt < 0)
X return (FALSE);
X
X oldlen = 0; /* use savlin instead */
X
X if ((oldlex != VSAVE && !app) || cnt == 0)
X { /* if new save, cnt == 0 and not appending */
X slastl=0;
X savlin=0; /* haven't saved anything */
X savlen=0;
X nxtsav=mxbuff; /* start saving at end */
X if (cnt == 0)
X {
X return (TRUE);
X }
X }
X
X if (oldlex != VSAPPEND && app) /* need to reset count for append */
X savlen=0;
X
X lend=min(curlin+cnt-1 ,nxtlin-1);
X for (l=curlin; l <= lend ; ++l)
X {
X if (nxtsav-nxtchr < ALMOSTOUT) /* make space if need and can */
X if (!gbgcol() || (nxtsav-nxtchr) < ALMOSTOUT)
X {
X tverrb("No save room ");
X return (FALSE);
X }
X
X from = *(lines+l)+1; /* first character of the line */
X do
X {
X *(buff+nxtsav--) = *(buff+from++);
X }
X while (*(buff+from-1)!=ENDLINE);
X ++savlin; /* keep track of the length */
X ++savlen; /* savlen for rmvlst */
X if (curlin==nxtlin-1) /* don't save last line twice! */
X {
X slastl=1;
X break;
X }
X dwnlin(1); /* move to next line on screen for + only */
X }
X return (TRUE);
X }
X
X/* =============================>>> SEARCH <<<============================= */
X search(lexcnt,iarg)
X int lexcnt,iarg;
X { /* search - search down in buffer for a patter */
X
X#define SEARCHEND (-30)
X SLOW char chr,c0,c1,c2;
X static int slines;
X SLOW int oldx,oldy,oldlin;
X SLOW int change, searchv, lininc, newln, fold_wild;
X SLOW int l,lbeg,is;
X SLOW BUFFINDEX ib, bbeg, oldpos, nbbeg;
X FAST int i;
X
X SLOW int how_match, set_len; /* how wild card matching happens */
X char *cp, *s_getset();
X SLOW int w_len,inset,extra_len; /* length of match */
X
X static int lastsb = 0;
X
X lininc = (lexcnt >= 0 ) ? 1 : (-1);
X searchv = FALSE;
X newln = FALSE; /* haven't rubbed out 2nd line */
X
X oldpos = curchr; /* need to remember for -f */
X oldx = tvx ; oldy = tvy ; oldlin = curlin;
X
X ins_mode = TRUE; /* so ttymode can echo right */
X
X if (! iarg)
X goto l100; /* get arg form search buffer */
X
X tvmsg("Find?",FALSE);
X
X if (! grptch(&chr))
X goto l9000;
X
X slines=1; /* only one line so far */
X for (i = 0; chr != ESC && i < 100; ++i) /* read in the pattern */
X {
X if (chr == delkey && rptcnt[rptuse] <= 0) /* edit interactive input */
X {
X --i; /* adjust i for for loop ++i */
X if (i >= 0) /* wipe out chars on screen */
X {
X if (sbuff[i] == 0) /* newline */
X {
X --slines; tvcout(CR); newln = TRUE;
X#ifdef USELF
X tvcout(LF);
X#endif
X }
X else
X {
X if (newln)
X {
X tvcout('\\');
X ctrlch(sbuff[i]);
X }
X else
X {
X tvcout(BACKSPACE);
X tvcout(' ');
X tvcout(BACKSPACE);
X if (sbuff[i] < ' ' && sbuff[i] != 27)
X {
X tvcout(BACKSPACE);
X tvcout(' ');
X tvcout(BACKSPACE);
X }
X }
X }
X --i; /* wipe the character */
X }
X gkbd(&chr); /* get new char */
X continue;
X }
X sbuff[i]=chr; /* stuff it away */
X if (chr == LF)
X {
X#ifdef USELF
X tvcout(chr); /*$$$ to ignore lfs in cr/lf systems */
X#endif
X }
X else if (chr == CR)
X {
X if (rptcnt[rptuse] <= 0)
X tvcout(chr);
X#ifdef USELF
X tvcout(LF); /*$$$ when needed */
X#endif
X ++slines;
X sbuff[i]=0; /* end of a line */
X }
X else
X ctrlch(chr); /* echo character, handline control chars */
X
X/*# fetch the next character */
X if (! grptch(&chr))
X goto l9000;
X }
X
X tvcout('$'); /* echo the escape */
X tvxy(oldx,oldy); /* return to old location */
X
X if (i>0) /* we got a new pattern */
X {
X lastsb=i-1; /* last valid character */
X sbuff[i] = 0; /* make sure an EOS */
X }
X fixend();
X
Xl100:
X extra_len = 0;
X if (lininc < 0)
X endlin();
X bbeg = curchr; /* start from current character first time */
X c0 = sbuff[0]; /* initial char of pattern */
X if (!xcases) /* get initial character of pattern */
X c0 = (c0 >= 'A' && c0 <= 'Z') ? c0+' ' : c0;
X
X for (l = curlin ; l < nxtlin && l ; l += lininc) /* l is same as l != 0 */
X {
X if ( !c0 ) /* !c0 same as c0 == 0 */
X {
X if (lastsb == 0) /* matching cr only? */
X {
X dwnlin(1); /* go down one line */
X newscr(); /* screen needs updating */
X goto l8000;
X }
X else
X {
X for (ib = bbeg; *(buff+ib); ++ib)
X ;
X goto l1000;
X }
X }
X
Xl900:
X if (c0 < ' ') /* save time, check if might be w.c. once */
X {
X ib = bbeg;
X if (*(buff+ib))
X goto l1000;
X }
X
X for (ib=bbeg; *(buff+ib); ++ib) /* search current line */
X {
X c2 = *(buff+ib); /* next char of buffer */
X if (!xcases)
X c2 = (c2 >= 'A' && c2 <= 'Z') ? c2+' ' : c2;
X
X if (c2 != c0)
X continue; /* first characters don't match */
X else if (lastsb == 0)
X { /* one character pattern */
X curchr = ib+1;
X curlin = l;
X goto l5000; /* successful match */
X }
X else
X {
X if ((c1 = sbuff[1]) < ' ') /* possible wild? */
X goto l1000;
X c2 = *(buff+ib+1);
X if (! xcases) /* fold to lower case */
X {
X c1 = (c1 >= 'A' && c1 <= 'Z') ? c1+' ' : c1;
X c2 = (c2 >= 'A' && c2 <= 'Z') ? c2+' ' : c2; /* clower */
X }
X if ( c1 != c2 )
X continue; /* first two don't match */
X else
X goto l1000; /* first two match, so possibility */
X }
X }
X
X/* # fall thru => no match on this line */
Xl950:
X bbeg = *(lines+l+lininc)+1; /* next beginning character */
X continue; /* go check next line */
X
Xl1000: /* we have two characters matching! */
X nbbeg = ib; /* beginning of possible match in buff */
X lbeg = l; /* current line we are searching */
X how_match = 1; /* assume exact match */
X for (is = -1 ; ++is <= lastsb ; )
X {
X if ((c1 = sbuff[is]) < ' ') /* possible wild card */
X {
X if (c1 == W_span)
X {
X extra_len--;
X how_match = 2; /* span match */
X continue; /* keep scanning search pat */
X }
X else if (c1 == W_skip) /* skip? */
X {
X extra_len--;
X how_match = 0; /* skip match */
X continue; /* keep scanning search pat */
X }
X else if ((cp = s_getset(c1,&set_len,&fold_wild)) == NULL) /* not wild */
X goto NOT_WILD; /* continue normally */
X
X /* ok, to here, then have possible wild card match */
X
X w_len = 0;
X
X for ( ; ; )
X {
X chr = *(buff + nbbeg); /* pick up char */
X if (fold_wild) /* fold if not user */
X chr = clower(chr);
X if (chr == ENDLINE) /* break on end of line */
X break; /* get out */
X
X inset = s_inset(chr,cp,set_len); /* see if in set */
X if ((how_match > 0 && inset) || (how_match == 0 && !inset))
X {
X nbbeg++; /* bump to next char */
X ++w_len;
X if (how_match == 1)
X break; /* only once on mode 1 */
X }
X else
X break;
X }
X
X if (w_len <= 0)
X {
X ++bbeg; /* this part of line doesn't match */
X extra_len = 0;
X if (c0 == 0)
X goto l950;
X else
X goto l900; /* try rest of current line */
X }
X
X /* to here, then exit from wild card match */
X extra_len += w_len - 1;
X how_match = 1; /* back to 1 again */
X continue; /* leave cursor on 1st unmatched */
X }
X
XNOT_WILD:
X c2 = *(buff+nbbeg);
X if (! xcases) /* fold to lower case */
X {
X c1 = (c1 >= 'A' && c1 <= 'Z') ? c1+' ' : c1;
X c2 = (c2 >= 'A' && c2 <= 'Z') ? c2+' ' : c2; /* clower */
X }
X
X if ( c1 != c2 )
X {
X extra_len = 0;
X ++bbeg; /* this part of line doesn't match */
X if (c0 == 0)
X goto l950;
X else
X goto l900; /* try rest of current line */
X }
X
X /* regular matched sequence */
X
X if (*(buff+nbbeg)==0 && lbeg+1 < nxtlin)
X {
X ++lbeg;
X nbbeg = *(lines+lbeg)+1; /* point to next character */
X }
X else
X ++nbbeg;
X }
X
X/*# fall through => found the pattern */
X curlin = lbeg;
X curchr = nbbeg;
X
Xl5000:
X change = curlin-oldlin; /* compute real line change */
X if ((slines > 1 && iarg) || tvdlin == tvlins || newln)
X newscr();
X else
X update(change);
X goto l8000;
X }
X curchr = oldpos; /* reset things */
X tvxy(oldx, oldy);
X if (slines > 1 && iarg)
X newscr(); /* patch up screen */
X pat_buff[0] = 0;
X tverrb("Not found "); /* announce failure a little */
X goto l9000;
X
Xl8000: /* success return */
X oldlen = lastsb+1+extra_len; /* remember the length */
X save_pat(); /* save the find pattern */
X savlen = (-1); /* haven't saved lines */
X searchv = TRUE;
X
Xl9000:
X ins_mode = FALSE;
X return (searchv);
X }
X
X/* =============================>>> S_GETSET <<<============================= */
X char *s_getset(wildchr,set_len,fold)
X char wildchr; /* wild card character */
X int *set_len, *fold; /* length of set, fold flag */
X {
X static char sets[] = /* possible sets */
X {
X 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
X 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
X 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
X '4', '5', '6', '7', '8', '9', '.', ',', '?', '!',
X '[', ']', '{', '}', '(', ')', '<', '>', '\'','"',
X '+', '-', '/', '*', '=', '@', '#', '$', '%', '^',
X '&', '_', '~', '`', '|', '\\', ' ', 9, ';', ':', 0
X };
X
X struct wild_set
X {
X char wch;
X int s_start, s_len;
X };
X
X static struct wild_set wild_cards[] =
X {
X { W_letter, 0, 26 }, /* ^L is a letter, starts at 0, 26 long */
X { W_digit, 26, 10 }, /* ^D is digit, starts at 26, 10 long */
X { W_alpha, 0, 36 }, /* ^A is alpha numeric, start at 0, 36 long */
X { W_punc, 36, 4 }, /* ^P is punctuation, at 36, 4 long */
X { W_anything, 0, 70 }, /* ^X is any thing, whole set */
X { W_others, 36, 34 }, /* ^O is non-alphanum, start at 36, 32 long */
X { 0 , 0, 0 } /* end of set */
X };
X
X SLOW int i;
X
X *fold = FALSE; /* assume won't fold */
X if (!use_wild)
X return NULL; /* not there if not using! */
X
X for (i = 0 ; wild_cards[i].wch ; ++i) /* scan list */
X {
X if (wildchr == wild_cards[i].wch) /* found the one we want */
X {
X *set_len = wild_cards[i].s_len;
X *fold = TRUE;
X return (&sets[ wild_cards[i].s_start ]);
X }
X }
X if (wildchr == W_user)
X {
X *set_len = strlen(user_set);
X return user_set;
X }
X else
X return NULL;
X
X }
X
X/* =============================>>> S_inset <<<============================= */
X s_inset(c2,cp,set_len)
X char c2, *cp;
X int set_len;
X {
X FAST int i;
X
X for (i = 0 ; i < set_len ; ++i)
X if (c2 == *(cp+i))
X return TRUE;
X return FALSE;
X }
X
X/* =============================>>> SETPAR <<<============================= */
X setpar(val)
X int val;
X { /* setpar - reset varoius parameters
X syntax for setpar is [val]:<let>, where [val] is the new value
X of the parameter, : is the setpar command, and <let> is the
X letter of the parameter to set. */
X
X static char chr;
X
X if (! grptch(&chr))
X return;
X chr = clower(chr);
X
X switch (chr)
X {
X case 'a': /* set auto indent */
X autoin = val > 0;
X break;
X
X case 'e': /* expand tabs */
X tabspc = max(val,0);
X verify(1); /* need to redisplay */
X break;
X
X case 'd': /* display line */
X if (val < 1 || val > tvlins)
X tverrb("Bad par val");
X else
X {
X dsplin=val;
X verify(1);
X }
X break;
X
X case 'f': /* set find mode */
X xcases = val <= 0;
X break;
X
X case 'm': /* match wild cards */
X use_wild = val;
X break;
X
X case 'o':
X if (rdonly)
X {
X tverrb("Can't :o, R/O");
X break;
X }
X tvclr();
X ask("New output file name: ",dest_file,FNAMESIZE);
X if (*dest_file)
X {
X expand_name(dest_file); /* expand output name as needed */
X rdonly = FALSE;
X }
X verify(1);
X break;
X
X case 's': /* scroll lines */
X if (val < 0 || val > dsplin-1)
X tverrb("Bad par val");
X else
X scroll=val;
X break;
X
X case 't': /* tty mode */
X tvclr();
X ttymode = val;
X ttynext = 1000;
X verify(1);
X break;
X
X case 'r': /* change repeat buffer in use */
X if (val < 1 || val > REPEATBUFS)
X tverrb("Bad par val");
X else
X rptuse=val-1; /* adjust for 0 index int */
X break;
X
X case 'u':
X tvclr();
X ask("Enter user wild card set: ",user_set,39);
X verify(1);
X break;
X
X case 'v': /* virtual window size */
X if (val < 3 || val > tvhardlines)
X tverrb("Bad par val");
X else
X {
X tvlins = val; /* set to new display line */
X ddline = (tvlins / 2) + 1; /* fix home line */
X setdscrl(); /* set scroll value */
X dsplin = ddline; /* reset these */
X scroll = dscrl;
X verify(1); /* update the screen */
X }
X break;
X
X case 'w': /* change wrap width */
X wraplm=val;
X break;
X
X default:
X tverrb("Bad par name");
X }
X }
X
X/* =============================>>> SNEXT <<<============================= */
X snext(lexcnt,iarg)
X int lexcnt,iarg;
X { /* snext - find a text pattern across page boundaries */
X
X SLOW int ihow,pagout;
X
X if (lexcnt < 0)
X {
X tverrb("Search fails");
X return (FALSE);
X }
X
X ihow=iarg; /* make a local copy */
X pagout=FALSE;
X for(;;)
X {
X if (! search(lexcnt,ihow))
X {
X wtpage(1); /* write out current page */
X ihow=FALSE; /* don't reread search pattern */
X pagout=TRUE;
X if (! rdpage())
X {
X tvclr(); /* no more text */
X tverrb("Search fails");
X return (FALSE);
X }
X }
X else /* found it */
X {
X if (pagout)
X newscr();
X return (TRUE);
X }
X }
X }
X
X/* =============================>>> STORE_RPT <<<============================= */
X store_rpt(dummy)
X int dummy;
X { /* start at current cursor position, insert into repeat buffer
X identified until find >$$ or exceed size limit, deleting as it goes */
X
X SLOW char chr;
X SLOW int saved, i, val;
X
X beglin(); /* start by moving to beginning of current line */
X
X if ((chr = *(buff+curchr)) != '#') /* get current char, which must be # */
X {
X tverrb("Not a valid rpt buff");
X return (FALSE);
X }
X val = *(buff+curchr+1)-'0'; /* pick up buffer number */
X
X if (!chk_rpt_nr(val))
X return FALSE;
X
X delnxt(4); /* delete the #n:< */
X
X --val; /* change to relative */
X
X saved = 0; /* no previous chars */
X for (i = 0 ; ; ++i)
X {
X chr = *(buff+curchr); /* get the character */
X
X if (chr == ESC && i > 1 && rptbuf[val][i-1] == ESC &&
X rptbuf[val][i-2] == SLOOPEND)
X {
X rptbuf[val][i-1] = 0; /* set to 0 */
X lstrpt[val] = i - 2;
X nxtrpt[val] = 0;
X delnxt(2); /* delete the 27 and following CR */
X return TRUE;
X }
X if (++saved > 99)
X {
X tverrb("Only 100 chars in rpt");
X return FALSE;
X }
X if (chr == ENDLINE)
X chr = CR;
X rptbuf[val][i] = chr; /* save the char */
X delnxt(1); /* and delete it */
X }
X
X }
X
X/* =============================>>> SVKLIN <<<============================= */
X svklin(lin)
X int lin;
X { /* svklin - save one line that will be killed */
X
X SLOW BUFFINDEX from,to;
X
X to=0;
X for (from= *(lines+lin)+1; *(buff+from)!=ENDLINE; ++from)
X {
X unkbuf[to]= *(buff+from); /* put it in unkill buffer */
X to = min(130,to+1);
X }
X unkbuf[to]=0;
X }
X
X/* =============================>>> TOPPAG <<<============================= */
X toppag()
X { /* toppag - move cursor to top of the page */
X
X curlin=1;
X curchr = *(lines+1)+1; /* first char of buffer */
X newscr();
X }
X
X/* =============================>>> TVIDEFS <<<============================= */
X tvidefs()
X { /* initialize these AFTER opening, defaults set by -c */
X
X dsplin=ddline;
X scroll=dscrl;
X xcases=dxcase;
X }
X
X/* =============================>>> TVINIT <<<============================= */
X tvinit()
X { /* perform initializations needed for tv edit */
X
X FAST BUFFINDEX i;
X FAST char *chrp;
X SLOW char *lim;
X char *malloc();
X
X#ifdef MSDOS
X BUFFINDEX coreleft(); /* !!! cii-86 dependent */
X#endif
X
X/* This is a time eater if a big buffer -- if your loader inits
X mem to some known value, it might be possible to change GARBAGE
X to that value (be sure no other conflicts, like EOS == 0) */
X
X/* try for maximum size buffer */
X
X#ifndef GEMDOS
X if ((lines = (BUFFINDEX *) malloc((MAXLINE+1)*sizeof(BUFFINDEX)))
X == NULL) /* line pointer array */
X exit(1);
X#else
Xif ((lines=(BUFFINDEX *)malloc((unsigned int)((MAXLINE+1)*sizeof(BUFFINDEX))) )
X == NULL) /* line pointer array */
X exit(1);
X#endif
X
X#ifdef UNIX
X for (mxbuff=MAXBUFF ; (buff = malloc(mxbuff+2))==NULL ; mxbuff -= 1000)
X ; /* text buffer pointer */
X#endif
X#ifdef CPM
X for (mxbuff=MAXBUFF ; (buff = malloc(mxbuff+2))==NULL ; mxbuff -= 1000)
X ; /* text buffer pointer */
X#endif
X#ifdef GEMDOS
X for (mxbuff = 60000L ; (buff = malloc((unsigned int) (mxbuff+2)))==NULL
X ; mxbuff -= 1000L)
X ; /* text buffer pointer */
X#endif
X#ifdef MSDOS /* *** Cii-86 C compiler dependent! */
X
X /* cii-86 requires you to manually leave some memory left over
X for the I/O routines to use. Sigh. */
X
X if ((mxbuff = (coreleft() - 4000) ) > MAXBUFF)
X mxbuff = MAXBUFF;
X for ( ; (buff = malloc(mxbuff+2))==NULL ; mxbuff -= 1000)
X ; /* text buffer pointer */
X#endif
X
X mxline = MAXLINE;
X
X lim = buff + mxbuff;
X for (chrp = buff ; chrp <= lim ; *chrp++ = GARBAGE )
X ; /* mark as all garbage */
X
X curlin = /* init some stuff */
X oldlen =
X curchr = 0;
X
X xoutcm = leftmg = nxtlin = nxtchr = tvdlin = 1;
X *(buff+mxbuff)=0; /* needs to be null for save buffer */
X nxtsav=mxbuff; /* point to end of the buffer */
X
X pat_buff[0] = 0; /* null pattern buffer */
X
X
X savlin = savlen = (-1);
X for (i = 0 ; i < REPEATBUFS ; ++i)
X { /* fix repeat buffers to initial state */
X rptcnt[i]= nxtrpt[i] = lstrpt[i] = rptbuf[i][1] = 0;
X rptbuf[i][0]=SLOOPEND;
X }
X rptuse=0; /* start with first repeat buff */
X bakflg = FALSE;
X ineof =
X echof = TRUE;
X }
X
X/* =============================>>> TVERR <<<============================= */
X tverr(str)
X char str[];
X { /* tverr - display an error message on the last line of the screen
X always writes on screen, returns to old position */
X
X SLOW int oldx,oldy,oldxot,oldech;
X
X waserr = TRUE;
X oldx=tvx ; oldy=tvy ; oldxot=xoutcm ; oldech=echof;
X
X ttynext = 1000; /* force new read */
X
X echof = TRUE; /* always echo! */
X tvmsg(str,TRUE); /* print the message part */
X tvxy(oldx,oldy);
X xoutcm=oldxot;
X echof=oldech; /* restore to what it was */
X }
X
X/* =============================>>> TVERRB <<<============================= */
X tverrb(str)
X char str[];
X { /* tverrb - display an error message on the last line of the screen
X always writes on screen, returns to old position */
X
X sendcs(cerrbg);
X tverr(str);
X sendcs(cerred);
X }
X
X/* =============================>>> TVHDLN <<<============================= */
X tvhdln()
X { /* tvhdln - home to display line */
X
X SLOW int xf;
X xf = findx();
X tvxy(xf,tvdlin);
X }
X
X/* =============================>>> TVMSG <<<============================= */
X tvmsg(str,intty)
X char str[];
X int intty;
X { /* tvmsg - display a message on the last line of the screen */
X
X FAST int i;
X SLOW int oldtty;
X
X tvxy(1,tvhardlines);
X tvelin();
X
X oldtty = ttymode;
X if (ttymode && intty)
X {
X ttymode = FALSE;
X prompt(">");
X }
X
X for (i=0; str[i]; ctrlch(str[i++]))
X ;
X
X if (oldtty) /* end with < if was ttymode */
X remark("<");
X
X ttymode = oldtty;
X }
X
X/* =============================>>> TVTYLN <<<============================= */
X tvtyln(chrptr)
X BUFFINDEX chrptr;
X { /* tvtyln - type a line on the screen without cr/lf */
X
X#ifdef ULBD
X FAST BUFFINDEX i;
X
X if (cundlb[0] || cboldb[0]) /* check for underline/bold */
X {
X for (i = *(lines+curlin)+1 ; *(buff+i)!=ENDLINE ; ++i)
X if (*(buff+i)==TOGUNDERLINE || *(buff+i)==TOGBOLD)
X {
X tvxy(1,tvy);
X xoutcm=1;
X tvplin(*(lines+curlin)+1);
X return;
X }
X }
X#endif
X xoutcm=tvx;
X tvplin(chrptr);
X }
X
X/* =============================>>> UNKILL <<<============================= */
X int unkill()
X { /* unkill the single last line killed */
X
X SLOW char chrval;
X FAST int i;
X
X for (i=0; unkbuf[i]; ++i)
X {
X chrval=unkbuf[i];
X if (! ins_chr(chrval)) /* unkill slowly by using insert */
X {
X return (FALSE);
X }
X }
X return (ins_chr(CR));
X }
X
X/* =============================>>> UPDATE <<<============================= */
X update(change)
X int change;
X { /* update - update the screen when line position has changed
X will not be used if any alterations have been made */
X
X SLOW int abschg,bscrol;
X
X if (! echof)
X return;
X abschg = change;
X
X bscrol = (ctopb[0]==0) ? 0 : scroll;
X
X if (change < 0) /* have to scroll screen down */
X {
X abschg = (-change);
X if (tvdlin-abschg < 1)
X newscr();
X else if (curlin < tvdlin) /* won't fit exactly */
X {
X if (tvdlin >= dsplin-scroll && abschg!=1)
X {
X tvclr(); /* clear the screen */
X tvtype(1,tvlins); /* type out a screen */
X }
X tvdlin=curlin;
X }
X else if (tvdlin-abschg >= dsplin-scroll)
X tvdlin -= abschg;
X else
X {
X if (tvdlin > dsplin-scroll)
X { /* moving up from below display line */
X abschg=dsplin-scroll-(tvdlin-abschg);
X tvdlin=dsplin-scroll; /* update */
X }
X if (ctopb[0]==0) /* can't do reverse linefeeds */
X newscr(); /* no choice, redraw screen */
X else
X {
X tvtopb(abschg); /* make blank lines at top */
X tvtype(curlin-tvdlin+1,abschg); /* fill in */
X }
X }
X }
X else if (change > 0) /* have to scroll screen up */
X if ((tvdlin+change>tvlins && tvdlin<dsplin+bscrol) || change>=tvlins)
X newscr();
X else if (tvdlin < dsplin+bscrol || nxtlin-1 <= tvlins)
X if (tvdlin+change > dsplin+bscrol && nxtlin-1 > tvlins)
X newscr();
X else
X tvdlin += change;
X else if (nxtlin-curlin<=tvlins-tvdlin) /* on bottom part */
X {
X if (tvdlin<=dsplin+bscrol && abschg!=1)
X {
X tvclr(); /* rewrite whole screen */
X tvtype(nxtlin-tvlins,tvlins);
X }
X tvdlin=min(tvlins,nxtlin-1)-(nxtlin-curlin)+1;
X }
X else
X {
X tvbotb(abschg); /* make room */
X tvxy(1,tvlins-abschg+1); /* home to right line */
X tvtype(curlin+tvlins-tvdlin-abschg+1,abschg); /* fix up screen */
X if (tvdlin < dsplin+bscrol)
X tvdlin=dsplin;
X }
X tvhdln();
X }
X
X/* =============================>>> WORDR <<<============================= */
X wordr(cnt)
X int cnt;
X { /* wordr - move cursor over words */
X
X SLOW int lim,words,incr,lenmov;
X
X lenmov=0;
X if (cnt<0)
X {
X incr = (-1); /* change */
X lim = (-cnt);
X }
X else if (cnt == 0)
X {
X incr = -1;
X lim = 0;
X }
X else
X {
X incr = 1;
X lim = cnt;
X }
X
X for (words=1; words<=lim; ++words)
X {
X if ((*(buff+curchr)==ENDLINE && incr>0) ||
X (*(buff+curchr-1)==BEGLINE && incr<0) )
X {
X if (curlin+incr==nxtlin || curlin+incr<1)
X break; /* at a buffer limit, so quit */
X dwnlin(incr); /* move up or down */
X lenmov += incr;
X if (cnt<0)
X endlin();
X continue; /* move to next word */
X }
X
X/* ok, first, skip over word characters */
X while (wrdchr(*(buff+curchr)))
X {
X if (*(buff+curchr-1)==BEGLINE && incr<=0)
X goto l100;
X else
X {
X curchr += incr;
X lenmov += incr;
X }
X }
X
X/* now skip over remaining non word chars */
X while (! wrdchr(*(buff+curchr)))
X {
X if ((*(buff+curchr)==0 && incr>0) || (*(buff+curchr-1)==BEGLINE &&
X incr<0))
X break;
X else
X {
X curchr += incr;
X lenmov += incr;
X }
X }
Xl100: ;
X }
X
X if (incr < 0) /* move cursor to beginning of word */
X while (wrdchr(*(buff+curchr-1)))
X {
X curchr += incr;
X lenmov += incr;
X }
X tvhdln();
X oldlen = lenmov ; savlen=(-1) ;
X }
X
X/* =============================>>> WRDCHR <<<============================= */
X int wrdchr(chr)
X char chr;
X { /* wrdchr - determine if a character is a "word" type character */
X
X if ((chr>='a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') ||
X (chr >= '0' && chr <= '9'))
X return (TRUE);
X else
X return (FALSE);
X }
X/* -------------------------------- tvx_2.c ------------------------------- */
SHAR_EOF
echo ALL DONE!
exit 0
More information about the Comp.sources.unix
mailing list