/**** **** pp Amiga PagePrint Program **** Version 1.0 ****/ /*** *** (C) Copyright 1986 Phil Mercurio (Quicksilver Software) *** All Rights Reserved *** *** This software is released as a shareware product. It may *** be copied providing that no charge is made to the recipient *** and that this copyright notice remains intact. *** *** If you use and find value in this software, please send $10 *** to the author at this address: *** *** Phil Mercurio *** Quicksilver Software *** 2515 #9 Camino Del Mar *** Del Mar, CA 92014 *** *** Be sure to include your name and address, as this will place *** you on the Quicksilver Software mailing list. Your support *** of shareware products will encourage the further production *** of low-cost software. ***/ /** ** pp.c ** ** PagePrint program. Prints text files with a date/time header, ** page breaks, and line numbers. Options include turning off or ** varying the line numbers & adding a copyright notice as a footer. ** This program is intended to be run from the CLI. ** ** Basic usage: ** ** pp {flags} files ** ** ** Flags: ** ** -c Insert copyright notice ** -d Debugging turned on (not useful for the end-user) ** -n Set increment for numbered lines; if followed by 0, ** a non-numeric argument, or no argument at all, causes ** line numbers to be inhibited. ** -q Suppress messages of current file being printed ** -? Prints Help Message ** ** Flags may appear anywhere on the command line. ** ** ** Examples: ** ** pp pp.c || prints this source code file with line numbers ** || every 5th line ** pp -qc pp.c pp.h || prints two source code files, with line ** || numbers & copyright footer, with no status ** || messages to screen ** pp -n 1 pp.c || prints pp.c with every line numbered ** pp -n pp.c || prints pp.c with no line numbers ** ** Configuring This Program For Your Needs ** ** PP gets most of the information it needs from your printer preferences, ** specifically the left and right margin and number of lines. However, ** there are several constants and strings which you may change to ** configure the output to your taste. All of these constants are grouped ** together at the beginning of the header file "pp.h". By modifying ** these constants and recompiling, you can adjust the spacing around ** the header and footer, the highlighting used to accentuate the line ** numbers, and several other features. One constant you'll definitely ** want to change is "OwnerName", which contains the name to be inserted ** in the copyright notice. The comments in "pp.h" should help. ** ** ** Quicksilver Software ** PJM 860212 Created ** PJM 860213 -n & -c working ** PJM 860216 -l working ** PJM 860307 Removed wildcard expansion (installed "shell" instead) ** PJM 860504 Made copyright notice legal ** PJM 860808 Removed dependency on "arrange" text formatter; ** renamed "-l" as "-n" and added "-d" and "-q". ** PJM 860811 Version 1.0 released as a shareware product. **/ #include "pp.h" main(ac,av) int ac; char **av; { register int i; #ifdef Trace printf("main(%d,%lx)\n",ac,av); #endif Trace initialize(); parseArgs(ac,av); configure(); for(i=0; i < NFiles; i++) { if(!Quiet) fprintf(stderr,"Printing file \"%s\" ... ",FileName[i]); pp(FileName[i]); if(!Quiet) fprintf(stderr,"done.\n"); } finalize(); } /* * Initialize the internal state variables */ initialize() { #ifdef Trace printf("initialize()\n"); #endif Trace Enable_Abort = 1; IntuitionBase = xOpenLibrary("intuition.library",0); CopyRight = No; Debug = No; Quiet = No; NFiles = 0; LineCount = 5; GetPrefs(&Prefs,sizeof(Prefs)); LeftMargin = Prefs.PrintLeftMargin; LineWidth = Prefs.PrintRightMargin - Prefs.PrintLeftMargin - Indent; LinesPerPage = Prefs.PaperLength - NonBody; } /* * Parse the argument list. File names are added to the * FileName array and NFiles is incremented. */ parseArgs(ac,av) int ac; char **av; { register char *p; #ifdef Trace printf("parseArgs(%d,%lx)\n",ac,av); #endif Trace strcpy(MyName,av[0]); for(ac--, av++; ac > 0; ac--, av++) { if(av[0][0] == '?' && av[0][1] == 0) helpArgs(); if(av[0][0] == '-') { for(p=&av[0][1]; *p; p++) switch(*p) { case '?': helpArgs(); break; case 'c': case 'C': CopyRight = Yes; break; case 'd': case 'D': Debug = Yes; break; case 'n': case 'N': if(ac > 1 && IsDigit(av[1][0])) { ac--; av++; LineCount = atoi(av[0]); } else LineCount = 0; break; case 'q': case 'Q': Quiet = Yes; break; default: fprintf(stderr,"%s: unknown flag '%c'\n",MyName,*p); exit(0); } } else { strcpy(FileName[NFiles],av[0]); NFiles++; } } } /* * Print out a help message and exit. */ helpArgs() { int c; #ifdef Trace printf("helpArgs()\n"); #endif Trace puts(" PagePrint program. Prints text files with a date/time header,"); puts(" page breaks, and line numbers. Options include turning off or"); puts(" varying the line numbers & adding a copyright notice as a footer."); puts(" This program is intended to be run from the CLI."); puts(""); puts(" Basic usage:"); puts(""); puts(" pp {flags} files"); puts(""); puts(" Flags:"); puts(""); puts(" -c Insert copyright notice (Note: Change owner name in pp.h)"); puts(" -n Set increment for numbered lines; if followed by 0,"); puts(" a non-numeric argument, or no argument at all, causes"); puts(" line numbers to be inhibited."); puts(" -q Suppress messages of current file being printed"); puts(" -? This Help Message"); puts(""); puts(" Flags may appear anywhere on the command line."); pauseHelp(); puts(""); puts(" Examples:"); puts(""); puts(" pp pp.c || prints this source code file with line numbers"); puts(" || every 5th line"); puts(" pp -qc pp.c pp.h || prints two source code files, with line "); puts(" || numbers & copyright footer, with no status"); puts(" || messages to screen"); puts(" pp -n 1 pp.c || prints pp.c with every line numbered"); puts(" pp -n pp.c || prints pp.c with no line numbers"); pauseHelp(); printf("%c0;32;40m",CSI); /* Fore: 2 Back: 0 */ puts(" PP (PagePrint)"); puts(" ) Copyright 1986 Phil Mercurio (Quicksilver Software)"); puts(" All Rights Reserved"); printf("%c0;31;40m",CSI); /* Fore: 1 Back:0 (Normal) */ pauseHelp(); puts(" This software is released as a shareware product. It may"); puts(" be copied providing that no charge is made to the recipient"); puts(" and that this copyright notice remains intact."); puts(""); puts(" If you use and find value in this software, please send $10"); puts(" to the author at this address:"); puts(""); puts(" Phil Mercurio"); puts(" Quicksilver Software"); puts(" 2515 #9 Camino Del Mar"); puts(" Del Mar, CA 92014"); puts(""); puts(" Be sure to include your name and address, as this will place"); puts(" you on the Quicksilver Software mailing list. Your support"); puts(" of shareware products will encourage the further production"); puts(" of low-cost software."); exit(0); } /* * Pause the help print out, exit if RETURN not pressed. */ pauseHelp() { printf("%c0;33;40m",CSI); /* Fore: 3 Back: 0 */ puts(" Press RETURN to continue\n"); printf("%c0;31;40m",CSI); /* Fore: 2 Back:0 (Normal) */ if(getchar() != 0xA) exit(0); } /* * Configure global variables based on the parsed arguements. */ configure() { #ifdef Trace printf("configure()\n"); #endif Trace if(Debug) Prt = stdout; else Prt = xopen("prt:","a"); if(Debug) { fprintf(stderr,"Debugging ON\n"); fprintf(stderr,"LeftMargin = %d\n",LeftMargin); fprintf(stderr,"LineWidth = %d, LinesPerPage = %d\n", LineWidth, LinesPerPage); } buildFooter(); } /* * Build the copyright footer. */ buildFooter() { register int i; char buf[StrSiz]; int y,m,d,wd; for(i=0; i < LineWidth; i++) Footer[i] = ' '; Footer[i] = 0; DateStamp(&Now); parseDate(&Now,&y,&m,&d,&wd); sprintf(buf,"(C) Copyright %d",y); insStr(Footer,buf); insStr(&Footer[(LineWidth - strlen(OwnerName))/2],OwnerName); insStr(&Footer[LineWidth - strlen(AllRights)],AllRights); } /* * Pretty-print the file file. */ pp(file) char *file; { FILE *fp; #ifdef Trace printf("pp(%s)\n",file); #endif Trace getFIB(file, &FIB); dateStr(Date,&(FIB.fib_Date)); timeStr(Time,&(FIB.fib_Date)); fp = xopen(file,"r"); buildHeader(file,Date,Time); ppFile(fp); fclose(fp); } /* * Build the header for the file "file". The date and time of the file * are used in the header. */ buildHeader(file,date,time) char *file, *date, *time; { register int i; static char buf[StrSiz]; for(i=0; i < LineWidth; i++) Header[i] = ' '; Header[i] = 0; buf[0] = 0; strcat(buf,date); strcat(buf," "); strcat(buf,time); insStr(Header,buf); insStr(&Header[(LineWidth - strlen(file))/2],file); insStr(&Header[LineWidth - strlen(PageTemplate)],PageTemplate); } /* * Copy the file into Prt from in. Lines longer than LineWidth chars * are split up, with the continuation lines preceeded by Arrow. * Line numbers are inserted every LineCount lines, if LineCount > 0. */ ppFile(in) FILE *in; { Line = 1; Page = 1; RealLine = 0; beginPage(); while(fillBuf(in)) { writeLine(); while(emptyBuf()) /* null body */ ; Line++; } putLines(LinesPerPage - RealLine); endPage(); } /* * Fill the input buffer from the file in. Returns Yes if successful, * No otherwise. */ fillBuf(in) FILE *in; { #ifdef Trace printf("fillBuf()\n"); #endif Trace if(fgets(Buf1,BufSiz,in) == NULL) return(No); else { expandTabs(Buf1,Buf2); BufPtr = Buf2; return(Yes); } } /* * Expand the tabs in in, copying the string to out. Also removes * the terminating newline and checks for buffer overflow. Overflowing * lines are truncated. */ expandTabs(in,out) char *in, *out; { register int i; #ifdef Trace printf("expandTabs(%s,%s)\n",in,out); #endif Trace i = 0; while(!IsEndOfBuffer(*in) && i < BufSiz-1) { if(*in == '\t') { in++; do { *out++ = ' '; i++; } while(i % TabStop != 0); } else { *out++ = *in++; i++; } } *out = 0; } /* * Begin a new page by outputting the PreHeader lines, the Header, * and the PreBody lines. */ beginPage(fp) FILE *fp; { register int i; #ifdef Trace printf("beginPage()\n"); #endif Trace putLines(PreHeader); putSpaces(Indent); sprintf(&Header[LineWidth - NPageChars],PageNumFmt,Page); fprintf(Prt,"%s\n",Header); putLines(PreBody); } /* * End a page by outputting the PreFooter and PostFooter lines, * and the Footer, if CopyRight is Yes, else the appropriate number * of blank lines. */ endPage() { register int i; #ifdef Trace printf("endPage()\n"); #endif Trace putLines(PreFooter); if(CopyRight) { putSpaces(Indent); fprintf(Prt,"%s\n",Footer); } else { putLines(NLFooter); } putLines(PostFooter); } /* * Write out the first physical line from Buf2, checking for * the need to put out the line number and/or start a new page. */ writeLine() { register int i; char lineNum[Indent+1]; #ifdef Trace printf("writeLine()\n"); #endif Trace if(RealLine == LinesPerPage) { endPage(); Page++; beginPage(); RealLine = 0; } if(LineCount != 0 && Line % LineCount == 0) { sprintf(lineNum,LineNumFmt,Line); putPrefix(lineNum); } else { putSpaces(Indent); } for(i=0; !IsEndOfBuffer(*BufPtr) && i < LineWidth; i++, BufPtr++) putc(*BufPtr,Prt); putLines(1); RealLine++; } /* * Write out the next LineWidth characters from BufPtr, preceeding it * with an Arrow. We have to check for the need to page break before * outputting. No is returned when BufPtr is exhausted, Yes otherwise. */ emptyBuf() { register int i; #ifdef Trace printf("emptyBuf()\n"); #endif Trace if(IsEndOfBuffer(*BufPtr)) return(No); if(RealLine == LinesPerPage) { endPage(); Page++; beginPage(); RealLine = 0; } putPrefix(Arrow); for(i=0; i < LineWidth && !IsEndOfBuffer(*BufPtr); i++, BufPtr++) putc(*BufPtr,Prt); putLines(1); RealLine++; return(Yes); } /* * Output the prefix to Prt, using the highlighting commands * as defined in pp.h. If the highlighting commands are NULL, * they are not output, otherwise they're preceeded by an ESCAPE. */ putPrefix(p) char *p; { #ifdef Trace printf("putPrefix(%s)\n",p); #endif Trace if(!IsEndOfBuffer(*HiLiteOn)) fprintf(Prt,"%c%s",ESC,HiLiteOn); fprintf(Prt,"%s",p); if(!IsEndOfBuffer(*HiLiteOff)) fprintf(Prt,"%c%s",ESC,HiLiteOff); } /* * Put n spaces to Prt. */ putSpaces(n) int n; { #ifdef Trace printf("putSpaces(%d)\n",n); #endif Trace while(n--) putc(' ',Prt); } /* * Put n blank lines to Prt. */ putLines(n) int n; { #ifdef Trace printf("putLines(%d)\n",n); #endif Trace while(n--) putc('\n',Prt); } /* * Open a file with mode mode, printing an error message if unsuccessful. */ FILE * xopen(file,mode) char *file, *mode; { FILE *fp; fp = fopen(file,mode); if(fp == NULL) { fprintf(stderr,"%s: unable to open file \"%s\"\n",MyName,file); exit(0); } return(fp); } /* * Open a library, printing an error message if unsuccessful. */ LONG xOpenLibrary(lib,version) char *lib; int version; { LONG libPtr, OpenLibrary(); libPtr = OpenLibrary(lib,0); if(libPtr == NULL) { fprintf(stderr,"Unable to open library \"%s\"\n",lib); exit(0); } return(libPtr); } /* * Print out the argument list. */ dbArgs(ac,av) int ac; char **av; { register int i; for(i=0; i < ac; i++) printf("%s ",av[i]); printf("\n"); } /* * Finalize the program by closing printer. */ finalize() { #ifdef Trace printf("finalize()\n"); #endif Trace if(!Debug) fclose(Prt); } /* * Insert the string from in the string to, but do not terminate * with 0. */ insStr(to,from) char *to, *from; { while(!IsEndOfBuffer(*from)) *to++ = *from++; }