/* ---------------------------- tvx_io.c ------------------------------- */ #include "tvx_defs.ic" #include "tvx_glbl.ic" #define SWITCH '-' #define FILESEP '.' #ifdef MSDOS #define TEMPEXT ".$$1" /* name of temporary file */ #define BACKEXT ".BAK" /* name of backup file */ #endif #ifdef OSCPM #define TEMPEXT ".$$1" /* name of temporary file */ #define BACKEXT ".BAK" /* name of backup file */ #endif #ifdef GEMDOS #define TEMPEXT ".Z1X" /* name of temporary file */ #define BACKEXT ".BAK" /* name of backup file */ #endif #ifdef UNIX #define BACKEXT ".B" /* name of backup file */ #endif FILE *fopen(); /* local globals (used by tv terminal driver section) */ static int linptr; /* common "linot" */ static char linout[242]; static char stemp[FNAMESIZE+1]; /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FILE IO section File handling algorithm: The original name specified on command line is called orig_file. It will remain untouched throughout the editing session. At the very end (normal exit), it will be renamed to the ".BAK" name. source_file is the current name of the file with source. It will orignally be the same as orig_file, but may change to a generated scratch name depending on the operating system. source_file is always the lastest fully written version of the file (like after file beginning, for example). work_file is the output file. On normal exit, this is the file renamed to dest_file. On buffer beginning, it will be moved to source_file, possibly after renameing. dest_file is the ultimate destination file. This name is not actually used until the final rename on normal exit. It is checked to be sure it is a valid name to be opened, however. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* =============================>>> ABORT <<<============================= */ abort() { /* abort - close files, abort operation */ char rply[4]; tvclr(); ask("Abort, are you sure? ",rply,1); if (clower(rply[0]) != 'y') { verify(1); return; } abort2(); } /* =============================>>> ABORT2 <<<============================= */ abort2() { clobak(); tvclr(); if (!newfil) fclose(infile); if (!rdonly) fclose(outfile); if (strcmp(orig_file,source_file) != 0) { prompt("File begin used, intermediate edits in: "); remark(source_file); } unlink(work_file); /* delete the work file */ reset(); quit(); } /* =============================>>> FBEG <<<============================= */ int fbeg() { /* fbeg - go back to file top */ SLOW int fbegv; if (rdonly) { tverrb("Can't: R/O"); /* can't do this for read only access */ return (FALSE); } for (wtpage(1) ; rdpage() ; wtpage(1) ) /* write out rest */ ; if ((! newfil)) { fclose(infile); /* close source_file */ } if (usecz) fputc(ENDFILE,outfile); fclose(outfile); /* close work_file */ /* files closed now, re-open */ newfil = FALSE; /* not a new file any more */ strcpy(source_file,work_file); /* new source file */ temp_name(work_file,FALSE); /* make a new temporary name */ if (!(infile = fopen(source_file,FILEREAD))) goto l900; else ineof = FALSE; unlink(work_file); /* get rid of previous copies */ if (!(outfile = fopen(work_file,FILEWRITE))) { goto l900; } fbegv=rdpage(); /* read in new buffer */ newscr(); return (fbegv); l900: tverrb("Error re-opening"); return (FALSE); } /* =============================>>> FILE_EXIT <<<============================= */ file_exit() { /* close the input and output files, rename */ SLOW int i; if (!newfil) /* don't close input if new file */ { fclose(infile); } while (!rdonly && !*dest_file) { remark("No name for output file has been specified."); prompt("Enter new name for output file: "); reply(dest_file,FNAMESIZE); } if (!rdonly) /* don't close output if read only access */ { if (usecz) fputc(ENDFILE,outfile); set_mode(outfile); /* set output mode if can */ fclose(outfile); /* orig_file has the name to be renamed to .bak work_file has the file name we want to be dest_name */ if (strcmp(orig_file,dest_file) == 0) /* make backup version */ { strcpy(stemp,orig_file); #ifndef COMMA_BAK if ((i = rindex(stemp,FILESEP)) > 0) /* see if extenstion */ scopy(BACKEXT,0,stemp,i); /* make .bak */ else { scopy(BACKEXT,0,stemp,strlen(stemp)); /* just add on */ } #else i = rindex(orig_file,'/')+1; scopy(".,",0,stemp,i); scopy(orig_file,i,stemp,strlen(stemp)); #endif unlink(stemp); /* delete previous generation */ ren_file(orig_file,stemp); /* rename the file */ if (!makebackup) /* don't want to keep old one */ unlink(stemp); /* delete it if don't want backup file */ } if (strcmp(orig_file,source_file) != 0) /* delete intermediate file */ unlink(source_file); while (infile = fopen(dest_file,FILEREAD)) /* output exists? */ { fclose(infile); prompt("Output file "); prompt(dest_file); prompt(" already exists. Overwrite it? (y/n) "); ureply(stemp,1); if (*stemp == 'Y') { unlink(dest_file); break; } prompt("Enter new name for output file: "); reply(dest_file,FNAMESIZE); } ren_file(work_file,dest_file); /* finally, rename last file */ } } /* =============================>>> FOPENX <<<============================= */ fopenx(argc,argv) int argc; char *argv[]; { /* open the input file This routine picks up file name from the user, creates a backup version in some appropriate manner, and opens the file for input and output. */ SLOW int iswval, iswbeg, argnum, set_ttymode; SLOW char ch; char rply[4]; usebak = logdef; /* if useing backup log file */ ttymode = FALSE; /* not in tty mode, so io ok */ ttynext = 1000; /* force read */ if (argc <= 1) { remark("Usage: tvx filename [-b -i -l -o=f -r -s -t -w -# {-z -c=f}]"); #ifdef FULLHELP remark(""); prompt(" Options: "); remark(VERSION); remark(" -[no]b : backup file -[no]i : autoindent"); remark(" -[no]l : make command log file"); remark(" -o=outputfile -r : read only"); remark(" -s : big save buff -[no]w : word processing mode"); remark(" -t : tty edit mode -# : set virtual window lines to #"); #ifdef MSDOS remark(" -[no]z : use control-z for end of file"); #endif #ifdef CONFIGFILE #ifdef MSDOS remark(" -c=configfile -c : use /bin/config.tvx"); #endif #ifdef GEMDOS remark(" -c=configfile -c : use /bin/config.tvx"); #endif #ifdef OSCPM remark(" -c=configfile -c : use A:config.tvx"); #endif #endif #ifdef UNIX remark(" {options not available for unix}"); #endif #endif remark(""); reset(); quit(); } newfil= /* assume opening an old file */ rdonly = FALSE; /* assume not read only */ makebackup = MAKE_BACKUP; /* default value for make a backup */ blimit = BUFFLIMIT; for (argnum = 1 ; argnum < argc ; ++argnum) { strcpy(stemp,argv[argnum]); /* pick up the file name or switch */ REDO: if (stemp[0] == SWITCH) /* switch in form "/R filename" only */ { iswbeg=1; /* start at 1 */ iswval = TRUE; if (clower(stemp[1]) == 'n' && clower(stemp[2]) == 'o') { iswval = FALSE ; iswbeg = 3 ; } ch = clower(stemp[iswbeg]); /* get the char */ if (ch == 'r') /* read only access */ rdonly=iswval; else if (ch == 'i') /* auto indent */ autoin = iswval; else if (ch == 'w') /* word processing mode */ { if (iswval) wraplm = 70; else wraplm = 0; } else if (ch == 'l') usebak=iswval; else if (ch == 'b') makebackup = iswval; /* make a backup file */ else if (ch == 'z') usecz = iswval; else if (ch == 'o' && (stemp[iswbeg+1] == '=' || stemp[iswbeg+1] == ':')) /* specifying output */ { if (!iswval) /* wrong order! */ { remark("Bad -O= switch"); quit(); } scopy(stemp,iswbeg+2,dest_file,0); /* remember name */ } #ifdef CONFIGFILE else if (stemp[iswbeg] == 'c' && stemp[iswbeg+1] == 0) /* default cfg */ { strcpy(stemp,cfgname); goto REDO; } else if (stemp[iswbeg] == 'c' && (stemp[iswbeg+1] == '=' || stemp[iswbeg+1] == ':')) /* specifying config */ { expand_name(&stemp[iswbeg+2]); if ((bkuin = fopen(&stemp[iswbeg+2],FILEREAD))==0) { remark("Can't open configuration file."); continue; } rdcfg(lexsym,LEXVALUES+1); rdcfg(synofr,20); rdcfg(synoto,20); rdcfg(funchar,50); rdcfg(funcmd,50); rdcfg(&funkey,1); rdcfg(&autoin,1); rdcfg(&ddline,1); rdcfg(&dscrl,1); rdcfg(&dxcase,1); rdcfg(&wraplm,1); rdcfg(&use_wild,1); rdcfg(&usebak,1); logdef = usebak; #ifdef MSDOS rdcfg(&usecz,1); #endif #ifdef GEMDOS rdcfg(&usecz,1); #endif fclose(bkuin); } #endif else if (ch == 's') /* big save buffer */ { if (!iswval) blimit=BUFFLIMIT; else blimit=BUFFLIMIT*3; } #ifndef VTERM else if (ch == 't') /* tty mode */ set_ttymode = iswval; /* make a backup file */ #endif else if (ch >= '0' && ch <= '9') /* making a virtual window */ { tvlins = atoi(&stemp[iswbeg]); /* get virtual screen size */ if (tvlins < 3 || tvlins > tvhardlines) /* invalid window */ { remark("Invalid window size"); tvlins = tvhardlines; } else { ddline = (tvlins / 2) + 1; /* fix home line */ setdscrl(); } } else /* illegal switch */ { prompt("Unknown switch -"); ttwt(ch); prompt(": Ignore and continue? (y/n) "); ureply(rply,1); if (*rply != 'Y') { reset(); quit(); } } } else /* must have a file name */ { strcpy(orig_file,stemp); } } /* end for */ /* now open file properly - make copies to all 4 names */ GETNAME: while (!*orig_file) { ask("Edit file? ",orig_file,FNAMESIZE); } expand_name(orig_file); /* expand on unix */ if (!(infile = fopen(orig_file,FILEREAD))) /* can open? */ { prompt("Create file "); prompt(orig_file); prompt("? (y/n) "); ureply(rply,1); if (*rply != 'Y') { *orig_file = 0; goto GETNAME; } if (*dest_file) remark("New file, -o= switch ignored"); *dest_file = 0; newfil = TRUE; /* a new file */ rdonly = FALSE; } /* orig_file now has the name of the source file, and it might be open */ ineof = FALSE; strcpy(source_file,orig_file); /* copy to other names */ strcpy(work_file,orig_file); if (!*dest_file) /* no -o specified */ strcpy(dest_file,orig_file); if (!newfil) /* not new file */ { fclose(infile); /* close orig file */ if (!(infile = fopen(source_file,FILEREAD))) /* re-open */ { remark("Internal editor error, aborting"); exit(100); } get_mode(infile); /* get mode of original file */ } else { *orig_file = *source_file = 0; } /* now see if we can make an output file */ if (!rdonly) { temp_name(work_file,TRUE); /* make into a temporary name 1st time*/ #ifndef OSCPM /* new code added here for version 1/22/86 */ if ((outfile = fopen(work_file,FILEREAD))) { /* this code is needed when the temp_name might not be unique - which happens when you push (^O) and try to edit a file with the same main name but perhaps a different extension - the temp file will be the same, and the child version of tvx will then delete the temporary file created by the parent. This can happen again if fbeg, but let's assume the 'y' applies forever. */ fclose(outfile); /* close up the file */ prompt("Work file already exists: "); remark(work_file); prompt("Erase it and continue with editing? (y/n) "); ureply(rply,1); if (*rply != 'Y') { reset(); exit(100); /* abnormal exit */ } } /* end of new code added here for version 1/22/86 */ #endif unlink(work_file); /* get rid if already there */ if (!(outfile = fopen(work_file,FILEWRITE))) { prompt("Unable to create output work file: "); remark(work_file); if (!newfil) { prompt("Continue in read only mode? (y/n) "); ureply(rply,1); if (*rply != 'Y') { fclose(infile); reset(); exit(100); /* abnormal exit */ } } *dest_file = *work_file = 0; rdonly = TRUE; } } else { *dest_file = *work_file = 0; } ttymode = force_tty ? TRUE : set_ttymode; /* now safe to set ttymode */ } /* =============================>>> setdscrl <<<============================= */ setdscrl() { /* compute a new value for dscrl */ if (dscrl == 0) return; /* if already 0, don't change */ dscrl = tvlins / 3; if ((ddline + dscrl) >= tvlins) /* looks ugly if hits last line */ dscrl--; if (dscrl < 0) /* don't allow this */ dscrl = 0; } #ifdef CONFIGFILE /* =============================>>> RDCFG <<<============================= */ rdcfg(toset,cnt) char *toset; int cnt; { /* read cnt vals from bkuin */ FAST int i,val; for (i = 0 ; i < cnt ; ++i) { if ((val = fgetc(bkuin)) == EOF) { remark("Invalid configuration file, aborting"); fclose(bkuin); quit(); } *toset++ = val; /* replace with new commands */ } } #endif /* =============================>>> ADDFIL <<<============================= */ int addfil(rw) int rw; { /* addfil - add contents of external file to save buffer positive means read into buffer, negative means write save buffer */ SLOW int chr; SLOW int limit; SLOW BUFFINDEX fromch; SLOW int i; SLOW FILE *outf; if (rw >= 0) /* read a file */ { if (!gbgcol(nxtchr)) /* gc first */ { newscr(); tverrb("No save room"); return (FALSE); } tvclr(); #ifdef LASL ask("Read external filename: ",stemp,FNAMESIZE); #else ask("Yank filename: ",stemp,FNAMESIZE); #endif expand_name(stemp); /* expand on some systems */ if (!(bkuin = fopen(stemp,FILEREAD)) || !*stemp) { newscr(); #ifdef LASL tverrb(" Unable to open external file "); #else tverrb(" Unable to open yank file "); #endif return (FALSE); } savlin=0 ; savlen=0 ; nxtsav =mxbuff ; /* clear out save buffer */ limit = max(nxtchr,mxbuff/2)+ALMOSTOUT; do { if ((chr = getchr(bkuin)) < 0) { newscr(); fclose(bkuin); return (TRUE); } if (chr == NEWLINE) { #ifdef FILELF getchr(bkuin); #endif chr=ENDLINE; ++savlin; } *(buff+nxtsav--) = chr; if (nxtsav <= limit) { newscr(); tverrb("File only partly read"); break; } } while (1); fclose(bkuin); return (TRUE); } /* --------------- to here, then writing from save buffer --------------*/ if (nxtsav==mxbuff) /* nothing to save */ { tverrb("Save buffer empty!"); return (TRUE); } tvclr(); ask("Write to external filename: ",stemp,FNAMESIZE); expand_name(stemp); /* expand on some systems */ if (!(outf = fopen(stemp,FILEWRITE)) || !*stemp) { newscr(); tverrb(" Unable to open external file "); return (FALSE); } /* # move down line to make space for new */ fromch = mxbuff; /* where taking saved stuff from */ for (i = 0 ; i < savlin ; ++i) { for ( ; ; ) /* scan save buffer */ { if ((chr = *(buff+fromch--)) == ENDLINE) { fputc(NEWLINE,outf); #ifdef FILELF fputc(LF,outf); #endif break; } else fputc(chr,outf); } } if (usecz) fputc(ENDFILE,outf); fclose(outf); newscr(); return (TRUE); } /*=============================>>> SCOPY <<<================================*/ scopy(old,oldbeg,new,newbeg) char old[], new[]; int oldbeg,newbeg; { while (old[oldbeg]) new[newbeg++]=old[oldbeg++]; new[newbeg] = 0; } /* ************************************************************************** Following code is for non-unix systems **************************************************************************** */ #ifndef UNIX /* =============================>>> get_mode <<<============================= */ get_mode(f) FILE *f; { /* gets access mode of open file f */ } /* =============================>>> set_mode <<<============================= */ set_mode(f) FILE *f; { /* sets access mode of open file f */ } /* ==========================>>> expand_name <<<============================ */ expand_name(n) char *n; { /* expands unix file names */ } /* =============================>>> ren_file <<<=========================== */ ren_file(old,new) char *old, *new; { #ifndef GEMDOS if (rename(old,new) != 0) { prompt(old) ; prompt(" not renamed to "); remark(new); } #endif #ifdef GEMDOS gemdos(0x56,0,old,new); /* can't find C version */ #endif } /* =============================>>> temp_name <<<=========================== */ temp_name(n,first) char *n; int first; { /* generates a temporary name from n. Depending on value of first, it will either add a 1 or 2 to name */ SLOW int i; if (first) { if ((i = rindex(n,FILESEP)) > 0) /* see if extenstion */ scopy(TEMPEXT,0,n,i); /* make .bak */ else { scopy(TEMPEXT,0,n,strlen(n)); /* just add on */ } } else { i = strlen(n); if (n[i-1] == '1') n[i-1] = '2'; else n[i-1] = '1'; } } #endif /* ************************************************************************** This section is for the version supporting command logfile backup. The code necessary for this version is included here, and may be compiled by defining VB to be a blank. **************************************************************************** */ /* =============================>>> OPNBAK <<<============================= */ opnbak() { /* opnbak - open the backup log file if VB defined as ' ', then backup version created */ #ifdef VB if (! usebak) { bakflg = FALSE; return; } bkuout = fopen(BACKUPNAME,FILEWRITE); bakpos = 1; #endif } /* =============================>>> PUTBAK <<<============================= */ putbak(chr) char chr; { /* putbak - put a character into the backup file */ #ifdef VB static char copy; if (! usebak) return; copy=chr; if (copy < 32 || copy == '@' || copy==delkey) { fputc('@',bkuout); bakcrlf(); if (copy < 32) copy += '@'; else if (copy==delkey) copy = '?'; /* let @? be rubout */ } fputc(copy,bkuout); bakcrlf(); #endif } #ifdef VB /* =============================>>> BAKCRLF <<<============================= */ bakcrlf() { /* conditionally put a cr/lf to backup file */ if (++bakpos > 63) { fputc(NEWLINE,bkuout); #ifdef FILELF fputc(LF,bkuout); #endif bakpos = 1; } } #endif /* =============================>>> CLOBAK <<<============================= */ clobak() { #ifdef VB if (! usebak) return; fputc(NEWLINE,bkuout); #ifdef FILELF fputc(LF,bkuout); #endif if (usecz) fputc(ENDFILE,bkuout); fclose(bkuout); #endif } /* =============================>>> GETBAK <<<============================= */ getbak(chr) char *chr; { /* get one char from back up file if there */ #ifdef VB SLOW int ich; l10: if ((ich = getchr(bkuin)) < 0 || ich == ENDFILE) { l15: fclose(bkuin); *chr=0; /* harmless character */ bakflg=FALSE; newscr(); return; } if (ich == NEWLINE) goto l10; #ifdef FILELF if (ich == LF) goto l10; #endif *chr=ich; if (ich=='@') { l20: if ((ich = getchr(bkuin)) < 0 || ich == ENDFILE) { goto l15; } if (ich == NEWLINE) goto l20; #ifdef FILELF if (ich == LF) goto l20; #endif *chr=ich; if (ich == '?') *chr=delkey; else if (*chr != '@') *chr= ich - '@'; } #endif } /* =============================>>> OPNATF <<<============================= */ opnatf() { /* open an indirect command file */ #ifdef VB tvclr(); ask("Name of command file: ",stemp,FNAMESIZE); /* read in the file name from the terminal */ expand_name(stemp); if (!*stemp) return; if (!(bkuin = fopen(stemp,FILEREAD))) { newscr(); tverrb("Bad @ name"); return; } bakflg=TRUE; newscr(); #endif } /* ************************************************************************** This section contains code to write and read buffers of data **************************************************************************** */ /* =============================>>> RDPAGE <<<============================= */ int rdpage() { /* rdpage - read in file up to buffer limit only place text read from edited file */ SLOW int chr; SLOW int l,newlns; if (newfil) /* can't read in when a new file */ { return (FALSE); } if (nxtlin > mxline || nxtchr > mxbuff-130) /* error check */ { tverrb("Lines filled "); return (FALSE); } newlns=0; /* begin at the beginning */ while (mxline-nxtlin > LINELIMIT && nxtsav-nxtchr > blimit && !ineof) { /* read in while have room */ chr = fgetc(infile); if (chr == EOF) { ineof = TRUE; break; } if (chr == ENDFILE && usecz) { ineof = TRUE; break; } #ifdef FILELF if (chr == LF) continue; #endif *(buff+nxtchr) = BEGLINE; *(lines+nxtlin) = nxtchr++; ++newlns ; while (chr != NEWLINE) /* store a line */ { *(buff+nxtchr++) = chr; chr = fgetc(infile); if (chr == EOF) { ineof = TRUE; break; } if (chr == ENDFILE && usecz) { ineof = TRUE; break; } } *(buff+nxtchr++)=ENDLINE; ++nxtlin; } l900: if (nxtlin > 1) /* we really read something */ { curlin=1; /* point to top of char */ curchr = *(lines+1)+1; /* point to first character */ } return (newlns > 0) ; } /* =============================>>> WTPAGE <<<============================= */ wtpage(whow) int whow; { /* wtpage - write out contents of text buffer, and clear line list */ FAST int i; FAST char *chrp; SLOW char *lim; SLOW int wlimit; if (whow < 0) /* allow writing partial buffer */ wlimit = curlin - 1; else wlimit = nxtlin -1; if (nxtlin <= 1 || rdonly) { tverr("Empty buffer"); goto zapb; } if (whow < 0) tverr("Writing partial buffer"); else tverr("Writing buffer"); tvhdln(); for (i = 1 ; i <= wlimit ; ++i) { chrp = buff + (*(lines+i)+1); /* ptr to first char of line */ while (*chrp != ENDLINE) { fputc(*chrp++, outfile); } fputc(NEWLINE,outfile); #ifdef FILELF fputc(LF,outfile); #endif } zapb: if (whow < 0) { killin(-(curlin-1)); /* kill to top of buffer */ if (!gbgcol(nxtchr)) /* gc first */ { newscr(); tverrb("Warning: no extra room created"); return (FALSE); } return (TRUE); } else { lim = buff + nxtsav; for (chrp=buff ; chrp < lim ; *chrp++ = GARBAGE) ; tvdlin = /* start on first line again */ nxtlin = /* reset to initial state */ nxtchr = 1; curchr = curlin=0; return (TRUE); } } /* ************************************************************************** This section contains misc. stuff likely to be operating system dependent **************************************************************************** */ /* ===========================>>> OPSYSTEM <<<============================== */ opsystem() { #ifdef MSDOS /* !!! cii-86 dependent */ char rp[80]; MS_AGAIN: tvclr(); ask("DOS command (any key to resume edit when done): ",rp,79); remark(""); if (system(rp) != 0) { tvxy(1,1); ask("Sorry, but couldn't find COMMAND.COM.",rp,1); } else { tvxy(1,1); ask("",rp,1); if (*rp == '!') goto MS_AGAIN; } verify(1); #endif #ifdef UNIX unix_sys(); #endif #ifdef GEMDOS return; #endif } #ifndef UNIX /* ===========================>>> TTINIT <<<============================== */ ttinit() { /* this routine could be used to set up keyboard input, perhaps turning on non-echoed input */ return; } /* ===========================>>> TTCLOS <<<============================== */ ttclos() { /* this routine could undo anything ttinit() did */ return; } #endif #ifndef VTERM /* ===========================>>> TTRD <<<============================== */ ttrd() { /* this routine is called to read one unechoed char from the keyboard */ static int tc, i; static char chr; RDTOP: if (ttymode) tc = rdtty(); /* get a char from the tty */ else { #ifdef OSCPM while (!(tc = bdos(6,-1))) /* cp/m implementation */ ; #endif #ifdef MSDOS tc = bdos(7,-1); /* ms-dos implementation (!!! cii-86) */ #endif #ifdef GEMDOS tc = gemdos(7); /* GEMDOS application */ #endif #ifdef UNIX tc = ttrd_unix(); #endif } chr = tc & 0377; if (chr == funkey) /* function key */ { if (ttymode) { tc = rdtty(); /* get a char from the tty */ } else { #ifdef OSCPM while (!(tc = bdos(6,-1))) /* cp/m implementation */ ; #endif #ifdef MSDOS tc = bdos(7,-1); /* ms-dos implementation */ #endif #ifdef GEMDOS tc = gemdos(7); /* GEMDOS application */ #endif #ifdef UNIX tc = ttrd_unix(); #endif } chr = tc & 0377; for (i = 0 ; i < 50 && funchar[i] ; ++i) { if (chr == funchar[i]) { tc = funcmd[i] & 0377; return (tc); } } goto RDTOP; /* ignore invalid function keys */ } tc = chr & 0377; return (tc); } #endif #ifndef UNIX /* ===========================>>> TTWT <<<============================== */ ttwt(chr) char chr; { /* this routine is called to write one char to the keyboard It also interprets print direction */ if (ttymode) return; dispch(chr); /* cp/m, ms-dos version */ if (useprint) printc(chr); } #endif #ifdef OSCPM /* ===========================>>> GETCHR <<<============================== */ getchr(filnum) FILE *filnum; { /* get a character from filnum */ #define EOFBYTE 26 FAST int ichr; if (((ichr = getc(filnum)) == EOFBYTE)) { if (usecz) return (EOF); } return (ichr); } #endif #ifdef MSDOS /* ===========================>>> GETCHR <<<============================== */ getchr(filnum) FILE *filnum; { /* get a character from filnum */ #define EOFBYTE 26 FAST int ichr; if (((ichr = fgetc(filnum)) == EOFBYTE)) { if (usecz) return (EOF); } return (ichr); } #endif #ifdef GEMDOS /* ===========================>>> GETCHR <<<============================== */ getchr(filnum) FILE *filnum; { /* get a character from filnum */ #define EOFBYTE 26 FAST int ichr; if (((ichr = fgetc(filnum)) == EOFBYTE)) { if (usecz) return (EOF); } return (ichr); } #endif /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TVX TERMINAL DRIVER for various terminals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* =============================>>> TRMINI <<<============================= */ trmini() { /* initialize term if necessary */ sendcs(cinit); tvclr(); } /* =============================>>> reset <<<============================= */ reset() { sendcs(cendit); ttclos(); } /* =============================>>> ttyverify <<<============================= */ ttyverify(knt) int knt; { SLOW BUFFINDEX oldline, oldchr, limit; /* current position */ oldline = curlin; oldchr = curchr; /* remember where we were */ ttymode = FALSE; /* enable output stuff */ if (knt < 0) /* type some above */ { curchr = 0; curlin = curlin + knt ; /* back n lines */ if (curlin < 1) curlin = 1; while (curlin < oldline) /* write out the lines */ ttyline(curlin++); /* write line, no cursor */ } else { ttyline(curlin); /* type current line */ curchr = 0; /* this turns off cursor */ limit = oldline + knt - 1; if (limit >= nxtlin) limit = nxtlin - 1; while (++curlin <= limit) ttyline(curlin); } curchr = oldchr; curlin = oldline; ttymode = TRUE; } /* =============================>>> ttyline <<<============================= */ ttyline(linenr,cursor) BUFFINDEX linenr; { SLOW BUFFINDEX chrc; SLOW int outlen; chrc = *(lines+linenr)+1; /* point to first character in line */ outlen = 0; /* nothing out yet */ for ( ; ; ) { if (chrc == curchr) /* at cursor */ { outlen += 2; if (outlen > 78) /* line wrap */ { remark(""); ttwt('_'); outlen = 3; } ttwt('/'); ttwt('\\'); } if (*(buff+chrc) == ENDLINE) /* done */ break; outlen += ttywtch(*(buff+chrc)); /* watch for line wrap */ if (outlen > 78) { remark(""); ttwt('_'); outlen = 1; } ++chrc; /* next character */ } remark(""); } /* =============================>>> ttywtch <<<============================= */ ttywtch(chr) char chr; { if (chr >= ' ') /* regular character */ { ttwt(chr); return 1; } else /* control character */ { ttwt('^'); ttwt(chr+'@'); return 2; } } /* =============================>>> rdtty <<<============================= */ rdtty(knt) int knt; { /* fake rdtt for ttymode - only called when in ttymode */ #define RDBUFFSIZE 81 static char rdtbuf[RDBUFFSIZE]; RDTOP: ttymode = FALSE; /* take out of ttymode for echo */ if (ttynext >= RDBUFFSIZE) /* need to read a line */ { if (ins_mode) /* different prompts for modes */ prompt("+"); else prompt("tvx>"); reply(rdtbuf,80); /* read a line */ ttynext = 0; /* reset pointer */ } ttymode = TRUE; /* no echo again */ if (rdtbuf[ttynext] == 0) /* end of buffer */ { ttynext = 1000; if (ins_mode) return (CR); /* return a carriage return for ins */ else goto RDTOP; /* read another line */ } else { return (rdtbuf[ttynext++]); /* return character */ } } /* =============================>>> TVPLIN <<<============================= */ tvplin(chrptr) BUFFINDEX chrptr; { /* tvplin - put line beginning at chrptr will only type what will fit on screen (using xout) */ SLOW char tmp; SLOW int linlen, origx; SLOW BUFFINDEX i; #ifdef ULBD SLOW int ul, bd, useul, usebd; ul = bd = useul = usebd = FALSE; #endif last_col_out = linptr = 0; origx = xoutcm; /* save x so can get true linelen */ for (i=chrptr; *(buff+i)!=ENDLINE && xoutcm <= 240; ++i) { #ifdef NO_EXTEND_CHAR if ((*(buff+i) < ' ' || (*(buff+i) & 0x80) ) && (*(buff+i) >= 0)) /* control character? */ #else if (*(buff+i)<' ' && *(buff+i) >= 0) /* control character? */ #endif { if (*(buff+i) == TAB) { if (tabspc > 0) { do { linout[linptr++] = ' '; /* replace with blanks */ ++xoutcm; } while ( ((xoutcm-1) % tabspc) != 0); } else { linout[linptr++] = '^'; linout[linptr++] = 'I'; xoutcm += 2; } continue; } else /* other control character */ { linout[linptr++] = (*(buff+i) & 0x80) ? '~' : '^'; ++xoutcm; if (xoutcm==tvcols && *(buff+i) != ENDLINE) continue; /* #$$$ ascii machines!!!! */ tmp = *(buff+i); if ((tmp &= 0x7f) < ' ') /* ok to mix extended, ctrl */ tmp += '@'; linout[linptr++]=tmp; #ifdef ULBD if ( *(buff+i)==TOGUNDERLINE && cundlb[0] != 0) { if (ul) { strcopy(cundle,0,linout,&linptr); ul = FALSE; } else { strcopy(cundlb,0,linout,&linptr); useul = TRUE; ul = TRUE; } } if (*(buff+i) == TOGBOLD && cboldb[0] != 0) { if (bd) { strcopy(cbolde,0,linout,&linptr); bd = FALSE; } else { strcopy(cboldb,0,linout,&linptr); usebd = TRUE; bd = TRUE; } } #endif } } /*# end if control character */ else { linout[linptr++] = *(buff+i); } ++xoutcm; } if (*(buff+chrptr-1)==BEGLINE) /* write whole line */ { last_col_out = linlen = min(tvcols,linptr-leftmg+1); if (linlen > 0) { tvlout(&linout[leftmg-1],linlen); } } else { linlen = min(tvcols-origx+1,linptr); last_col_out = linlen + origx - 1; if (linlen > 0) tvlout(linout,linlen); } #ifdef ULBD if (useul) sendcs(cundle); if (usebd) sendcs(cbolde); #endif } /* =============================>>> TVLOUT <<<============================= */ tvlout(chrbuf,lenbuf) char chrbuf[]; int lenbuf; { /* tvlout - intercepts tvcout calls to use line I/O */ if (!(echof && !bakflg)) return; ttwtln(chrbuf,lenbuf); /* write out whole line */ } /* =============================>>> TVTYPE <<<============================= */ tvtype(ibeg,icnt) int ibeg,icnt; { /* tytype - type icnt lines starting at lines[ibeg] no cr/lf on the last line */ FAST int i,lim; SLOW BUFFINDEX start; if (!echof) return; xoutcm=tvx; lim = ibeg+icnt-1; for (i = ibeg ; i<=lim && i>> SCRPRINT <<<============================= */ scrprint() { /* print screen on printer */ #ifndef UNIX SLOW beg, cnt; tvclr(); /* clear screen first */ finddl(&beg, &cnt); useprint = TRUE; /* enable printing */ tvtype(beg,cnt); /* and display/print */ printc(CR); /* force closing cr/lf */ #ifdef USELF printc(LF); #endif useprint = FALSE; #endif verify(1); /* reset screen */ } /* =============================>>> VERIFY <<<============================= */ verify(knt) int knt; { /* verify - rewrite the screen or type current line with cursor */ SLOW int xf; if (ttymode) ttyverify(knt); else { newscr(); xf = findx(); tvxy(xf,tvy); /* reset cursor to current position */ } } /* =============================>>> CSRCMD <<<============================= */ csrcmd() { ins_mode = FALSE; /* let world know in command mode */ sendcs(ccsrcm); } /* =============================>>> CSRINS <<<============================= */ csrins() { SLOW int oldx,oldy,oldxot; ins_mode = TRUE; /* in insert mode */ sendcs(ccsrin); if (tvdlin != tvhardlines) { oldx = tvx; oldy = tvy; oldxot = xoutcm; tvmsg("### Insert Mode ###",FALSE); tvxy(oldx,oldy); xoutcm = oldxot; } } /* ************************************************************************** tv screen primitives follow *************************************************************************** */ /* =============================>>> TVBOTB <<<============================= */ tvbotb(n) int n; { /* tvbotb - make n blank lines at the bottom of the screen */ FAST int i,j; /* All versions control sequences */ if (n >= tvlins) { tvclr(); } else { tvxy(1,tvhardlines); /* go to real last line */ for (i = 1 ; i <= n ; ++i) /* and write n blank lines */ sendcs(cbotb); j=tvlins-n+1; /* home to virtual last line */ tvxy(1,j); /* position at first new blank line */ } } /* =============================>>> TVCLR <<<============================= */ tvclr() { /* tvclr - clear the entire screen and home */ tvxy(1,1); tvescr(); } /* =============================>>> TVCOUT <<<============================= */ tvcout(chr) char chr; { /* tvcout - send one character to the terminal */ if (echof && !bakflg) ttwt(chr); } /* =============================>>> TVELIN <<<============================= */ tvelin() { /* tvelin - erase the rest of the current line */ sendcs(celin); } /* =============================>>> TVESCR <<<============================= */ tvescr() { /* tvescr - erase from current cursor position to end of screen */ SLOW int oldx,oldy; FAST int i; if (cescr[0]) sendcs(cescr); else { oldx = tvx ; oldy = tvy ; tvelin(); for (i = oldy+1 ; i <= tvhardlines ; ++i) { tvxy(1,i); tvelin(); } tvxy(oldx,oldy); } } /* =============================>>> TVINSL <<<============================= */ tvinsl() { /* tvinsl - insert line, handle virtual screen size */ SLOW int oldx,oldy; FAST int i; oldx = tvx ; oldy = tvy ; sendcs(ciline); if (tvlins != tvhardlines) { tvxy(1,tvlins+1); /* kill scrolled down line */ tvelin(); tvxy(oldx,oldy); } } /* =============================>>> TVTOPB <<<============================= */ tvtopb(n) int n; { /* tvtopb - create n blank lines at the top of the screen */ FAST int i; if (! ctopb[0]) return; tvxy(1,1); /* home first */ if ( n >= tvlins) tvescr(); /* simply erase the screen */ else { for (i = 1 ; i <= n ; ++i) sendcs(ctopb); if (tvlins != tvhardlines) { tvxy(1,tvlins+1); /* kill scrolled down line */ tvelin(); tvxy(1,1); } } } /* =============================>>> TVXY <<<============================= */ tvxy(ix,iy) int ix,iy; { /* tvxy - position cursor at position x,y x=0 is left most column y=0 is top most line */ #ifdef TERMCAP /* TERMCAP different */ tvx=ix; tvy=iy; tcapxy(ix,iy); /* call termcap version of xy */ #else /* generic version of tvxy */ SLOW int x,y, coord1, coord2; FAST int i; SLOW char chrrep[4]; x = min(ix+addx,tvcols+addx); /* column is addx */ y = iy+addy; /* same for row */ tvx = ix; tvy = iy; sendcs(cxybeg); /* opening control sequence */ if (cxy1st == 'l') { coord1 = y ; coord2 = x; } else { coord1 = x ; coord2 = y; } if (cxychr) { itoa(coord1,chrrep); sendcs(chrrep); } else tvcout(coord1); sendcs(cxymid); /* middle control sequence */ if (cxychr) { itoa(coord2,chrrep); sendcs(chrrep); } else tvcout(coord2); sendcs(cxyend); /* send terminating sequence */ #endif /* end of gerneric version */ } /* =============================>>> SENDCS <<<============================= */ sendcs(cs) char cs[]; { /* send a control sequencs to terminal */ FAST int i; #ifndef UNIX for (i = 0 ; cs[i] ; ++i) tvcout(cs[i]); #else /* unix version */ #ifdef TERMCAP /* termcap uses special output */ tcapcs(cs); /* send control string to termcap */ #else i = strlen(cs); tvlout(cs,i); #endif /* terminal specific unix version */ #endif /* end of unix version */ } /* =============================>>> GKBD <<<============================= */ gkbd(chr) char *chr; { /* gkbd - get one character from the keyboard */ #ifdef VB if (!bakflg) { #endif do { *chr = ttrd(); /* read only if non-backup version */ } while (*chr == 0); /* ignore EOS character */ #ifdef VB } else getbak(chr); putbak(*chr); /* save to backup file */ #endif } #ifndef UNIX /* =============================>>> TTWTLN <<<============================= */ ttwtln(chrbuf,len) char chrbuf[]; int len; { /* write one line to terminal, generic version, unix uses its own */ FAST int i; for (i = 0 ; i < len ; i++) ttwt(chrbuf[i]); } #endif #ifdef OSCPM /* ===========================>>> DISPCH <<<============================== */ dispch(chr) char chr; { bdos(2,chr); /* cp/m, ms-dos version */ } /* =============================>>> USER_1 <<<============================= */ user_1(knt) int knt; { knt = 0; return (TRUE); } /* =============================>>> USER_2 <<<============================= */ user_2(knt) int knt; { knt = 0; return (TRUE); } #endif #ifdef MSDOS #ifndef IBMPC /* ===========================>>> DISPCH <<<============================== */ dispch(chr) char chr; { bdos(2,chr); /* cp/m, ms-dos version */ } #endif /* =============================>>> USER_1 <<<============================= */ user_1(knt) int knt; { knt = 0; return (TRUE); } /* =============================>>> USER_2 <<<============================= */ user_2(knt) int knt; { knt = 0; return (TRUE); } #endif #ifdef GEMDOS /* ===========================>>> DISPCH <<<============================== */ dispch(chr) char chr; { gemdos(2,chr); /* cp/m, ms-dos version */ } /* =============================>>> USER_1 <<<============================= */ user_1(knt) int knt; { knt = 0; return (TRUE); } /* =============================>>> USER_2 <<<============================= */ user_2(knt) int knt; { knt = 0; return (TRUE); } #endif /* ---------------------------- tvx_io.c ------------------------------- */