home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- **
- ** pr2.c -- a new (better?) file paginator
- **
- ** usage:
- ** pr2 [options/filenames...]
- **
- ** options:
- ** -T <#> Set number of rows in the top margin.
- ** -B <#> Set number of rows in the bottom margin.
- ** -L <#> Set number of cols in the left margin.
- ** -R <#> Set number of cols in the right margin.
- ** -w <#> Set number of cols on a page.
- ** -l <#> Set number of rows on a page.
- ** -s <#> Set the line spacing.
- ** -p <#> Set the page number.
- ** -pr Set page numbering to roman numerals
- ** -pa Set page numbering to arabic numerals
- **
- ** -t#text Assign 'text' to title # and turn it on.
- ** -h#[yn] Turn title # on or off.
- ** -h#[tb][lcr]
- ** Set the position of the title: t=top,
- ** b=bottom, l=left, c=center, r=right.
- ** Examples: tc=top center, bl=bottom left.
- **
- ** -v Displays the version number of pr2. If
- ** this option is given and no files are
- ** specified on the command line, pr2 will
- ** quit immediately rather than wait for
- ** text from standard input.
- **
- ** $Revision: 2.2 $
- **
- ** $Author: jearls $
- ** $Date: 91/12/02 12:03:13 $
- **
- ** Modification History: $Log: pr2.c,v $
- ** Revision 2.2 91/12/02 12:03:13 jearls
- ** Added -v option
- **
- ** Revision 2.1 91/11/24 10:10:24 jearls
- ** Added -s option for line spacing.
- ** Added usage info to header for -t, -h, -s.
- **
- ** Revision 2.0 91/11/24 00:57:58 jearls
- ** Initial Revision
- **
- ***********************************************************/
-
- #include <stdio.h>
- #include <strings.h>
- #include <ctype.h>
-
- typedef struct Title
- {
- char *text;
- int pos; /* 1 = left, 2 = right, 3 = center */
- int header; /* 1 = header, 0 = footer */
- int flag; /* 1 = print, 0 = don't */
- } Title;
-
- typedef struct Page
- {
- int rows, cols, top, bottom, left, right;
- } Page;
-
- static Title titles[6] =
- {
- { "%f", 3, 1, 1 },
- { "- %p -", 3, 0, 1 },
- { "", 1, 1, 0 },
- { "", 2, 1, 0 },
- { "", 1, 0, 0 },
- { "", 2, 0, 0 }
- } ;
-
- static Page page = { 66, 80, 6, 6, 10, 10 };
-
- static int linenum = 0, charnum = 0,
- pagenum = 1, pageform = 1, /* 0 = roman, 1 = arabic */
- lineSpacing = 1;
- static char *curFilename, *progName, pagestr[10];
-
- char *strdup(char *s)
- {
- char *p;
-
- p = (char *)malloc(1+strlen(s));
- if (p)
- (void)strcpy(p, s);
- return(p);
- }
-
- char *instr(char *str, char *sub)
- {
- char *p, *q, *index();
-
- while (str = index(str, *sub))
- {
- p = str; q = sub;
- while (*(++q) && ((*++p) == (*q)));
- if (!(*q))
- return(str);
- str++;
- }
- return((char *)NULL);
- }
-
- char *subst(char *orig, char *old, char *new)
- {
- char *p, *q;
- int expand = strlen(new)-strlen(old) + 1;
-
- while(q = instr(orig, old))
- {
- p = (char *)malloc(strlen(orig) + expand);
- *q = '\0';
- (void)strcpy(p, orig);
- (void)strcat(p, new);
- (void)strcat(p, q+strlen(old));
- free(orig);
- orig = p;
- }
-
- return(orig);
- }
-
- void addTitle(char *line, Title title, int header)
- {
- char *txt, *p;
- int col, len;
-
- if ((title.flag) && (title.header == header))
- {
- txt = strdup(title.text);
- txt = subst(txt, "%f", curFilename);
- txt = subst(txt, "%p", pagestr);
- col = 0;
- if (title.pos != 1)
- col = page.cols - page.right - strlen(txt);
- if (title.pos == 3)
- col = (col - page.left) / 2;
- if (title.pos != 2)
- col += page.left;
- len = strlen(line);
- while (len < col)
- line[len++] = ' ';
- p = txt;
- while (*txt)
- line[col++] = *(txt++);
- if (col > len)
- line[col] = '\0';
- free(p);
- }
- }
-
- void addRoman(char **s, int num, int pos, char c1, char c5, char c10)
- {
- int dig = (num/pos) % 10;
-
- if (dig == 9)
- {
- *((*s)++) = c1;
- *((*s)++) = c10;
- } else
- if (dig == 4)
- {
- *((*s)++) = c1;
- *((*s)++) = c5;
- } else {
- if (dig > 4)
- *((*s)++) = c5;
- dig %= 5;
- while (dig--)
- *((*s)++) = c1;
- }
- }
-
- void roman(char *s, int num)
- {
- addRoman(&s, num, 1000, 'm', '?', '?');
- num %= 1000;
- addRoman(&s, num, 100, 'c', 'd', 'm');
- num %= 100;
- addRoman(&s, num, 10, 'x', 'l', 'c');
- num %= 10;
- addRoman(&s, num, 1, 'i', 'v', 'x');
- *s = '\0';
- }
-
- void print_header()
- {
- char *line;
- int lp;
-
- if (page.top > 1)
- {
- if (pageform)
- (void)sprintf(pagestr, "%d", pagenum);
- else
- roman(pagestr, pagenum);
-
- line = (char *)malloc(page.cols);
- *line = '\0';
-
- for (lp=0; lp<6; lp++)
- addTitle(line, titles[lp], 1);
-
- linenum = lp = (page.top - 1) / 2;
-
- while (lp--)
- putchar('\n');
-
- puts(line);
- free(line);
-
- linenum++;
- }
-
- while (linenum < page.top)
- {
- putchar('\n');
- linenum++;
- }
-
- charnum = 0;
- }
-
- void print_footer()
- {
- char *line;
- int lp;
-
- if (page.bottom > 1)
- {
- if (pageform)
- (void)sprintf(pagestr, "%d", pagenum++);
- else
- roman(pagestr, pagenum++);
-
- line = (char *)malloc(page.cols);
- *line = '\0';
-
- for (lp=0; lp<6; lp++)
- addTitle(line, titles[lp], 0);
-
- linenum += lp = page.bottom / 2;
-
- while (lp--)
- putchar('\n');
-
- puts(line);
- free(line);
-
- linenum++;
- }
-
- while (linenum < page.rows)
- {
- putchar('\n');
- linenum++;
- }
-
- linenum = charnum = 0;
- }
-
- void out(char c)
- {
- int lp;
-
- if ((isprint(c)) || (isspace(c)))
- {
- if ((c != '\014') && (linenum == page.rows - page.bottom))
- print_footer();
- if (linenum < page.top)
- print_header();
- if (isprint(c))
- {
- if (charnum == page.cols - page.right)
- out('\n');
- while (charnum < page.left)
- {
- putchar(' ');
- charnum++;
- }
- putchar(c);
- charnum++;
- } else
- switch(c)
- {
- case '\t' :
- out(' ');
- while ((charnum - page.left) % 8)
- out(' ');
- break;
- case '\r' :
- case '\013' :
- case '\n' :
- for (lp=lineSpacing; lp--;)
- {
- if (linenum == page.rows - page.bottom)
- {
- print_footer();
- print_header();
- }
- putchar('\n');
- linenum++;
- }
- charnum = 0;
- break;
- case '\014' :
- while (linenum < page.rows-page.bottom)
- out('\n');
- print_footer();
- break;
- }
- }
- }
-
- void doFile(char *fn)
- {
- int c;
- FILE *f;
-
- if (curFilename = fn)
- f = fopen(fn, "r");
- else
- {
- curFilename = "stdin";
- f = stdin;
- }
-
- if (f == (FILE *)NULL)
- perror(fn);
- else
- {
- while ((c = getc(f)) != EOF)
- out((char)c);
- if (linenum)
- out('\014');
-
- if (fn)
- fclose(f);
- }
- }
-
- void usage(char *err)
- {
- fprintf(stderr, "%s: %s\n", progName, err);
- exit(1);
- }
-
- int isnumber(char *s)
- {
- if (!(*s)) return(0);
- while ((*s) && (isdigit(*s))) s++;
- return(!(*s));
- }
-
- void main(int argc, char **argv)
- {
- int fileFlag = 0, tmp, tmp2;
- char buf[128], *p;
-
- progName = *argv;
-
- while (--argc)
- if (**(++argv) == '-')
- {
- switch((p = *argv)[1])
- {
- case 'T' :
- if (p[2])
- if (isnumber(p+2))
- page.top = atoi(p+2);
- else
- usage("-T : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- page.top = atoi(*argv);
- else
- usage("-T : Numeric argument needed.");
- else
- usage("-T : Numeric argument needed.");
- break;
-
- case 'B' :
- if (p[2])
- if (isnumber(p+2))
- page.bottom = atoi(p+2);
- else
- usage("-B : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- page.bottom = atoi(*argv);
- else
- usage("-B : Numeric argument needed.");
- else
- usage("-B : Numeric argument needed.");
- break;
-
- case 'L' :
- if (p[2])
- if (isnumber(p+2))
- page.left = atoi(p+2);
- else
- usage("-L : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- page.left = atoi(*argv);
- else
- usage("-L : Numeric argument needed.");
- else
- usage("-L : Numeric argument needed.");
- break;
-
- case 'R' :
- if (p[2])
- if (isnumber(p+2))
- page.right = atoi(p+2);
- else
- usage("-R : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- page.right = atoi(*argv);
- else
- usage("-R : Numeric argument needed.");
- else
- usage("-R : Numeric argument needed.");
- break;
-
- case 'l' :
- if (p[2])
- if (isnumber(p+2))
- page.rows = atoi(p+2);
- else
- usage("-l : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- page.rows = atoi(*argv);
- else
- usage("-l : Numeric argument needed.");
- else
- usage("-l : Numeric argument needed.");
- break;
-
- case 'w' :
- if (p[2])
- if (isnumber(p+2))
- page.cols = atoi(p+2);
- else
- usage("-w : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- page.cols = atoi(*argv);
- else
- usage("-w : Numeric argument needed.");
- else
- usage("-w : Numeric argument needed.");
- break;
-
- case 's' :
- if (p[2])
- if (isnumber(p+2))
- lineSpacing = atoi(p+2);
- else
- usage("-s : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- lineSpacing = atoi(*argv);
- else
- usage("-s : Numeric argument needed.");
- else
- usage("-s : Numeric argument needed.");
- break;
-
- case 'p' :
- if (p[2])
- if (p[2] == 'a')
- pageform = 1;
- else
- if (p[2] == 'r')
- pageform = 0;
- else
- if (isnumber(p+2))
- pagenum = atoi(p+2);
- else
- usage("-p : Numeric argument needed.");
- else if (argc--)
- if (isnumber(*(++argv)))
- pagenum = atoi(*argv);
- else
- usage("-p : Numeric argument needed.");
- else
- usage("-p : Numeric argument needed.");
- break;
-
- case 't' :
- if ((p[2] < '1') || (p[2] > '6'))
- {
- (void)sprintf(buf,
- "-t: %c: Illegal title specifier.", p[2]);
- usage(buf);
- }
-
- tmp = p[2] - '1';
- p += 3;
- if ((!(*p)) && (argc))
- {
- p = *(++argv);
- argc--;
- }
- if (!(*p))
- {
- fprintf(stderr,
- "Warning: no text given for title %d; ",
- tmp);
- fprintf(stderr,
- "turning title off and clearing.\n");
- titles[tmp].flag = 0;
- } else
- titles[tmp].flag = 1;
-
- titles[tmp].text = p;
- break;
-
- case 'h' :
- if ((p[2] < '1') || (p[2] > '6'))
- {
- (void)sprintf(buf,
- "-h: %c: Illegal title specifier.", p[2]);
- usage(buf);
- }
-
- tmp = p[2] - '1';
- switch (p[3])
- {
- case 'Y' :
- case 'y' : titles[tmp].flag = 1;
- tmp = -1; break;
- case 'N' :
- case 'n' : titles[tmp].flag = 0;
- tmp = -1; break;
- case 'T' :
- case 't' : titles[tmp].header = 1; break;
- case 'B' :
- case 'b' : titles[tmp].header = 0; break;
- default : sprintf(buf,
- "%s: Illegal title position.",
- *argv);
- usage(buf);
- }
-
- if (tmp > -1)
- switch(p[4])
- {
- case 'L' :
- case 'l' : titles[tmp].pos = 1; break;
- case 'R' :
- case 'r' : titles[tmp].pos = 2; break;
- case 'C' :
- case 'c' : titles[tmp].pos = 3; break;
- default : sprintf(buf,
- "%s: Illegal title position.",
- *argv);
- usage(buf);
- }
- break;
-
- case 'v' :
- puts("$Revision: 2.2 $");
- fileFlag = 1;
- break;
-
- case '\0' :
- doFile(NULL);
- fileFlag = 1;
- break;
-
- default :
- (void)sprintf(buf, "-%c : Unknown flag.", p[1]);
- usage(buf);
- }
- } else {
- doFile(*argv);
- fileFlag = 1;
- }
-
- if (!fileFlag)
- doFile(NULL);
- }
-