sources-request@panda.UUCP (03/10/86)
Mod.sources: Volume 4, Issue 18 Submitted by: gatech!unmvax!wampler (Bruce Wampler) #--------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/* ======================================================================== X X TVX - A full screen editor in C X XOriginally 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 | ihnp4!lanl | seismo!gatech}!unmvax!wampler X X X This version of TVX Copyright (c) 1986 by Bruce E. Wampler X X Permission is hereby granted for free, unrestricted nonprofit X use of this software. Please feel free to modify, distribute, X and share this software as long as you aren't making any money X from it. If you want to use this code in a profit making environment, X please contact the author for permission. X X X Direct comments, bug reports, suggestions to X Bruce Wampler at above address. X XConverted 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 So it goes. X XPLEASE! 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 If possible, put your changes in #ifdefs so they can be X incorporated into the master source easily if appropriate. X XDescription 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_EDIT.C - all emulator version dependent code here. 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 char clower(),cupper(); 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#ifdef SCR_BUF X ttflush(); X#endif 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#ifdef SCR_BUF X ttflush(); X#endif 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 if (dsp_mem) X tvelin(); 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#ifdef SCR_BUF X ttflush(); X#endif X } X X/* =============================>>> DELNXT <<<============================= */ X int delnxt(cnt) X int cnt; X { /* delnxt - delete next n characters */ X 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 > 0) ? cnt : (-cnt); /* remember absolute value of cnt */ X if (abscnt > 100) /* make sure about this! */ X { /* they probably meant kill lines! */ X tvclr(); X ask("Kill that many chars? (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 && cdelchr[0]) X sendcs(cdelchr); X else X { 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#ifdef SCR_BUF X ttflush(); X#endif X return (TRUE); 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#ifdef SCR_BUF X ttflush(); X#endif 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, old_ef; X X X if (!chk_rpt_nr(val)) X return FALSE; X X old_ef = echof; echof = 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((int)'#'); ins_chr((int)val+'1'); ins_chr((int)':'); X /* start with number */ X ins_chr((int)loop_beg); /* insert start of repeat loop */ X X for (cp = &rptbuf[val][0] ; *cp ; ++cp) X ins_chr((int)*cp); X ins_chr((int)loop_end); X ins_chr((int)27); ins_chr((int)27); /* make a way for store_rpt to find end */ X X ins_chr((int)CR); /* terminate line */ X curlin = start_line; X curchr = *(lines+curlin)+1; X X echof = old_ef; X X verify(1); X#ifdef SCR_BUF X ttflush(); X#endif X return (TRUE); 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#ifdef SCR_BUF X ttflush(); X#endif 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 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) % tabspc)!=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#ifdef SCR_BUF X ttflush(); X#endif X } X X/* =============================>>> FOLDCASE <<<============================= */ X foldcase(cnt) X int cnt; X { X /* fold from upper to lower or lower to upper case if letter */ X SLOW int ni; X SLOW char fchr; X X for (ni = 0 ; ni < cnt ; ++ni) X { X fchr = *(buff+curchr); /* get current character */ X if (fchr >= 'a' && fchr <= 'z') X fchr = cupper(fchr); X else if (fchr >= 'A' && fchr <= 'Z') X fchr = clower(fchr); X if (fchr == ENDLINE) X right(1); X else X { X delnxt(1); /* delete cur character */ X insert((int)fchr,FALSE); /* and put back */ X } X } 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((int)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--)!=ENDLINE); 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 { X if ((*chr=rptbuf[rptuse][nxtrpt[rptuse]]) == 0) X return (FALSE); 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((int)*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 && how) 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 && how) 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 && how) 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#ifdef SCR_BUF X ttflush(); X#endif 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 && how && chr >= ' ') 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#ifdef SCR_BUF X ttflush(); X#endif 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 && how) /* 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#ifdef SCR_BUF X ttflush(); X#endif X return FALSE; X Xl1000: X if (ins_msg && how) X fixend(); X csrcmd(); X#ifdef SCR_BUF X ttflush(); X#endif X return TRUE; X } SHAR_EOF echo Extracting tvx_defs.ic: sed 's/^X//' >tvx_defs.ic <<\SHAR_EOF X/* X TVX - A full screen editor written in C X X This version of TVX Copyright (c) 1986 by Bruce E. Wampler X X Permission is hereby granted for free, unrestricted nonprofit X use of this software. Please feel free to modify, distribute, X and share this software as long as you aren't making any money X from it. If you want to use this code in a profit making environment, X please contact the author for permission. X X Revison summary: (edit ALL cases of VERSION when change) X Version X 1/10/ - this code first released to USENET X 1/29/86 - memory code fixed, changes contained in first fix notice X 1/30/86 - fixed insert mode msg problem in unkill X 2/6/86 - cleaned up atari stdio.h problem, bug with noteloc X 2/11/86 - added required code for Unix System V X 2/14/86 - GETSIO option, allows fgets I/O if faster than fgetc X 2/17/86 - bug in multi-line repeat loop, bug in addfil: ALMOSTOUT X 2/22/86 - vi emulation + modeless version for emacs and tvx0 X 2/25/86 - added SCR_BUF stuff from decvax!gancarz (Mike Gancarz) X 3/6/86 - added hires screen for atari st [released to mod.sources] X X********************************************************************* */ X X X/* ======================================================================== */ X/* Define the editor being emulated: (possibly by -D switch to cc) X X TVX_EM - The original tvx (this really IS tvx) X VI_EM - emulates vi X EMAX_EM - emulates emacs X TVX0M_EM - a tvx flavored modeless editor X*/ X X/* #define TVX_EM */ X/* #define VI_EM */ /* vi emulation */ X/* #define TVX0M_EM */ /* modeless emulation */ X/* #define EMAX_EM */ X X/* ======================================================================== */ X/* ====> Select terminal version: #define at most ONE of <================= */ X/* the following symbols debending the terminal used. (except SUN) */ X X#undef IBMPC X#undef ATARI520 X/* #define VT100 */ X#undef HP2621 X#define TERMCAP /* Unix TERMCAP version */ X/* #define SUN */ /* define for SUN in addition to TERMCAP */ X X X/* ======================================================================== */ X/* ==================> Select ONE operating system <====================== */ X X/* #define OSCPM */ /* CP/M-80 */ X#undef MSDOS /* 8086 MS-DOS */ X#undef GEMDOS /* atari 520 gemdos */ X X/* NOTE: If you define UNIX, please look at the beginning of tvx_unix.c X for additional Unix related options */ X#define UNIX /* unix is a bit different! */ X X/* !!!! following defines used in ADDITION to UNIX if used !!!! */ X/* #define SYSV */ /* define this in ADDITION to UNIX for System V */ X/* #define ULTRIX11 */ /* for DEC PDP-11 Ultrix */ X/* #define PRO350 */ /* DEC PRO-350 system */ X X#define SCR_BUF /* buffered screen update much faster on Unix */ X /* not implemented for other systems yet, but should be easy */ X#define S_BUFSIZE 2048 /* size of screen buffer */ X X/* ======================================================================== */ X X/* the include for stdio.h is here after os has been defined */ X X#ifdef GEMDOS X/* GEMDOS requires that the brain damaged stdio.h provided with the X developer's kit be replaced to get rid of conflicts with the X portab.h file - ugly. A special file called stdiotvx.h is provided X with the atari distribution */ X X#include "stdiotvx.h" X X#else X#include <stdio.h> X#endif X X/* ========> select other options by defining appropriate symbols <======== */ X X#define VB /**/ /* whether or not to create backup log version */ X X#undef ULBD /* supports underline, bold in ^U, ^B format */ X X#define NEED_MISC_DEFS /**/ X/* ======================================================================== */ X#ifdef NEED_MISC_DEFS X/* following definitons are usually not defined in most stdio.h's */ X X#define NIL (-1) /* nil ptr for lists */ X#define TRUE 1 X#define FALSE 0 X X/* following might not be defined in some C's stdio.h, but usually are */ X X/* #define EOF (-1) */ /* standard end of file */ X/* #define EOS '\0' */ /* standard end of string */ X#endif X X/* ********************************************************************** */ X/* ********************************************************************** */ X X/* Other options now selected automatically depending on above #defines */ X X/* ********************************************************************** */ X/* ********************************************************************** */ X X/* ----------------- Emulator Version ----------------------------------- */ X X#ifdef TVX_EM X#define TVX_CMDSET /* command set used by tvx */ X#define START_IDM "TVX - Full Screen Editor" X#define START_HELPM "Press ? for help after starting" X#define VERSION " - TVX (3/6/86) - " X#define DEF_CUTMODE 0 X#endif X X#ifdef VI_EM X#define START_IDM "TVX - Editor emulating vi" X#define VERSION " - VIX (3/6/86) - " X#define START_HELPM "Press = for help after starting" X#define DEF_CUTMODE 1 X X#undef VI_MODS X/* VI_MODS defines some "extensions" or enhancements to vi that X the local users prefer to the way vi does things. Specifically: X 1) j and k become line oriented rather than column oriented. ^P behaves X in the usual up column, and ^N work like the usual down arrow. X 2) r is changed to advance the cursor after the changed char. X*/ X#endif X X#ifdef EMAX_EM X#define NOMODE_LEX X#define START_IDM "EMAX - TVX/EMAX Full Screen Editor" X#define START_HELPM "Press <ESC>? for help after starting" X#define VERSION " - EMAX (3/6/86) - " X#define DEF_CUTMODE 1 X#endif X X#ifdef TVX0M_EM X#define TVX_CMDSET X#define NOMODE_LEX X#define START_IDM "Modeless TVX - Full Screen Editor" X#define START_HELPM "Press <ESC>? for help after starting" X#define VERSION " - TVX/0 (3/6/86) - " X#define DEF_CUTMODE 0 X#endif X X/* ---------------- Operating System dependent defintions --------------- */ X X/* important note: max value for REPEATBUFS is 9! */ X X/* ---------------------------------------------------------------------- */ X#ifdef OSCPM /* uses Software Toolworks C/80 */ X#define BACKUPNAME "BACKUP.LOG" /* backup log file name */ X#define BUFFLIMIT 2500 /* how much empty space to save in buffer */ X#define FILEREAD "rb" /* read a file in binary */ X#define FILEWRITE "wb" /* write a binary file */ X#define FNAMESIZE 14 /* size of file names */ X#define INT16 /**/ /* ints are 16 bits */ X#define LINELIMIT 75 /* number of spare lines to save */ X#define MAKE_BACKUP 1 /* 1 (true), want to make .bak file by default */ X#define MAXBUFF 40000 /* maximum number of total characters */ X#define MAXLINE 1150 /* maximum number of lines (abt. MAXBUFF/30) */ X#define REPEATBUFS 3 /* number of repeat buffers allowed */ X#define USELF /**/ /* using line feed on video */ X#define FILELF /**/ /* also in files */ X#define NEWLINE 13 /* 1st line separator: CR */ X#define USECTRLZ /**/ X#define NEEDTVLIB /**/ /* need standard c lib routines */ X#define BUFFINDEX unsigned int X#define FAST static X#define SLOW static X#endif X X/* ---------------------------------------------------------------------- */ X#ifdef MSDOS X#define HELP /**/ /* help available */ X#define FULLHELP /**/ /* all of it */ X#ifdef TVX_EM X#define CONFIGFILE /**/ /* allow -c switch */ X#endif X#define BACKUPNAME "BACKUP.LOG" /* backup log file name */ X#define BUFFLIMIT 3000 /* how much empty space to save in buffer */ X#define FILEREAD "rb" /* read a file in binary */ X#define FILEWRITE "wb" /* write a binary file */ X#define FNAMESIZE 70 /* size of file names, allows paths */ X#undef GETSIO /* fgets slower than fgetc for cii-86 */ X#define INT16 /**/ /* ints are 16 bits */ X#define LINELIMIT 75 /* number of spare lines to save */ X#define MAKE_BACKUP 1 /* 1 (true), want to make .bak file by default */ X#define MAXBUFF 60000 /* maximum number of total characters */ X#define MAXLINE 3500 /* maximum number of lines (abt. MAXBUFF/30) */ X#define REPEATBUFS 5 /* number of repeat buffers allowed */ X#define USELF /**/ /* using line feed */ X#define FILELF /**/ /* also in files */ X#define NEWLINE 13 /* 1st line separator: CR */ X#define BUFFINDEX unsigned int X/* #define USECTRLZ */ /* default value for ^Z */ X#define FAST static X#define SLOW static X#endif X/* ---------------------------------------------------------------------- */ X/* ---------------------------------------------------------------------- */ X#ifdef GEMDOS X#define HELP /**/ /* help available */ X#define FULLHELP /**/ /* all of it */ X#ifdef TVX_EM X#define CONFIGFILE /**/ /* allow -c switch */ X#endif X#define BACKUPNAME "BACKUP.LOG" /* backup log file name */ X#define BUFFLIMIT 3000 /* how much empty space to save in buffer */ X#define FILEREAD "r" /* read a file in binary */ X#define FILEWRITE "w" /* write a binary file */ X#define fopen fopenb X#define FNAMESIZE 70 /* size of file names, allows paths */ X#define GETSIO /* use fgets for main file I/O */ X#define INT16 /**/ /* ints are 16 bits */ X#define LINELIMIT 75 /* number of spare lines to save */ X#define MAKE_BACKUP 1 /* 1 (true), want to make .bak file by default */ X#define MAXBUFF 60000 /* maximum number of total characters */ X#define MAXLINE 3500 /* maximum number of lines (abt. MAXBUFF/30) */ X#define REPEATBUFS 5 /* number of repeat buffers allowed */ X#define USELF /**/ /* using line feed */ X#define FILELF /**/ /* also in files */ X#define NEWLINE 13 /* 1st line separator: CR */ X#define USECTRLZ /**/ X#define BUFFINDEX long X#define FAST register X#define SLOW static X#endif X/* ---------------------------------------------------------------------- */ X X/* ---------------------------------------------------------------------- */ X#ifdef UNIX X#define getchr fgetc X#define FLOWCONTROL /**/ /* define this if you want ^S/^Q enabled */ X#undef COMMA_BAK /* #define if you want ".," backup files */ X X#define NO_EXTEND_CHAR /* only allow 127 displayable chars */ X X#define HELP /**/ /* help available */ X#define FULLHELP /**/ /* all of it */ X#ifdef TVX_EM X#define CONFIGFILE /**/ /* allow -c switch */ X#endif X#define BACKUPNAME "BACKUP.LOG" /* backup log file name */ X#define BUFFLIMIT 4000 /* how much empty space to save in buffer */ X#define FILEREAD "r" /* read a file in binary */ X#define FILEWRITE "w" /* write a binary file */ X#define FNAMESIZE 80 /* size of file names, allows paths */ X#define GETSIO /* use fgets for main file I/O */ X#define LINELIMIT 100 /* number of spare lines to save */ X#define MAKE_BACKUP 1 /* 1 (true), want to make .B file by default */ X /* change to 0 if don't want, which is like other Unix eds */ X#define MAXBUFF 120000 /* maximum number of total characters */ X#define MAXLINE 5000 /* maximum number of lines (abt. MAXBUFF/30) */ X#define NEWLINE 10 X#define REPEATBUFS 9 /* number of repeat buffers allowed */ X#define USELF /**/ /* using line feed on screen */ X#define BUFFINDEX unsigned int X#define FAST register X#define SLOW /* dynamics */ X#endif X X/* ---------------------------------------------------------------------- */ X X#ifdef ULTRIX11 X#undef MAXBUFF X#undef MAXLINE X#define MAXBUFF 40000 /* maximum number of total characters */ X#define MAXLINE 1150 /* maximum number of lines (abt. MAXBUFF/30) */ X#endif X X/* ---------------------------------------------------------------------- */ X/* ---------------------- Misc defintions ------------------------------- */ X X#define ARB 100 X#define ALMOSTOUT 300 /* garbage collect when ALMOSTOUT characters left */ X#define BACKSPACE 8 X#define BELL 7 /* bell */ X#define CR 13 X#define ESC 27 X#define ENDFILE 26 X#define LF 10 X#define NO 0 X#define TOGUNDERLINE 21 /* ^U for underline */ X#define TOGBOLD 2 /* ^B for bold */ X#define TAB 9 X#define YES 1 X/* these look like they can be changed, but beware, especially X with positive values (you can't change ENDLINE to LF, for example) */ X#define BEGLINE (char)(0xff) X#define ENDLINE 0 /* marks end of a line */ X#define GARBAGE (char)(0xfe) /* filler character for gbgcol */ X X#define E0 0 /* element 0 of arrays (skipped) */ X X/* ---------------------- Wild card values ----------------------------------- */ X#define W_letter 12 /* ^L is letter */ X#define W_digit 4 /* ^D is digit */ X#define W_alpha 1 /* ^A is alpha num */ X#define W_punc 16 /* ^P is punctuation */ X#define W_anything 24 /* ^X is any character */ X#define W_others 15 /* ^O is non-alpha */ X#define W_user 21 /* ^U is user set */ X#define W_span 23 /* ^W is "word" of */ X#define W_skip 14 /* ^N is not in word of*/ X/* -------------------- Command Definitions ----------------------------- */ X X#ifdef TVX_CMDSET /* both 2 mode and modeless tvx use the same */ X#define VRIGHT 1 /* lex val right, or foward one character */ X#define VLEFT 2 /* left or backwards one character */ X#define VDOWNLINE 3 /* down line, to beg. of next line */ X#define VUPLINE 4 /* up line, to beg. of prev. line */ X#define VDOWNCOL 5 /* down in column ^D */ X#define VUPCOL 6 /* up in column ^U */ X#define VDELLAST 7 /* delete previous character */ X#define VDELNEXT 8 /* delete forward */ X#define VINSERT 9 /* insert text */ X#define VKILLALL 10 /* kill entire current line */ X#define VKILLREST 11 /* kill rest of current line */ X#define VKILLPREV 12 /* kill previous part of line */ X#define VBEGLINE 13 /* beginning of current line */ X#define VENDLINE 14 /* back of current line */ X#define VSEARCH 15 /* find a string */ X#define VNEXT 16 /* next - search across pages */ X#define VFLIP 17 /* page a screen full */ X#define VTOP 18 /* top of buffer */ X#define VBOTTOM 19 /* bottom of buffer */ X#define VFBEGIN 20 /* beginning of file */ X#define VVERIFY 21 /* verify: rewrite screen or show dot */ X#define VOPENLINE 22 /* open a new line */ X#define VREMOVE 23 /* remove last thing maniuplated */ X#define VSAVE 24 /* put text in save buffer */ X#define VGET 25 /* get or restore save buffer */ X#define VWPAGE 26 /* write current page, fetch next page */ X#define VYANK 27 /* "save" from external file */ X#define VQUIT 28 /* quit */ X#define VSAGAIN 29 /* search for the thing again */ X#define VXREPEAT 30 /* execute repeat buffer */ X#define VMEMORY 31 /* print remaining buffer space */ X#define VSETPARS 32 /* set parameters */ X#define VRMVINS 33 /* remove last, enter insert mode */ X#define VUNKILL 34 /* unkill last line killed */ X#define VMVWORD 35 /* move over a word at a time */ X#define VMVBWORD 36 /* move over words backwards */ X#define VSAPPEND 37 /* append to save buffer */ X#define VPRINTS 38 /* print screen */ X#define VHELP 39 /* show contents of repeat buffer */ X#define VHALFP 40 /* half a page down */ X#define VABORT 41 /* abort */ X#define VCHANGE 42 /* change n chars */ X#define VJUMP 43 /* jump back to prev loc */ X#define VTIDY 44 /* tidy - justify */ X#define VNOTELOC 45 /* note current location */ X#define VRETNOTE 46 /* ^N - Return to noted loc */ X#define VSYSTEM 47 /* call operating system */ X#define VEDITRPT 48 /* edit repeat buffer n */ X#define VSTORERPT 49 /* store in repeat buffer n */ X#define VEXECRPT 50 /* execute repeat buffer k n time */ X#define VINSPAT 51 /* insert search pattern */ X#define VUSER1 52 /* spare 1 */ X#define VUSER2 53 /* spare 2 */ X#define VFOLDCASE 54 /* fold case */ X#define LEXVALUES 54 /* total number of lexical values */ X#endif X X#ifdef VI_EM /* needed vi_em lexical values */ X#define VMEMORY 4 X#define VHELP 7 X#define VSEARCH 12 X#define VRSEARCH 15 X#define VDOWNCOL 23 X#define VUPCOL 24 X#define VSAPPEND 32 X#define VENDZ 33 X#define VMVBWORD 36 X#define VRSAGAIN 27 X#define VPUT 29 X#define VTVX 30 X#define VSAPPEND 32 X#define VENDZ 33 X#define VMVBWORD 36 X#define VINSERT 40 X#define VNOTELOC 44 X#define VSAGAIN 45 X#define VGET 47 X#define VMVWORD 51 X#define VSAVE 53 X#define VNOOP 50 X X#define LEXVALUES 54 /* total number of lexical values */ X#endif X X#ifdef EMAX_EM X#define VSAVE 100 X#define VSAPPEND 101 X#define VNEXT 102 X#define VSAGAIN 103 X#define VTVX 3 X#define VNOOP 7 X#define VDOWNCOL 11 X#define VUPCOL 13 X#define VOPENLINE 12 X#define VRSEARCH 14 X#define VSEARCH 15 X#define VGET 18 X#define VEXTEND 17 X#define VQUIT 19 X#define VMVBWORD 24 X#define VMVWORD 25 X#define VHELP 27 X X#define LEXVALUES 27 X#endif X X#define UNKNOWN (-5) /* unknown lexical value */ X X/* ********************************************************************* */ SHAR_EOF echo ALL DONE! exit 0