home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1997 February
/
PCWK0297.iso
/
technika
/
simic
/
pspage.c
< prev
next >
Wrap
Text File
|
1993-11-10
|
11KB
|
348 lines
/* ======== PSpage - a page manipulation program ======== */
/*
* Copyright 1991, 1990 by Adobe Systems Incorporated. All rights reserved.
*
* This file may be freely copied and redistributed as long as:
* 1) This entire notice continues to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* ************************************************************************
* THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
* NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
* INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
* LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
* KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
* AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* ************************************************************************
*/
/*
* SUMMARY:
* This program will manipulate a properly formatted PostScript document,
* that is, one that complies with the Adobe Document Structuring Conventions.
* Given the simplicity of this program, it is really only interested in the
* following comments;
* %!PS-Adobe-X.x
* %%EndSetup
* %%Page:
* %%Trailer
*
* OPTIONS:
* p - allows a range of pages to be specified in the form
* of a list separated by commas. E.g. 4,5-13,22
* Ranges can be specified forwards, e.g. 5-13, or backwards, e.g. 13-5
* r - will cause PSpage to page reverse the document.
*
* DEFAULTS:
* If options are not specified, all pages are output without page reversal.
*
* KNOWN BUGS:
* For page reversal: PSpage does not check the %%Pages: comment to see if
* the second argument is a 0, which indicates that page order should not
* be changed.
*
* PSpage does not handle included documents, that would be better serviced
* by a proper state machine implementation.
*
* Specifying an open range (e.g. 5-) to indicate that the current page until
* the end of the document is desired but is not supported.
*
* THINGS TO TWEAK:
* ** MAXPAGES defines the maximum number of pages that can be reversed
* ** MAXRANGES defines the maximum number of ranges that can be specified
* ** In the #include section, the file <stdarg.h> may be <varargs.h> or
* <sys/varagrs.h> on your system.
*
* CHANGE HISTORY:
* 90-June-01 orthlieb created
* 91-June-05 mackay incorporated comments; made lines < 80 chars;
* 91-Sept-26 mackay added comment on #include <stdarg.h>
*/
/* ----------------------- includes ----------------------*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
/* ------------------------ defines ----------------------*/
#define TRUE 1
#define FALSE 0
#define VERBOSE TRUE
#define TERSE FALSE
#define error printf
/* MAXPAGES defines the maximum number of pages that can be reversed */
#define MAXPAGES 100
/* MAXRANGES defines the maximum number of ranges that can be specified */
#define MAXRANGES 25
/* ----------------------- typedefs --------------------- */
typedef char bool;
/* ------------------------ globals ----------------------*/
long pageloc[MAXPAGES];
int numpages;
bool pagereverse = FALSE; /* Default: No page reversal */
char *pageranges[MAXRANGES];
int numranges = 0;
FILE *infile, *outfile;
/* ------------------------ externs ----------------------*/
extern void find_page_locations(FILE *thefile);
extern void output_document(FILE *infile, FILE *outfile);
extern void check_args(int numargs, char **args);
/* ----------------------- mainline ----------------------*/
void main (int argc, char **argv)
{
/* Setup page ranges */
numranges = 1;
pageranges[0] = "*";
pageranges[1] = NULL;
check_args(argc, argv);
find_page_locations(infile);
rewind(infile);
output_document(infile, outfile);
}
void print_instructions(bool howlong)
{
error("PSpage [-p <pages>] [-r] <infile> <outfile>\n");
if (howlong == TERSE) return;
error("This program will manipulate a properly formatted PostScript\n");
error("document, that is, one that complies with the Adobe Document\n");
error("Structuring Conventions. \n\n");
error("Options:\n");
error("p - allows a range of pages to be specified in the form\n");
error(" of a list separated by commas. E.g. 4,5-13,22\n");
error(" Ranges can be specified forwards, e.g. 5-13,\n");
error(" or backwards, e.g. 13-5\n");
error("r - will cause PSpage to page reverse the document.\n\n");
error("Defaults:\n");
error("If options are not specified, all pages are output");
error(" without page reversal\n\n");
error("Known Bugs:\n");
error("For page reversal: PSpage does not check the %%Pages: comment\n");
error("to see if the second argument is a 0, which indicates that page\n");
error("order should not be changed.\n");
error("PSpage does not handle included documents, that would be better\n");
error("serviced by a proper state machine implementation.\n");
}
void check_args(int numargs, char **arg)
{
int mark;
char *cmd;
/* Check to see if long instructions are desired */
if (numargs < 2 || arg[1][0] == '?') {
print_instructions(VERBOSE);
exit(0);
}
if (numargs < 3) {
error("PSpage ERROR: Not enough arguments\n");
print_instructions(TERSE);
exit(0);
}
mark = 1;
while(mark < numargs) {
/* If we've found a command */
if (arg[mark][0] == '-') {
for (cmd = &arg[mark][1]; *cmd != '\0'; cmd++) {
/* Scan the arguments */
switch (*cmd) {
case 'p': /* Page number list */
error("PSpage STATUS: using page range option.\n");
/* The next argument must be a list of page ranges */
/* Breakout the page ranges into individual tokens */
numranges = 0;
pageranges[numranges++] = strtok(arg[mark+1],",");
while ((pageranges[numranges++] = strtok(NULL,",")) != NULL);
numranges--; /* Reset to reflect actual number of ranges */
mark++; /* move to next token */
break;
case 'r': /* Page reversal desired */
error("PSpage STATUS: performing page reversal.\n");
pagereverse = TRUE;
break;
default:
error("PSpage ERROR: invalid option\n");
print_instructions(TERSE);
exit(-1);
break;
}
}
}
else {
if (infile == NULL) {
if ((infile = fopen(arg[mark],"rb")) == NULL) {
error("PSpage ERROR: cannot open input file %s.\n",arg[mark]);
exit(-1);
}
}
else {
if ((outfile = fopen(arg[mark],"wb")) == NULL) {
error("PSpage ERROR: cannot open output file %s.\n",arg[mark]);
exit(-1);
}
}
}
mark++;
}
}
int check_comment(char *str, int numargs, ...)
{
va_list ap;
char *comment;
va_start(ap, numargs);
while (numargs-- > 0) {
comment = va_arg(ap, char *);
if (strncmp(str, comment, strlen(comment)) == 0) {
va_end(ap);
return TRUE;
}
}
va_end(ap);
return FALSE;
}
void find_page_locations(FILE *thefile)
{
int i;
bool endoffile = FALSE;
long oldpos = 0;
char buf[256];
char *junk;
while (endoffile == FALSE) {
/* Save our current position */
oldpos = ftell(thefile);
/* Get a line from the file */
if (fgets(buf, 256, thefile) == NULL) {
/* No %%Trailer, No %%EOF */
if (!pageloc[numpages]) pageloc[numpages] = oldpos;
endoffile = TRUE;
}
else {
/* Check to see if we've found a comment */
if (buf[0] == '%' && buf[1] == '%') {
/* Check for the Page comment, record the location */
if (check_comment(buf, 1, "%%Page:") == TRUE) {
/* Note the location of this page */
pageloc[numpages++] = oldpos;
}
/* Check for the trailer or EOF to see if it's time to leave */
if (check_comment(buf, 2, "%%Trailer", "%%EOF") == TRUE) {
/* End of the last page */
pageloc[numpages] = oldpos;
endoffile = TRUE; /* No use searching any more */
}
}
}
}
if (numpages == 0) {
error("PSpage ERROR: No %%%%Page: comments in this document.\n");
exit(-2);
} else {
error("PSpage STATUS: This document has %d pages.\n", numpages);
}
}
void find_page_parms(char *range, int *start, int *end)
{
char *pdash = NULL;
int temp;
if (range[0] == '*') {
*start = 1;
*end = numpages;
}
/* Single number */
else if ((pdash = strchr(range,'-')) == NULL) {
*start = *end = atoi(range);
}
else {
/* Range of numbers */
*pdash++ = '\0';
*start = atoi(range); *end = atoi(pdash);
}
if (*start < 1 | *end < 1 | *start > numpages | *end > numpages) {
error("PSpage ERROR: page range is invalid [%d-%d].\n", start, end);
exit(-3);
}
(*start)--; (*end)--;
/* Pull a little sneaky to help with page reversal */
if (pagereverse == TRUE) {
temp = *start; *start = *end; *end = temp;
}
}
void print_page(FILE *infile, FILE *outfile, int page)
{
long i;
if (fseek(infile, pageloc[page], SEEK_SET) != 0) {
error("PSpage ERROR: Seek at position %d, page %d\n",
pageloc[page], page+1);
exit(-2);
}
for (i = pageloc[page]; i < pageloc[page+1]; i++)
fputc(fgetc(infile), outfile);
}
void output_document(FILE *infile, FILE *outfile)
{
char c;
int pagestart, pageend, pageincr, rangeindex, rangeincr;
long i;
register int r, p;
/* Print out the top of the file */
for (i = 0; i < pageloc[0]; i++)
fputc(fgetc(infile),outfile);
/* Now start the page manipulations */
/* Flip the order of ranges for page reversal */
rangeincr = 1; rangeindex = 0;
if (pagereverse == TRUE) {
rangeincr = -1;
rangeindex = numranges - 1;
}
for (r = rangeindex; r < numranges && r >= 0; r += rangeincr) {
find_page_parms(pageranges[r], &pagestart, &pageend);
/* Print out each individual page */
if (pagestart > pageend)
for (p = pagestart; p >= pageend;p--)
print_page(infile, outfile, p);
else
for (p = pagestart; p <= pageend; p++)
print_page(infile, outfile, p);
}
/* Now print out the end of the file */
if (fseek(infile, pageloc[numpages], SEEK_SET) != 0) {
error("PSpage ERROR: Seek at position %d while writing trailer %d\n",
pageloc[numpages]);
exit(-2);
}
while ((c = fgetc(infile)) != EOF)
fputc(c,outfile);
}