/* ---------------------------------------------------------------------- MFPRINT.C a Multi-File Print Program Pat Warnshuis 1-503-246-3724 December 23, 1986 Portland Atari Club ---------------------------------------------------------------------- See also: MFPRINT.H and MFPRINT.DOC link as a stand-alone module */ #include #include #include "mfprint.h" main(argc, argv) char *argv[]; int argc; { struct FDTA dta; char cmdname[64], filename[64], *s, c ; int i, j, rderror, fileid; setbuf(stdout, 0); /* disable buffered io */ init(); /* check printer, set defaults */ /*G if last argv starts with '-', process cmd line switches H */ j = argc-1; if( argv[j][0] == '-' ) { doarg(argv[j]); argc--; } /*G list all other argv's as files, allowing for wildcards H */ for( j = 1; j < argc ; j++ ) { if( argv[j][0] == '-' ) { doarg(argv[j]); continue; } abortfile = FALSE; strcpy(filename, argv[j]); i = strlen(filename); /* strip trailing ',' */ if( filename[i] = ',' ) filename[i] = '\0'; s = filename; /* strip leading ' ' */ while( *s++ == ' ' ) for( i = 0; i <= strlen(filename) ; i++) filename[i] = filename[i+1]; /* find first entry for argv[j] */ Fsetdta(&dta); while( (rderror = Fsfirst(filename, 0x0010)) < 0 ) { getfname(filename); /* if bad, get new filename */ if( abortfile ) break; Fsetdta(&dta); /* clear rderror, try again */ } /*G list all matching files for argv[j] H */ if( abortfile ) break; while( !rderror ) { /*G convert dta.name to full pathname\filename H */ for( i = strlen(filename); i > 0; i--) if( (filename[i]=='\\') || (filename[i]==':') ) break; if( i > 0 ) { if( filename[i] == ':' ) filename[++i] = '\\' ; filename[++i] = '\0'; } filename[i] = '\0'; strcat(filename, dta.name); /*G open and list this file H */ fileid = openfn(filename); if( abortfile ) break; listfile(dta.name, dta.size, fileid); Fclose( fileid ); rderror = Fsnext(); /* any more files for argv[j]? */ } } show("\n\nAll done! Hit any key"); Cnecin(); exit(0); } /* ------------------------G doarg() H--------------------------------*/ /* process command line switches, allowing for loose syntax */ doarg(switches) char switches[]; { int i, chcnt; char c, str[64], *s; strcpy(str, switches); s = str; while( (c = *s++) ) { if( isdigit(c)) break; switch ( toupper(c) ) { case ',': case '-': case ' ': break; case 'C': lststr(CONDPRT); ltmarg = CONDLM; rtmarg = CONDRM; break; case 'E': lststr(ELITEPRT); ltmarg = ELITELM; rtmarg = ELITERM; break; case 'P': pageflag = FALSE; case 'H': hdrflag = FALSE; break; case 'T': tabspc = stoi(s); break; case 'L': ltmarg = stoi(s); break; default : usage(c); crsron(); s = str; *s ='\0'; egets("Please reenter switches (^C to abort): ", s, 64); crsroff(); if( *s == ABORT ) exit(0); break; } } } /* ------------------------G usage() H--------------------------------*/ /* display help screen for command line switches */ usage(c) char c; { clrscrn(); crsroff(); show("\n\nUnknown switch: "); revvid(); Bconout(CON, ' '); Bconout(CON, c); Bconout(CON, ' '); norvid(); show("\n\nUsage: MFPRINT [D:]FILENAME.EXT "); show("[-[P C H Ln Tn Nn] ]\n\n"); show(" DEFAULT\n"); show(" C = condensed (16 cpi) elite\n"); show(" H = header each page yes\n"); show(" Ln = left margin n 12 => 1 inch\n"); show(" Tn = tabs set at n spcs 8 \n"); show(" P = paging OFF ON\n"); show("\n\n"); } /* -----------------------G openfn() H--------------------------------*/ /* if cannot open file, allow user to enter new filename or to abort */ openfn(fname) char *fname; { char *s; int openok, fileid; openok = FALSE; while( !openok ) { s = fname; /* ensure all upper case filename */ while( *s = (char)(toupper(*s)) ) s++; if( (fileid = Fopen(fname, 0)) >0 ) openok = TRUE; else getfname(fname); if( abortfile ) break; } return ( fileid ); } /*---------------------------G getfname()H --------------------------*/ /* ask for new filename if new filename contains wildcard or open pathname show directory ask for new filename if new filename is null, abort */ getfname(fname) char *fname; { int chcnt, dir; char *s, c; clrscrn(); show("\n\nCould not open for input: "); revvid(); show(fname); norvid(); showat(" Your options are: ", 4,11); showat(" 1. Enter a complete pathname with filename", 6,11); showat(" 2. Enter a wild card name to show directory",7,11); showat(" 3. Enter to exit the program", 8,11); crlf();crlf();crsron(); chcnt = egets("Enter filename: ", fname, 40); crsroff(); if( !chcnt || fname[0] == ABORT ) abortwhat(0); dir = FALSE; s = fname; while( (c = *s++) ) if( (c=='*') || (c=='?') ) dir = TRUE; s -= 2; c = *s; if( (c=='\134') || (c==':') ) { strcat(fname, "*.*"); dir = TRUE; } if( dir ) { do_dir(fname); goxy(25,0);crsron(); chcnt = egets("Enter filename (wildcards ok): ", fname, 40); crsroff(); if( !chcnt || fname[0] == ABORT ) abortwhat(0); } } /* -----------------------G do_dir H--------------------------------*/ /* display directory for new device, pathname, or wildcard filename */ /* skip obvious binary files */ do_dir(fname) char *fname; { struct FDTA dta; char fext[4]; int i, rdstat, files, line, col; long *size; BOOLEAN isbin; clrscrn(); crsroff(); norvid(); show("Directory: "); show(fname); show("\n---------------------------------------------------------------"); show("\nFile Name Ext Size File Name Ext Size"); show("\n---------------------------------------------------------------"); line = 5; col = 0; files = 0; Fsetdta(&dta); rdstat = Fsfirst(fname,0x0010); while( (rdstat >= 0) && ( files++ < 64 ) ) { for(i = 0; i < 13 && dta.name[i] != '.'; i++ ) ; /* find ext */ if( dta.name[i] == '.' ) { dta.name[i++] = '\000'; /* name str */ strcpy(fext, &dta.name[i]); isbin = ( !strcmp(fext, "PRG") || !strcmp(fext, "TOS") || !strcmp(fext, "TTP") || !strcmp(fext, "RSC") || !strcmp(fext, "O" )); } else isbin = FALSE; if( !isbin && dta.name[0] != '.' ) { showat(dta.name, line, col); showat(fext, line, col+10); goxy(line, col+15); if(dta.attr == 0x10) show(" "); else show(ultosj(dta.size, 6)); if(line++ == 23) { line = 5; col += 27; } } rdstat = Fsnext(); } } /* ------------------------G listfile() H----------------------------*/ /* allocate & free memory for filesize */ /* read file in largest block allowed by memsize */ listfile(fname, fsize, fileid) char *fname; long fsize; int fileid; { register char *s; register long bytecnt; register int col; register char c; char header[80]; long memsize, buffsize; int nbuff, k, memfree, lncnt, pagelen; strcpy(header, "Printing "); strcat(header, fname); strcat(header, " Filesize = "); strcat(header, ultosj(fsize, 7)); show(header); crlf(); lststr(CRLF); col = 1; lncnt = TPMARG; pgcnt = 1; pagelen = PAGELN - BTMARG; /*G build static header -- avoid scanf()H */ strcpy(header, gettime()); strcat(header, " "); strcat(header, fname); strcat(header, " page "); dotitle(header); k = 3; while( k-- ) lststr(CRLF); lstspcs(ltmarg); /*G allocate memory in largest buffer available for filesize H */ nbuff = 1; buffsize = fsize; memsize = Malloc(-1L); if(memsize < 1024L) errexit("\nNOT ENOUGH MEMORY! "); if(memsize < fsize) { nbuff = (int)(fsize/memsize) + 1; buffsize = fsize/(nbuff-1); } buffsize = (buffsize + 0x400) & 0xFFFFFC00; buff = (char *)(Malloc(buffsize)); /* Gfill and list buffers until file is finished H */ while( nbuff-- ) { bytecnt = Fread(fileid, buffsize, buff); if( !nbuff ) Fclose(fileid); if( bytecnt == 0L ) break; s = buff; /* Gprocess single character... eol can be '\n' or CRLF H */ while( bytecnt-- ) { c = *s++; if( isprint(c) ) lst(c); else switch (c) { case CR: break; /* just count char */ case LF: col += rtmarg; /* force new line */ break; case TAB: k = tabspc - (col % tabspc); lstspcs(k); col += k-1; break; case FF: formfeed = TRUE; /* finish line */ break; case ESC: lst(c); /* printer control */ break; default: c = '~'; lst(c); break; } /* new line? */ if( ++col > rtmarg ) { if( Bconstat(CON) ) if( (c=Bconin(CON)) == ABORT ) abortwhat(); if( (++lncnt > pagelen) || formfeed ) { if( pageflag ) newpage(header); lncnt = TPMARG; } lststr(CRLF); lstspcs(ltmarg); col = 1; } if( abortfile ) break; } if( abortfile ) break; } lst(FF); if( buff ) { memfree = Mfree(buff); buff = 0L; } abortfile = FALSE; } /* ------------------------G newpage() H------------------------------*/ /* formfeed. If header flag set, list date/time, title & page number */ newpage(header) char *header; { int i; lststr(PGEJECT); pgcnt++; if( hdrflag ) { dotitle(header); i = TPMARG - 3; } else i = TPMARG -1; while( i-- ) lststr(CRLF); formfeed = FALSE; } /* -----------------------G dotitle() H-------------------------------*/ /* list time/date, filename, page number */ dotitle(header) char *header; { lststr(CRLF); lstspcs( rtmarg - strlen(header) - ltmarg ); lststr(BOLDON); lststr(header); lststr(uitosj(pgcnt, 3)); lststr(BOLDOFF); } /* -----------------------G gettime() H-------------------------------*/ /* return system time/date as "HH:MM MM/DD/YEAR" with '0' fills */ char *gettime() { static char time[20]; int i; strcpy(time, uitosj(HR, 2)); strcat(time, ":"); strcat(time, uitosj(MIN, 2)); strcat(time, " "); strcat(time, uitosj(MO, 2)); strcat(time, "/"); strcat(time, uitosj(DAY, 2)); strcat(time, "/"); strcat(time, uitosj(YR + 1900, 4)); /* replace blanks with '0' */ for( i=0 ; i < 5 ; i++) if(time[i] == ' ') time[i] = '0'; for( i=7 ; i < 10 ; i++) if(time[i] == ' ') time[i] = '0'; return( time ); } /* ------------------------G initialization H-----------------------*/ /* assign printer port, check printer on, set defaults */ init() { char c; hidems();clrscrn(); lstport = Setprt(-1); if( lstport & 0x0010 ) lstport = AUX; else lstport = PRT; while( !Bcostat(lstport) ) { revvid(); show("\n TURN THE PRINTER ON, HIT ANY KEY (^C ABORT)"); norvid(); if( (c=Bconin(CON)) == ABORT ) exit(0); crlf(); } tabspc = TABSPC; /* Set up default values */ ltmarg = ELITELM; rtmarg = ELITERM; lststr(ELITEPRT); pageflag = TRUE; hdrflag = TRUE; formfeed = FALSE; abortfile = FALSE; buff = 0L; } /* ------------------------G printer routines H----------------------*/ /* list(char), list(string), list(n spaces) */ /* if printer goes off line, check for user abort */ lst(c) char c; { while( !Bcostat(lstport) ) if( Bconstat(CON) ) if( (c=Bconin(CON)) == ABORT ) abortwhat(); Bconout(lstport, c); } lststr(s) char *s; { while( *s ) lst(*s++) ; } lstspcs(i) int i; { while( i-- ) lst('\040'); } /* ------------------------G egets H------------------------*/ /* get string with editing as in dialog box */ int egets(prompt, response, lim) char *prompt, response[]; int lim; { int c, i; show(prompt); /* display prompt string */ i = 0; while( c = response[i++] ) Bconout(CON, c); /* display default string */ i--; /* i = char_cnt of resp */ while( (c = Bconin(CON)) != '\r' ) { switch( c ) { case ESC : while( i-- > 0) show("\010\040\010"); i = 0; break; case BS : if( i > 0 ) { show("\040\010"); i--; } break; default : if( i < lim ) response[i++] = c; else Bconout(CON, '\007'); break; } } response[i] = '\0'; /* ignore CR, add NULL */ return(i); } /* ------------------------G screen display H----------------------*/ clrscrn() { show("\033E"); } crsron() { show("\033e"); } crsroff() { show("\033f"); } revvid() { show("\033p"); } norvid() { show("\033q"); } crlf() { show("\015\012"); } goxy(x,y) int x,y; { show("\033Y"); Bconout(CON, (char)(x+32)); Bconout(CON, (char)(y+32)); } show(s) char *s; { char c; while( c = *s++ ) if( c==LF ) { Bconout(CON, CR); Bconout(CON, LF); } else Bconout(CON, c); } showat(s,x,y) char *s; int x, y; { goxy(x,y); show(s); } /* ------------------------G conversions H------------------------*/ /* I hate printf() and scanf() !! */ /* atoi() does not handle int embedded in string as in switches */ stoi(s) char *s; { int rval; rval = 0; while( isdigit(*s) ) rval = rval * 10 + *s++ - '0'; return( rval ); } /* long-to-string, justified in field width < 25 */ char *ltosj(n, fwd) long n; int fwd; { static char rstr[25]; char *s, sign; s = rstr; sign = ' '; if( n<0 ) { n = -n; sign = '-'; } while( fwd-- ) *s++ = ' '; *s-- = '\0'; do ( *s-- = n%10 + '0' ); while( (n /= 10) > 0 ); *s = sign; return( rstr ); } /* int-to-string, justified in fieldwidth of fwd */ char *itosj(n, fwd) int n, fwd; { char *s; s = ltosj( (long)(n), fwd ); return( s ); } /* unsigned long-to-string, justified -- no leading sign char */ char *ultosj(n, fwd) long n; int fwd; { static char rstr[25]; char *s; s = rstr; while( fwd-- ) *s++ = ' '; *s-- = '\0'; do ( *s-- = n%10 + '0' ); while( (n /= 10) > 0 ); return( rstr ); } /* unsigned int-to-string, justified -- no leading sign char */ char *uitosj(n, fwd) int n, fwd; { char *s; s = ultosj( (long)(n), fwd); return( s ); } /* ------------------------G miscellaneous H-----------------------*/ /* display error message; wait for keyboard; exit */ errexit(s) char *s; { show(s); Cnecin(); abort(0); } abortwhat() { char c ; show("\n\nAbort all (A) or only this file (F)? "); c = Bconin(CON); if( toupper(c) == 'A' ) abort(); else abortfile = TRUE; } /* if mem allocated, free memory; if printer on, flush buffer; exit */ abort() { if( buff ) Mfree(buff); if( Bcostat(lstport) ) lststr(CRLF); showms(); exit(0); } debug(s1, s2) char *s1, *s2; { char c; crlf(); show(s1); show(s2); show("\n....any key... ^C to abort\n"); if( (c=Bconin(CON)) == ABORT ) abort(); }