#include "sysdef.h" /* */ /* Copyright Notice */ /* */ /* */ /* C version Copyright (C) 1984 Change Software, Inc. */ /* Copyright (C) 1978 1979 1980 1981 1982 1983 1984 by */ /* Change Software, Inc. */ /* */ /* */ /* This software is furnished under a license and may */ /* be used and copied only in accordance with the */ /* terms of such license and with the inclusion of */ /* the above copyright notice. This software or any */ /* other copies thereof may not be provided or other- */ /* wise made available to any other person. No title */ /* to and ownership of the software is hereby trans- */ /* ferred. */ /* */ /* The information in this software is subject to */ /* change without notice and should not be construed */ /* as a commitment by the author. */ /* */ /* */ #include "scterm.h" #include "tempio.h" #include "scerrd.h" #include "edswdf.h" #define CR 015 #define LF 012 #define INIT_SIZE 500 #if VAXVMS #define INCR_SIZE 1000 #else #define INCR_SIZE 300 #endif /* Modes in which the tempfile updates routines can be in These modes control the 'dirtyness' of a tempfile buffer Stored in INT CURMODE, defined in TEMPIO.H ST_NORMAL_MODE_mode: Do not update disk copy of text window. Access is assumed to be readonly, wwhich for most accesses is true. ST_IFL: Build index sequentially since the index will not be completed yet. Set when the readonly copy of the input file is being read. ST_INSERT: When adding lines, will force updates. ST_UPDATE: Update the text window to the work file. this must be set for any module which wants to alter text in a line. A note about temp file routines In general, the temp file handlers will abort on ANY fatal error. While not terribly gracious, what else is there to do? */ /* Globals that we really only need in this module, however, the structure 'WINDOW' will be referenced just about everywhere we reference a line. */ struct ctx { int laddr ; int lc ; } ; char bigbuffer[_maxlen*2] ; static struct ctx sccontext ; /* for saving context */ struct fswitch inswitch ; /* for input switches */ struct textline inline ; /* a useful line */ int indexsize[NWINDOWS] ; /* save size of virt mem */ int w = 0 ; /* current window number */ int win_low[NWINDOWS] ; /* save screen boundarys */ int win_high[NWINDOWS] ; /* same */ int win_curline[NWINDOWS] ; /* save current line number */ struct textline *w_l_address[_BCK_FIL]; /* pointer to current lines */ struct tempindex *win_workpt[NWINDOWS] ; /* points to workfile index */ struct tempindex *workpt ; /* point to workindex[] */ struct textwindow *windpt ; /* pointer to current bucket */ struct textwindow window[NWINDOWS] ; /* current view into workfile */ struct tempblock tempbuffer[NWINDOWS] ; /* store the current bucket */ struct stats tempstat ; /* update for cache hits */ struct deltype lastdeleted ; int tmpsiz = _tmpsize ; int bck_fil = _bck_fil ; int bck_size= _bck_size ; int maxlen = _maxlen ; int eoferror = ER_EOF ; int tty = _tty ; int ansi = _ansi ; int vt100 = _vt100 ; int vt220 = _vt220 ; int page_size[]={ /* size of the useable display */ 0 , /* tty */ 22 , /* ansi h19 style */ 20 , /* vt100 */ 20 , /* vt220's */ 0 /* future? */ } ; int termtype = 0 ; int matchflag = 0 ; int ffstop = 0 ; int tempopen = 0 ; int iniecho = 0 ; int escprint = 0 ; int leftmargin = 1 ; int rightmargin = 72 ; int read_only = 0 ; int infisize = 0 ; static int ctx_valid = 0 ; int curbucket[NWINDOWS] ; int lstbucket[NWINDOWS] ; int firbucket[NWINDOWS] ; int maxbucket[NWINDOWS] ; int linecount[NWINDOWS] ; int blkoffset[NWINDOWS] ; int win_maxline[NWINDOWS] ; int *maxline ; int lowlim ; int highlim ; int target ; int trimarg ; int filopen ; int dovtedit ; int argstat ; int curmode[NWINDOWS]; int *loclow ; int *lochigh ; int *curline ; int ttpsize ; int verbose = 1 ; int kblun = kb_lun ; int cmdlun= kb_lun ; int inlun = in_lun ; int outlun = out_lun ; int indlun = ind_lun ; int tmp1lun = tmp1_lun ; int tmp2lun = tmp2_lun ; int p_lines = 1 ; int oldstsone = 0 ; int sts_one = 0 ; int sts_two = 0 ; char argfile[_FILESIZE] ; char insource[_FILESIZE]; char worddelim[32] ; int dirindex = 0 ; int stvtedit = 0 ; int restart = 0 ; int waswild = 0 ; int maxfilesize = _FILESIZE ; int filesize = 0 ; int hlpctx[2] ; char *hlbuffer ; int nwindows = NWINDOWS ; char infi1[_FILESIZE] ; char infi2[_FILESIZE] ; #if NWINDOWS-3 char infi3[2] ; #else char infi3[_FILESIZE] ; #endif char *infile[] = { infi1,infi2,infi3 } ; /* Define the mechanism for indexing into the window pointers */ /* First, the fast way for virtual 32 bit systems like VMS. */ #if VAXVMS #define _gworkpt(offset) workpt+offset #endif #if RSX extern struct tempindex *mapwin() ; #define _gworkpt mapwin #endif /* #if RSX #define _gworkpt workpt+ #endif */ /* If we want to use a mapped dynamic region for memory management we can define _gworkpt as follows and write a function to check the mapping and appropiately remap if need be. Doing so will of course require mods to the way getvm is called. Additionally, the editor will run a bit slower due to the over- head involved with procedure calls and mapping the region. This alternative has been defined for possible use in the PDP-11 TED and has NO place being used on VMS (obviously). #define _gworkpt(offset) mapwork(offset) static struct tempindex *mapwork(offset) int offset ; { return( workpt+offset ) ; } */ /* Procedure Ins_Line Ins_line takes the line passed to it and inserts it into the current workfile bucket. Obviously, if the current bucket should become full Ins_Line will process that. For insertions after the initial file load, it is assumed that SAVELN has been called to setup the bucket split to handle this. */ ins_line( line ,size ) char *line; int size; { struct textline detab_buffer ; /* in case removing tabs and such */ register char *lp,*dp ; /* register pointer to the line */ register int i ; int more ; /* some local things */ extern int checkindex(); /* check the index for room */ lp = line ; if ( inswitch.tabxl ) then { lp = detab_buffer.c ; size = detab( lp,line, size ) ; } if ( inswitch.casexl ) then { dp = detab_buffer.c ; for (i=size; i > 0; i-- ) *dp++ = toupper(*lp++) ; lp = detab_buffer.c ; } more = true ; while (more) { curbucket[w] = lstbucket[w] ; if ( linecount[w] == 0 ) then blkoffset[w] = 0 ; if ((linecount[w] == bck_fil) || (blkoffset[w]+size >= bck_size)) then { ins_block(); ins_lnks(); linecount[w] = 0 ; more = true ; } else more = false ; } if ( size != 0 ) then tempbuffer[w].rsize[linecount[w]++] = size ; dp = &tempbuffer[w].txt[blkoffset[w]] ; blkoffset[w] += size ; scopy(dp,lp,size) ; return(SYS_NORMAL) ; } putlast( line,size ) char *line ; int size ; { ins_block(); ins_lnks(); ins_line( line,size ); } ins_block() { register int nxtbucket,done,foundlink; lstbucket[w] = 0 ; if ( curmode[w] == ST_IFL ) then { curbucket[w]++ ; lstbucket[w] = curbucket[w] ; (_gworkpt(lstbucket[w]))->link = lstbucket[w] + 1 ; } else { nxtbucket = 1 ; done = ( nxtbucket > maxbucket[w] ) ? true:false ; while (done == false ) { lstbucket[w] = nxtbucket ; if ( (_gworkpt(nxtbucket))->lcount != 0 ) then { nxtbucket++ ; foundlink = false ; done = ( nxtbucket > maxbucket[w] ) ? true:false ; } else { done = true ; foundlink = true ; } } if ( foundlink == false ) then { maxbucket[w] = nxtbucket ; lstbucket[w] = nxtbucket ; } (_gworkpt(nxtbucket))->link=(_gworkpt(curbucket[w]))->link; (_gworkpt(curbucket[w]))->link = nxtbucket ; (_gworkpt(nxtbucket))->lcount = -1 ; } /* end else */ } ins_lnks() { register int i,nchars,status ; (_gworkpt(curbucket[w]))->lcount = linecount[w] ; nchars = 0 ; for ( i=0; ichcount = nchars ; #endif status = checkindex(curbucket[w]) ; status = puttemp( &tempbuffer[w],curbucket[w],w ) ; tempstat.writes++ ; windpt->toplin = 0 ; if (linecount[w] == 0) then { if ( curbucket[w] == firbucket[w] ) then firbucket[w] = (_gworkpt(curbucket[w]))->link ; else { i = 1 ; while ( (_gworkpt(i))->link != curbucket[w] ) i++ ; (_gworkpt(i))->link = (_gworkpt(curbucket[w]))->link ; } (_gworkpt(curbucket[w]))->link = 0 ; } } dumpstats() { xprintf("Accesses (r/w) %d %d\n",tempstat.reads,tempstat.writes); xprintf("Faults (r/w) %d %d\n",tempstat.r_faults,tempstat.w_faults); xprintf("Cache hits %d\n", tempstat.hits) ; accstats() ; } dumpindex() { long ccount ; register int st,i ; st = 1 ; ccount = 0 ; for (i=1;i<=maxbucket[w] && testcc() == 0;i++) { #if CHARCOUNT decout((_gworkpt(i))->chcount) ; #endif decout((_gworkpt(i))->lcount ) ; decout((_gworkpt(i))->link ) ; decout(st) ; st = st + (_gworkpt(i))->lcount ; #if CHARCOUNT ccount = ccount + (_gworkpt(i))->chcount ; #endif crlfout() ; } xprintf("\n Average characters/bucket %d\n",(i=ccount/maxbucket[w])) ; xprintf(" Average lines/bucket %d\n\n",st/maxbucket[w]) ; } /* FindLine looks through the resident index to locate the workfile bucket that has the desired line in it. If the workfile bucket is already resident on the current window, it will simply return the the index to it. If not resident, it will ask the workfile cacher to return the bucket containing the line and then update the win- dow to contain all the lines from that bucket, returing the index to the desired line. */ struct textline *textpointer(linenumber) int linenumber ; { return( w_l_address[ findline(linenumber) ] ) ; /* return( &windpt->lines[findline(linenumber)] ); */ } findline( lineno ) int lineno; { int temp,status,oldcurmode ; register int i,buffoffset,wline ; read_only = 0 ; if ( *maxline < 2 ) then error( ER_NOLINES ) ; if ( (lineno >= windpt->botlin) && (lineno <= windpt->toplin) ) then return(lineno - windpt->botlin) ; else { if ((oldcurmode=curmode[w]) == ST_UPDATE) then putback(); /* Desired line not found in current window, assume that */ /* we are like searching for a pattern so try looking in */ /* the next window. If its not in the next window, then */ /* start all over from the first link to the end. Also */ /* check CTX_VALID to see if next field can be invalid. */ /* If CTX_VALID is zero then ignore the next field and */ /* start at the top of the index to the end. */ temp = 0 ; if ( (curbucket[w]=(_gworkpt(curbucket[w]))->link) != 0 && oldcurmode == ST_NORMAL_MODE && ctx_valid ) then { windpt->botlin = windpt->toplin + 1 ; windpt->toplin += (_gworkpt(curbucket[w]))->lcount ; temp = ( ( lineno >= windpt->botlin ) && ( lineno <= windpt->toplin ) ) ; } ; if ( temp == 0 ) then { curbucket[w] = firbucket[w] ; windpt->botlin = 1 ; windpt->toplin = (_gworkpt(curbucket[w]))->lcount ; while (! (( lineno >= windpt->botlin ) && ( lineno <= windpt->toplin )) ) { windpt->botlin = windpt->toplin + 1 ; curbucket[w] = (_gworkpt(curbucket[w]))->link ; windpt->toplin += (_gworkpt(curbucket[w]))->lcount ; } ; } ; status = gettemp( &tempbuffer[w],curbucket[w],w ) ; tempstat.reads++ ; lstbucket[w] = curbucket[w] ; ctx_valid = 1 ; buffoffset = 0 ; temp = (_gworkpt(curbucket[w]))->lcount ; for (wline=0; wlinec , &tempbuffer[w].txt[buffoffset] , tempbuffer[w].rsize[wline] ) ; w_l_address[wline]->len = tempbuffer[w].rsize[wline] ; buffoffset += w_l_address[wline]->len ; /* scopy( &windpt->lines[wline].c[0], */ /* &tempbuffer[w].txt[buffoffset], */ /* tempbuffer[w].rsize[wline] ) ; */ /* windpt->lines[wline].len = tempbuffer[w].rsize[wline] ;*/ /* buffoffset += windpt->lines[wline].len ; */ } curmode[w] = ST_NORMAL_MODE ; return( lineno - windpt->botlin ); } } putback() { register int i,nlines ; lstbucket[w] = curbucket[w] ; linecount[w] = 0 ; nlines = (_gworkpt(curbucket[w]))->lcount ; for ( i=0; i < nlines ; i++ ) ins_line( &windpt->lines[i].c[0],windpt->lines[i].len ); ins_lnks(); if (curmode[w] != ST_SPECIAL) then curmode[w] = ST_NORMAL_MODE ; ctx_valid = 0 ; return(SYS_NORMAL); } /* Procedure SAVELN SAVELN takes the current window from the start linenumber (relative to the start of the window) to the desired line and updates the index to make room for a new line. The line number are relative, in that they are number 1..WINDOWSIZE. Since offsets for array in 'C' start at zero, the reference to 'lineno-1' should be obvious. */ saveline(rel_start_line,rel_fin_line) int rel_start_line,rel_fin_line; { register int lineno; for ( lineno = rel_start_line; lineno < rel_fin_line; lineno++ ) ins_line(windpt->lines[lineno].c,windpt->lines[lineno].len); return(SYS_NORMAL); } /* Procedure CheckIndex Checkindex should check to see if there is sufficient space in the workfile pointer index (which is maintained in memory) to add ano- ther entry. If not, then it should do the equivalent of a EXTK$S to get the space needed and update the size. */ checkindex( rnum ) int rnum ; { register struct tempindex *status ; extern struct tempindex *getvm() ; int temp ; if ( rnum < indexsize[w]-10 ) then return( SYS_NORMAL ) ; else { if ( (status=getvm(indexsize[w]+INCR_SIZE,w,&temp)) == 0 ) then { tederror("Failure to extend index, please finish") ; return(0) ; } else { indexsize[w] = indexsize[w] + temp ; win_workpt[w] = status ; workpt = win_workpt[w] ; return( SYS_NORMAL ) ; } } } /* SCLOADLINE() load workbuffer with desired line */ /* SCUNLOADLINE() unload desired line from workbuffer */ /* TEXTMODIFY() mark text window as being dirty */ scunloadline() { extern int loaded,laddr,worklength ; extern char workbuffer[] ; register char *wp,*cp; register int i; if ( loaded == 0 ) then return(1) ; loaded = 0 ; wp = workbuffer ; if (worklength == 0) then worklength = 1 ; windpt->lines[sccontext.laddr].len = worklength ; cp = windpt->lines[sccontext.laddr].c ; for (i=0;i= *maxline ) then *curline = *maxline - 1 ; i = findline( *curline ) ; sccontext.laddr = i ; wp = workbuffer ; cp = windpt->lines[i].c ; worklength = windpt->lines[i].len ; scopy(workbuffer,windpt->lines[i].c,worklength) ; read_only = 0 ; if ( *curline == *maxline-1 ) then read_only = 1 ; return(1) ; } txtmod() { extern int *curline,inmode ; if ( (sts_one & _vtedit) == 0 ) then curmode[w] = ST_UPDATE ; else if ( *curline != *maxline ) then curmode[w] = ST_UPDATE ; } ins_scline() { savectx() ; rstctx() ; } savectx() { extern int *curline ; sccontext.laddr = findline(*curline) ; linecount[w] = 0 ; curmode[w] = ST_INSERT ; sccontext.lc = (_gworkpt(curbucket[w]))->lcount ; saveline(0,sccontext.laddr) ; } rstctx() { extern char workbuffer[]; extern int worklength ; ins_line(workbuffer,worklength) ; (*maxline)++ ; saveline(sccontext.laddr,sccontext.lc) ; ins_lnks() ; } /* switch to a new editing window */ wptset() { register int i ; for ( i = 0 ; i < _BCK_FIL; i++ ) w_l_address[i] = &windpt->lines[i] ; } vtswindow(new_w) int new_w ; { int temp_w ; #if NWINDOWS-1 temp_w = w ; if ( new_w == -1 ) then temp_w = ( temp_w == 0 ) ?1:0 ; else temp_w = new_w ; if ( temp_w > NWINDOWS-1 ) then { scwarning(w_badwin) ; return(0) ; } ; scunloadline() ; w = temp_w ; workpt = win_workpt[w] ; maxline = &win_maxline[w] ; windpt = &window[w] ; wptset() ; loclow = &win_low[w] ; lochigh = &win_high[w] ; curline = &win_curline[w] ; if ( *curline == 0 ) then { inseofmark() ; *loclow = 1 ; *curline = *loclow ; } putbin("\015\012",2) ; scloadline() ; scmove() ; newpage(*curline) ; sctopline() ; scloadline() ; scmove() ; return(1) ; #else scwarning(w_badwin) ; return(0) ; #endif }