home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 19 Printer
/
19-Printer.zip
/
REV.ZIP
/
rev.c
< prev
next >
Wrap
Text File
|
1993-02-26
|
33KB
|
999 lines
#define VER "1.0"
/*
* Text REVerter T.J. Domsalla, dommi@rz.tu-clausthal.de Version 0.93,
* Clausthal, 1991, 1993
*/
#ifdef READTEST
#undef READTEST
#define READTEST 1
#else
#define READTEST 0 /* Eingabe gleich wieder ausgeben */
#endif
#ifdef WRITETEST
#undef WRITETEST
#define WRITETEST 1
#else
#define WRITETEST 0 /* Ausgabe der Seiten in Logfile */
#endif
char *version_string = "PAGE REVERTER V "VER", "__DATE__", "__TIME__"\n"
" (l) T.J. Domsalla, TU Clausthal, catd@rz.tu-clausthal.de\n";
/**************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include "getopt.h"
/**************************************************************************/
/* Environmentvariable f"ur vorbesetzte Optionen */
#define REV_ENV_VAR "REV_OPTS"
#define STD_LINES_PER_PAGE 65
#define STD_COLS_PER_LINE 80
#define STD_TABLENGTH 4
#define MAXPAGES 4096
#define MINPAGES 128
#define BUFFERSIZE 0x80000 /* Lesebuffer */
#define MINBUFFERSIZE 0x1000
/* mein Drucker Initialisierungsstring (HP Deskjet) f"ur undok. Option -~ */
#define PRTINITSTRING "E(s2q20h6V&l12d120F&a12l144M"
#define MY_LINES_PER_PAGE 119
#define MY_COLS_PER_LINE 120
typedef enum { FALSE, TRUE } Bool;
/**************************************************************************
* und einige systemspezifische Konstanten
*/
#define PROCESS_INDICATOR_CHANGE 100 /* nach wieviel eingelesenen
* Zeichen Processindikator
* "andern */
/**************************************************************************/
static void CtrlCExit (void);
static void finish (void);
static int readin (void);
static int writeout (void);
static int writepage (int page);
static int writeline (char *);
static int scanPageHeader(void);
static int calcTab (int col);
static int filelength (char *filename);
void show_process_indicator (void);
static void usage (void);
/**************************************************************************/
Bool LogProcess = FALSE; /* write log file */
Bool ExtHelp = FALSE; /* extended help */
Bool Verbose = FALSE; /* Verbose mode */
Bool Version = FALSE; /* Print Version */
Bool ForwardOutput = FALSE; /* not revert output */
Bool DSided = FALSE; /* double sided */
Bool Evenforward = FALSE; /* gerade Seiten vorw. */
Bool Evenbackward = FALSE; /* gerade Seiten r"uckw. */
Bool Oddforward = FALSE; /* ungerade Seiten vorw. */
Bool Oddbackward = FALSE; /* ungerade Seiten r"uckw. */
Bool WithFF = TRUE; /* Seitenende mit \f */
Bool NoLastFF = TRUE; /* bis auf nach letzter Seite */
Bool UndoCtrlChar = FALSE; /* Ctrl-Zeichen in '.' umwandeln */
Bool PrintInitStr = FALSE; /* f"ur meine HP DJ Initial. */
unsigned int LinesPPage = STD_LINES_PER_PAGE; /* Zeilen pro Seite */
unsigned int ColsPLine = STD_COLS_PER_LINE; /* Spalten pro Zeile */
int StartPage = 0; /* erste Ausgabeseite */
int EndPage = -1; /* letzte Ausgabeseite */
char *InitFile = NULL; /* Datei mit Initialisierungsstring */
char *InFile = NULL; /* Eingabedatei */
char *OutFile = NULL; /* Ausgabedatei */
char *PrgName;
FILE *Stream;
FILE *LogF;
char *Heading = NULL; /* Zeiger auf's Original"uberschrift */
char HeadString[512]; /* Platz f"ur "Uberschrift */
Bool PageNumbering = FALSE;
/* folgende $Strings werden in Seiten"uberschrift ersetzt (s. scanPageHeader()) */
char *HeadVars[] = { "FILE", "DATE", "LINE", "PAGE" };
#define HEAD_FILE 0
#define HEAD_DATE 1
#define HEAD_LINE 2
#define HEAD_PAGE 3 /* for page numbering */
unsigned long BufferSize = BUFFERSIZE;
char *Buffer = NULL;
unsigned int TabLength = STD_TABLENGTH;
unsigned int MaxPages = MAXPAGES; /* Maximalzahl Seiten */
unsigned int NPages = 0; /* gelesene Seiten */
char **Pages = NULL; /* Seitenzeigerliste */
/**************************************************************************/
/* f"ur und von getopt() */
/* hier mogle ich meine eigene Option -~ ein: HP DJ Initialisierungsstring */
char *goptVektor = "~?b:c:d.e:FghH:i:l:no:p:s:t:uvVx."; /* Optionsliste */
extern union gopt_Arg gopt_Argument; /* f"ur Optionsargument */
/**************************************************************************/
/*
* Ausgabe von Meldungen (Warnungen, Fehlermeldungen, Info) nach stdout
* und/oder (abh. von WRITE_LOGFILE) LogF
*/
char MsgString[2048];
#define PRINTMSG if(LogProcess) \
fputs( MsgString, LogF); \
fputs( MsgString, stderr)
/**************************************************************************/
int main (int argc, char *argv[])
{
char ch;
int i;
if (LogProcess)
/* LOG File "offnen */
LogF = fopen ("rev.log", "w");
/* bei CTRL-C Dateien sauber raus aus'm Programm */
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
signal (SIGINT, CtrlCExit);
PrgName = argv[0];
if (LogProcess)
{
/* Argumentstring ins Logfile schreiben */
for (i = 0; i < argc; i++)
{
fprintf (LogF, "%s ", argv[i]);
}
fputc ('\n', LogF);
}
/* Argument"ubergabe an das Programm auslesen */
for (i = 0, ch = getopt_env (REV_ENV_VAR, *argv);
i < 2;
ch = getopt (argc - 1, argv + 1, *argv), i++)
do
{
switch (ch)
{
case 'h':
ExtHelp = TRUE;
case '?':
usage (); /* Hilfe */
exit (0);
break;
case 'b': /* Buffer f"ur Eingabe */
BufferSize = atol (gopt_Argument.s);
if (BufferSize < MINBUFFERSIZE) /* wir wollen's nicht */
BufferSize = MINBUFFERSIZE; /* "ubertreiben! */
break;
case 'c': /* Zeilenl"ange */
ColsPLine = atoi (gopt_Argument.s);
break;
case 'd': /* double sided output */
switch (gopt_Argument.c)
{
case '0':
/* nur geradzahlige Seiten vorw"arts ausgeben */
Evenforward = TRUE;
break;
case '1':
/* nur ungeradzahlige Seiten r"uckw"arts ausgeben */
Oddbackward = TRUE;
break;
case '2':
/* nur geradzahlige Seiten r"uckw"arts ausgeben */
Evenbackward = TRUE;
break;
case '3':
/* nur ungeradzahlige Seiten vorw"arts ausgeben */
Oddforward = TRUE;
break;
default:
if (LogProcess)
fprintf (LogF, "Option -d : %c no permissible argument;"
" only 0, 1, 2 or 3 are allowed.\n",
gopt_Argument.c);
fprintf (stderr, "Option -d : %c no permissible argument;"
" only 0, 1, 2 or 3 are allowed.\n",
gopt_Argument.c);
exit (-6);
break;
} /* switch */
DSided = TRUE;
break;
case 'e': /* letzte Seite */
EndPage = atoi (gopt_Argument.s) - 1;
break;
case 'F':
ForwardOutput = TRUE;
break;
case 'g':
LogProcess = TRUE;
break;
case 'H': /* Headings */
Heading = gopt_Argument.s;
/* Scannen der "Uberschrift wird verschoben, bis bekannt
* ist, wieviel Zeilen pro Seite benutzt werden sollen;
* dann wird die Anzahl der "Uberschriftszeilen von dieser
* Angabe abgezogen. */
break;
case 'i': /* Datei mit Initialisierungsstring;
* wird vor Ausgabe ausgegeben */
InitFile = gopt_Argument.s;
break;
case 'l': /* Seitenl"ange */
LinesPPage = atoi (gopt_Argument.s);
break;
case 'n':
NoLastFF = FALSE;
break;
case 'o': /* Ausgabedatei */
OutFile = gopt_Argument.s;
break;
case 'p': /* max. Seitenzahl */
NPages = atoi (gopt_Argument.s);
if (MaxPages < MINPAGES)
MaxPages = MINPAGES;
break;
case 's': /* erste Seite */
StartPage = atoi (gopt_Argument.s) - 1;
if (StartPage < 0)
StartPage = 0;
break;
case 't':
TabLength = atoi (gopt_Argument.s);
break;
case 'x': /* \f an Seitenende? */
WithFF = gopt_Argument.c == '-' ? FALSE : TRUE;
if (gopt_Argument.c != '+' && gopt_Argument.c != '-')
sprintf (MsgString, "%s: -f%c not valid; formfeed switched ON.\n",
*argv, gopt_Argument.c);
PRINTMSG;
break;
case 'u':
UndoCtrlChar = TRUE;
break;
case 'v': /* Plappermaul */
Verbose = TRUE;
break;
case 'V': /* Version */
Version = TRUE;
break;
case '~':
/* my private cheating for my HP Deskjet, hehe! */
PrintInitStr = TRUE;
LinesPPage = MY_LINES_PER_PAGE;
ColsPLine = MY_COLS_PER_LINE;
break;
case GOPT_IS_SIMPLE_STRING: /* Eingabedateiname */
InFile = gopt_Argument.s;
break;
case GOPT_ERROR: /* Fehler */
usage ();
sprintf (MsgString, "Program aborted; wrong option\n");
PRINTMSG;
exit (5);
break;
default: /* H"AH? Ich nix verstehn ch */
break;
} /* endswitch */
}
while ((ch = getopt (0, NULL, *argv)) != GOPT_FINISHED);
if (ForwardOutput && DSided)
{
sprintf (MsgString, "%s: Can't use -F and -d# together. ABORT.\n", PrgName);
PRINTMSG;
exit (8);
}
#if WRITETEST
LogProcess = TRUE;
#endif
/*
* falls EndPage ein Wert zugewiesen wurde, ist dieser auch gr"o"ser als
* StartPage? Nein -> Abbruch!
*/
if (EndPage != -1)
{
if (EndPage < StartPage)
{
sprintf (MsgString, "%s: end page < start page: ABORT.\n", PrgName);
PRINTMSG;
exit (7);
}
}
if (InFile) /* Eingabedatei wurde angegeben */
{
if ((Stream = fopen (InFile, "r")) == NULL)
{
sprintf (MsgString, "%s: Can't open `%s' for reading\n",
PrgName, InFile);
PRINTMSG;
exit (2);
}
BufferSize = filelength (InFile) + 1;
}
else
Stream = stdin;
if ((Buffer = (char *)malloc (BufferSize)) == NULL)
{
sprintf (MsgString, "%s: Virtual memory exhausted\n", PrgName);
PRINTMSG;
exit (3);
}
if ((Pages = (char **)malloc (MaxPages + 1)) == NULL)
{
sprintf (MsgString, "%s: Virtual memory exhausted\n", PrgName);
PRINTMSG;
exit (3);
}
if (OutFile) /* Eingabedatei wurde angegeben */
{
/* Datei als Standardausgabe behandeln */
if (freopen (OutFile, "w", stdout) == NULL)
{
sprintf (MsgString, "%s: Can't open `%s' for writing\n",
PrgName, OutFile);
PRINTMSG;
exit (4);
}
}
if (Version && !Verbose)
fprintf (stderr, "This is Rev version " VER "\n%s", version_string);
sprintf (MsgString, "This is Rev version " VER "\n%s\n"
"lines/page : %d\t\tcols/line : %d"
"\ntab length : %d"
"\n"
"input : %s\n"
"output : %s\n"
"init file : %s\n"
"write log file : %s\n"
"start page : %d\t\tend page : %d\n"
"buffer size : %ld\tmax pages : %d\n"
"page header : %d lines\n"
"verbose : %s\t\tUndo CTRL chars : %s\n"
"extra formfeed : %s\t\\f after last page : %s\n"
"double sided : %s",
Version ? version_string : "",
LinesPPage, ColsPLine,
TabLength,
InFile ? InFile : "stdin", OutFile ? OutFile : "stdout",
InitFile ? InitFile : "--",
LogProcess ? "YES" : "NO",
StartPage + 1, EndPage != -1 ? EndPage + 1 : 99999,
BufferSize, MaxPages,
/* --> */Heading ? (i=scanPageHeader()) : (i=0),
Verbose ? "ON" : "OFF", UndoCtrlChar ? "ON" : "OFF",
NoLastFF ? "NO" : "YES", WithFF ? "ON" : "OFF",
DSided ? "ON" : "OFF");
if (LogProcess)
fputs (MsgString, LogF);
if (Verbose)
fputs (MsgString, stderr);
if (DSided)
sprintf (MsgString, "\toutput %s sides %s\n\n",
Evenforward || Evenbackward ? "EVEN" : "ODD",
Evenforward || Oddforward ? "FORWard" : "BACKWard");
else
sprintf (MsgString, "\n\n");
if (LogProcess)
fputs (MsgString, LogF);
if (Verbose)
fputs (MsgString, stderr);
/* Anzahl Zeilen der "Uberschrift abziehen */
LinesPPage -= i;
readin (); /* Datei bzw. Eingabe einlesen */
writeout (); /* Datei pervertiert ausgeben */
finish ();
}
/**************************************************************************/
static void CtrlCExit ()
{
fprintf (stderr, "\n\nAaaeerghhhrrrlllchh... KILLED!\n");
if (LogProcess)
fprintf (LogF, "\nProcess has been killed!\n");
finish ();
}
static void finish ()
{
if (Buffer)
free (Buffer);
if (Stream != stdin)
fclose (Stream);
fclose (stdout);
if (LogProcess)
/* LOG File schlie"sen */
fclose (LogF);
exit (0);
}
/**************************************************************************
*
* Datei oder aus Standardeingabe einlesen und bereits jetzt in Seiten
* gliedern.
*/
static int readin ()
{
int col; /* Zeichenz"ahler f"ur orig. Zeile */
int pos; /* Zeichenz"ahler f"ur neue Zeile */
unsigned int lines = 0; /* Zeilenz"ahler pro Seite */
unsigned int alllines = 0; /* Zeilen-Gesamtzahl */
unsigned long int restbufsize = BufferSize;
char *buf = Buffer;
Bool NEWLINE;
Bool NEWPAGE;
Pages[NPages++] = buf; /* erste Seite setzen */
if (Verbose && InFile)
fprintf (stderr, "Loading %s ... ", InFile);
while (!feof (Stream))
{
/* Zeile (i.allg. mit \n\0 abschlie"send) einlesen */
if (fgets (buf, restbufsize, Stream) == NULL)
break;
/*
* falls nichts mehr eingelesen wurde, weil Datei nicht mit Ctrl-Z
* abgeschlossen wurde, raus. Ist dies der Fall, denkt feof() nicht
* daran, 0 zur"uckzugeben ...
*/
if (!*buf)
break;
if (!(alllines % PROCESS_INDICATOR_CHANGE)
&& Verbose && InFile)
show_process_indicator ();
col = pos = 0;
while (buf[col] && restbufsize > 0)
{
NEWLINE = NEWPAGE = FALSE;
--restbufsize; /* BufferSize schrumpft mit */
#if READTEST
if (buf[col] != '\n')
fprintf (stderr, "%c", buf[col]);
#endif
switch (buf[col])
{
case '\t': /* Tabulator */
pos += calcTab (pos) + 1;
col++;
break;
case '\f':
if (buf[-1] == '\n') /* \n vor \f l"oschen */
{
strcpy (buf + col - 1, buf + col);
/* ggf. vorherigen Seitenwechsel vorschieben */
if (Pages[NPages - 1] == buf + col - 1)
Pages[NPages - 1] = buf + col - 2;
}
else
col++;
NEWLINE = TRUE;
NEWPAGE = TRUE;
break;
case '\n':
col++;
NEWLINE = TRUE;
break;
case '\b':
col++, --pos;
break;
default:
col++, pos++;
break;
} /* switch */
if (pos >= ColsPLine)
NEWLINE = TRUE;
if (NEWLINE)
{
#if READTEST
fprintf (stderr, "\n");
#endif
lines++, alllines++;
if (buf[col - 1] != '\f' && buf[col] == '\n') /* "uberfl"ussiges \n
* l"oschen */
buf[col] = '\0'; /* (tritt nicht bei \n auf!) */
if (lines >= LinesPPage)
NEWPAGE = TRUE;
pos = 0;
}
if (NEWPAGE)
{
#if READTEST
fprintf (stderr, "\n");
#endif
lines = 0;
Pages[NPages++] = buf + col;
if (NPages == MaxPages - 1)
{
sprintf (MsgString, "%s: Sorry - page number exceeded; use "
"-p with a higher value!", PrgName);
PRINTMSG;
exit (5);
}
}
} /* while buf[col] */
buf += col;
} /* while !feof */
Pages[NPages] = NULL; /* Seitenliste mit NULL abschlie"sen */
sprintf (MsgString,
"\r%d lines on %d page%s read\n",
alllines, NPages, NPages < 2 ? "" : "s");
if (LogProcess)
fputs (MsgString, LogF);
if (Verbose)
{
fputs (MsgString, stderr);
if (DSided && NPages % 2)
fprintf (stderr,
"\n* WARNING *: Odd number of pages; before printing with option d1\n"
"after printing with option d0 you should put an extra sheet of paper\n"
"on top of your output pile!\n\n");
}
if (Stream != stdin)
fclose (Stream);
if (LogProcess)
fprintf (LogF, "restbufsize = %d\n\n", restbufsize);
return 0;
}
/***************************************************************************/
#define NEXTODD(x) ((x)%2 ? (x)+1 : (x))/* gerade sind ungerade ... */
#define NEXTEVEN(x) ((x)%2 ? (x) : (x)+1)/* und umgekehrt (0,1,2...) */
#define PREVODD(x) ((x)%2 ? (x)-1 : (x))
#define PREVEVEN(x) ((x)%2 ? (x) : (x)-1)
/***************************************************************************/
static int writeout ()
{
int page;
int startpage;
/*
* VORSICHT: ich gebe zu, da"s die Namensgebung bescheuert gew"ahlt ist, habe
* aber keinen Bock, daran etwas zu "andern...: startpage gibt an, mit welcher
* Seite die Ausgabe starten soll, StartPage weist allerdings auf die erste
* physikalische Seite (EndPage auf die letzte phys. Seite). W"ahrend also
* Startpage immer < EndPage sein sollte, ist startpage bei der
* R"uckw"artsausgabe immer >= Endpage-1.
*/
if (PrintInitStr)
/* Drucker-Initialisierungsstring schreiben */
fputs (PRTINITSTRING, stdout);
/* ist eine Datei mit Initialisierungsstring angegeben? */
if (InitFile)
{
FILE *f;
char buf[512];
/* Initialisierungsdatei "offnen und lesen */
if ((f = fopen (InitFile, "r")) != NULL)
{
while (!feof (f))
{
if (fgets (buf, 512, f) == NULL)
break;
fputs (buf, stdout);
} /* while */
}
fclose (f);
}
if (EndPage == -1 || EndPage >= NPages)
EndPage = NPages - 1;
if (DSided) /* doppelseitiger Druck */
/* erste auszugebende Seite bestimmen (startpage) */
{
if (Evenforward)
startpage = StartPage ? NEXTEVEN (StartPage) : 1;
else if (Evenbackward)
/* NPages zeigt hinter letzte Seite (*0) */
startpage = EndPage ? PREVEVEN (EndPage) :
(NPages % 2 ? NPages - 2 : NPages - 1);
else if (Oddforward)
startpage = StartPage ? NEXTODD (StartPage) : 0;
else /* Oddbackward */
startpage = EndPage ? PREVODD (EndPage) :
(NPages % 2 ? NPages - 1 : NPages - 2);
if (Evenforward || Oddforward)
for (page = startpage; page <= EndPage; page += 2)
writepage (page);
else
for (page = startpage; page >= StartPage; page -= 2)
writepage (page);
if (LogProcess)
fprintf (LogF, "\noutput page %d to page %d\n",
startpage + 1, Evenforward || Oddforward ? EndPage + 1 : StartPage + 1);
}
else
/* kein doppelseitiger Druck */
{
if (ForwardOutput)
for (page = StartPage; page <= EndPage; page++)
writepage (page);
else
/* alle Seiten r"uckw"arts ausgeben */
for (page = EndPage; page >= StartPage; --page)
writepage (page);
if (LogProcess)
fprintf (LogF, "\noutput page %d to page %d\n", EndPage + 1, StartPage + 1);
if (Verbose)
fputc ('\n', stderr);
}
/* falls \f nach letzter gedruckter Seite erw"unscht */
if (!NoLastFF)
fputc ('\f', stdout);
return 0;
}
/***************************************************************************/
static int writepage (int page)
{
char ch = '\0';
char *buf;
static int calls = 1;
/*
* ist eine Seite bereits mit \f beended worden (Zeichen in Datei), ist kein
* weiterer Seitenvorschub notwendig
*/
static Bool DontWriteExtraFF = FALSE;
/*
* vor erster auszugebender Seite ist ebenfalls kein Seitenvorschub n"otig,
* nicht mal erw"unscht.
*/
static Bool FirstPage = TRUE;
if (Pages[page]) /* gibt's die Seite? */
{
if (LogProcess)
fputc ('[', LogF);
if (Verbose)
fputc ('[', stderr);
if (WithFF && !FirstPage && !DontWriteExtraFF)
fputc ('\f', stdout);
FirstPage = FALSE; /* ab jetzt kannste ruhig */
sprintf (MsgString, "%d", page + 1);
if (Verbose)
fputs (MsgString, stderr);
if (LogProcess)
fputs (MsgString, LogF);
if (Heading)
fprintf (stdout, HeadString, page+1);
if (Pages[page + 1])
ch = *Pages[page + 1], *Pages[page + 1] = '\0'; /* n"achste Seite soll ja
* nicht ausge- geben
* werden */
for (buf = Pages[page]; *buf; buf += writeline (buf))
fputc ('\n', stdout);
/* \f falls nicht sowieso schon \f geschrieben */
if (Pages[page + 1] && *(Pages[page + 1] - 1) == '\f')
DontWriteExtraFF = TRUE;
else
DontWriteExtraFF = FALSE;
if (LogProcess)
fputc (']', LogF);
if (Verbose)
fputc (']', stderr);
if (!(calls++ % 13))
{
if (LogProcess)
fputc ('\n', LogF);
if (Verbose)
fputc ('\n', stderr);
}
if (ch)
*Pages[page + 1] = ch;
}
return 0;
}
/**************************************************************************
* Schreibe Zeile; liefert Anzahl geschriebener Zeichen zur"uck
*/
static int writeline (char *buf)
{
char line[ColsPLine + 2]; /* nicht ANSI C konform! */
int i;
int col = 0; /* Eingabe-Index */
int pos = 0; /* Ausgabe-Index */
Bool EOL = FALSE;
/* Zeichenweise Zeile ausgeben */
if (buf)
{
for (; *buf && !EOL && pos < ColsPLine; buf++)
{
switch (*buf)
{
case '\t':
for (i = calcTab (pos); i >= 0; --i, pos++)
line[pos] = ' ';
col++;
break;
case '\n': /* beachten, aber nicht "ubernehmen */
EOL = TRUE;
break;
default:
if (iscntrl (*buf))
{
line[pos++] = UndoCtrlChar ? '.' : *buf;
col++;
}
else
case '\f':
case '\b':
line[pos++] = *buf; /* besser als Chaos drucken */
col++;
}
}
line[pos] = '\0';
fputs (line, stdout);
#if WRITETEST
if (LogProcess)
fputs (line, LogF);
fputs ("\n", LogF);
#endif
}
return EOL ? col + 1 : col;
}
/**************************************************************************
* Falls Seiten"uberschrift "ubergeben wurde, scannen und Anzahl der
* "Uberschriftzeilen zur"uckgeben.
* ^ wird als \n betrachtet, $DATE durch aktuelles Datum ersetzt und
* $FILE durch den mit -o "ubergebenen Dateinamen (oder `stdout'),
* $LINEdc gibt eine Linie aus d Zeichen c an;
* die zu ersetzenden Strings sind in HeadVars angegeben.
* Heading enth"alt die Originalangabe, die nach HeaderString kopiert
* bzw. umgewandelt wird.
*/
static int scanPageHeader()
{
int nchars = 511; /* remaining room for headline */
int hlines = 0; /* line counter of headline */
int i, j;
char *cp = Heading; /* -> original user string */
char *hsp = HeadString; /* -> resulting headline */
time_t t;
/* Zeichen f"ur Zeichen Heading scannen */
for ( ; *cp && nchars; cp++, hsp++, --nchars)
{
switch (*cp)
{
case '^': /* NEWLINE */
*hsp = '\n';
hlines++;
break;
case '$':
/* m"ogliche Formatanweisungen scannen */
for (i = 0; i < sizeof(HeadVars)/sizeof(char *); i++)
if (strstr(cp+1, HeadVars[i]) == cp+1)
break;
switch (i)
{
case HEAD_FILE:
strcpy( hsp, InFile ? InFile : "stdin");
hsp = strrchr(hsp, '\0')-1;
cp += strlen(HeadVars[HEAD_FILE]);
nchars -= strlen(InFile?InFile:"stdin")-1;
break;
case HEAD_DATE:
time( &t);
hsp += (i = strftime(hsp, nchars, "%a %x", localtime(&t)) )-1;
cp += strlen(HeadVars[HEAD_DATE]);
nchars -= i-1;
break;
case HEAD_LINE:
cp += strlen(HeadVars[HEAD_LINE])+1;
j = (j=atoi(cp)) ? j : ColsPLine;
while (isdigit(*cp)) /* hinter Zahl gehen */
cp++;
for (i=0; i<j; i++)
*hsp++=*cp, --nchars;
--hsp, nchars++;
break;
case HEAD_PAGE:
PageNumbering = TRUE;
cp += strlen(HeadVars[HEAD_PAGE]);
strcpy( hsp, "%d");
hsp++, --nchars;
break;
default :
*hsp = '$';
break;
}
break;
default :
*hsp = *cp;
break;
} /* switch */
} /* while */
*hsp = '\0'; /* HeadString abschliessen */
return hlines+1;
}
/**************************************************************************
* Tabulator in Spalte actcol in Anzahl von Leerzeichen umrechnen;
* bis zum n"achsten Tabstop und maximal bis zum Zeilenende.
* col wird ab 0 gez"ahlt.
* Es wird die Anzahl-1 der zu setzenden Leerzeichen zur"uckgegeben.
*/
static int calcTab (int col)
{
int nspaces = TabLength - col % TabLength - 1;
return col + nspaces >= ColsPLine ? ColsPLine - col - 1 : nspaces;
}
/**************************************************************************
* Die kleine nette Spielerei mit dem laufenden Rad
*/
void show_process_indicator (void)
{
static int status = 0;
char part[] = "|/-\\";
status %= sizeof (part);
fprintf (stderr, "\b%c", part[status++]);
}
/**************************************************************************/
static int filelength (char *filename)
{
struct stat infstat;
stat (filename, &infstat);
return infstat.st_size;
}
/**************************************************************************/
static void usage ()
{
/*
* Hilfetext nach stdout, nicht nach stderr, ausgeben, so da"s man sich den
* Text auch seitenweise beispielsweise mit more anzeigen l"a"st.
*/
fprintf (stdout, "%s\n"
"Reverts ASCII text for printing (last page first, first page last)\n"
" with option for double sided printing (on HP Deskjet for example)\n\n"
"USAGE: %s [fname] [-?] [-h] [-v] [-F] [-x{-|+}] [-n]\n"
"\t [-H page_heading] [-o outfile] [-d{0|1|2|3}] [-l lines]\n"
"\t [-c cols] [-s start_page] [-e end_page] [-i init_file]\n"
"\t [-V] [-u] [-t tab_length] [-b buffer_size] [-p pages]\n"
"\t-?\tthis help\n"
"\t-h\textended help\n"
"\t-c\tcolumns per line (%d)\n"
"\t-l\tlines per page (%d)\n"
"\t-o\toutput file name (stdout)\n"
"\t-v\tverbose\n"
"\tfname\tinput file\n",
version_string, PrgName,
STD_LINES_PER_PAGE, STD_COLS_PER_LINE);
if (ExtHelp)
fprintf (stdout,
"\t-b\tsize of stdin read in buffer (%ld)\n"
"\t-d\toutput for double sided printing\n"
"\t 0\t print even sides forward\n"
"\t 1\t print odd sides backward\n"
"\t 2\t print even sides backward\n"
"\t 3\t print odd sides forward\n"
"\t-e\tlast (end) page (end of document)\n"
"\t-F\tforward output (OFF)\n"
"\t-g\twrite log file\n"
"\t-H\theader on pages (max. 512 chars)\n"
"\t `^' NEWLINE, `$DATE' date of output,\n"
"\t `$FILE' filename of -o option, `$PAGE' page numbering\n"
"\t `$LINEdc' d chars of c (for example: $LINE10-)\n"
"\t-i\tprint text from init_file before output\n"
"\t-n\tno \\f after last printed page (%s)\n"
"\t-p\tmax number of pages (%d)\n"
"\t-s\tfirst (start) page (1)\n"
"\t-t\ttab length (%d)\n"
"\t-u\tundo Ctrl characters (convert to `.')\n"
"\t-V\tprint version\n"
"\t-x\textra formfeed after page end (%s)\n"
"\t -\t OFF\n"
"\t +\t ON\n",
BUFFERSIZE,
NoLastFF ? "YES" : "NO",
MAXPAGES,
STD_TABLENGTH,
WithFF ? "ON" : "OFF");
}
/**************************************************************************/