/* Datei: pr.c, Ausgeben von Kat-Ce und ASCII-Dateien
 *
 * (c) Andreas Pidde
 *     Vor dem Sauerwassertor 7
 *     D - 5400 Koblenz-Ehrenbreitstein
 *
 *     Tel: (02 61) 7 16 41
 *
 * pr-Version vom 07. Mai 1990 (release 1.0)
 *
 * Compiler: Aztec-C V3.6A
 * Aufruf: cc pr.c -Z3072
 *         ln -o pr -lc
 */


/* Includes */

#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <clib/macros.h>

#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>


/* Konstanten-Deklarationen */

/* Einige besondere Zeichen */
#define NUL   '\0'
#define FF    ((char) 12)
#define ESC   '\033'
#define LF    '\n'
#define TAB   '\t'
#define BLANK ' '

#define TABSIZE  8	/* Default-Tabulator-Groesse */
#define MAXTAB  30	/* Maximale Tabulatorgroesse */

/* Moegliche Ausgabemodi */
#define NO_FF   0	/* LF zwischen Dateien */
#define END_FF  1	/* FF am Ende einer Datei */
#define BTWN_FF 2	/* FF zwischen zwei Dateien */
#define PRT_FF  3	/* Seitenformatierung */
#define NOTH_FF 4	/* Nichts zwischen den Dateien */

#define OUTPUTLEN 99	/* Stringlaenge, Output-Filename */

/* BOOLean Type */
#ifndef BOOL
#  define BOOL int
#endif
#ifndef TRUE
#  define TRUE 1
#endif
#ifndef FALSE
#  define FALSE 0
#endif


/* Makros */

/* Warten auf RETURN */
#define waitCR() { char c; while ((c = getchar()) != '\n'); }

/* Regulaeres Ende */
#define fini() cleanExit("Finished! ", 0)


/* Deklaration der externen Variablen */

/* Aztec-C : ^C Sbfrage an (!=0) , aus (==0) */
extern short Enable_Abort;

/* Amiga */
extern struct IconBase *IconBase;	/* icon.library */
extern struct WBStartup	*WBenchMsg;	/* WB-StartUp */


/* Definition globaler Variablen */

/* fuer WB-StartUp */
struct FileLock		*startLock, *newLock;	/* FileLocks der WB-Args */
BOOL	wbToolStdio = FALSE,	/* stdio-Fenster von TOOL TYPE */
	wbHasStdio = FALSE,	/* WB-Startup, stdio-Fenster vorhanden */
	fromWB = FALSE;		/* von WB gestartet */

char	*conSpec = "CON:0/0/640/200/PR";	/* Normales stdio-Fenster */

/* CLI-Optionen als Strings */
char	ffstr[]		= "-f",
	btwnstr[]	= "-b",
	prtstr[]	= "-p",
	nothstr[]	= "-0",

	manstr[]	= "-man",
	banstr[]	= "-ban",

	tabstr[]	= "-t",

	hdrstr[]	= "-h",
	empstr[]	= "-e",
	ulstr[]		= "-u",
	numlstr[]	= "-n",
	stepstr[]	= "-s",

	jumpstr[]	= "-j",
	quitstr[]	= "-q",
	lineffstr[]	= "+l",
	linestr[]	= "-l",
	pgstr[]		= "-pg",
	widstr[]	= "-w",
	offstr[]	= "-o",
	upperstr[]	= "-i",

	replstr[]	= "-r",
	sinstr[]	= "-stdin", /* Gleichzeitig init fuer sname */
	katstr[]	= "-k";

/* WB-Optionen, Werte als Strings */
char	FORMAT[]	= "FORMAT",
	BANNER[]	= "BANNER",
	FILETYPE[]	= "FILETYPE",
	TABCONV[]	= "TABCONV",
	LINENUMBERING[]	= "LINENUMBERING",
	LINESTART[]	= "LINESTART",
	LINESTEP[]	= "LINESTEP",
	FORMFEED[]	= "FORMFEED",
	LINES[]		= "LINES",
	LINEWID[]	= "LINEWID",
	LINEIND[]	= "LINEIND",
	PAGELEN[]	= "PAGELEN",
	TOP[]		= "TOP",
	START[]		= "START",
	HEADER[]	= "HEADER",
	OUTPUT[]	= "OUTPUT",
	END[]		= "END",

	NOTHING_A[]	= "NOTHING",
	AFF_A[]		= "AFF",
	BFF_A[]		= "BFF",
	PRINT_A[]	= "PRINT",
	LF_A[]		= "LF",
	TEXT_A[]	= "TEXT",
	KATCE_A[]	= "KATCE",
	PLAIN_A[]	= "PLAIN",
	BOLD_A[]	= "BOLD",
	ULINED_A[]	= "ULINED",
	TRUE_A[]	= "TRUE",
	FALSE_A[]	= "FALSE";

int	ff;	/* NO_FF  : Kein Formfeed ( Linefeed am Dateiende)
		 * END_FF : Formfeed am Dateiende
		 * BTWN_FF: Formfeed zwischen den Dateien
		 * PRT_FF : Druckaufbreitung (Seitenkopf 60 Zeilen)
		 * NOTH_FF: Zwischen den Dateien nichts ausgeben
		 */

int	charcnt,	/* Zeichenzaehler */
	lncnt,		/* Zeilenzaehler */
	sline,		/* Startzeile */
	ssize,		/* Schrittweite beim Zeilenzaehlen */
	tabsize,	/* Tabulargroesse (8) */
	start,		/* Start bei Seite n */
	endpage,	/* Ende bei Seite n */
	pgcnt,		/* Seitenzaehler */
	lines,		/* Zeilen pro Seite drucken */
	pglen,		/* Groesse einer Seite */
	lwid,		/* Zeilenbreite */
	offs,		/* linker Rand */
	upper;		/* oberer Rand */

unsigned int	plncnt;		/* gedruckter Zeilenzaeher */

char	*date,		/* fuer Datum */
	*fname,		/* aktueller Dateiname */
	*sname,		/* Name fuer stdin */
	output[OUTPUTLEN+1]; /* Ausgabe (wenn WB-Start, def: PRT:) */

BOOL	tabconv,	/* Tabulator -> Blank */
	lineno,		/* Zeilennummerierung an */
	katce,		/* Eingabe aus einer Kat-Ce-Datei */
	formf,		/* Nach einer Seite ff ausgeben */
	emp,		/* Header ist Bold */
	ul,		/* Header unterstrichen */
	hdr,		/* Header drucken */
	banner,		/* Titelseite drucken */
	betw_ff,	/* FormFeed zwischen zwei Dateien */

	stdin_set;	/* -stdin in argv-Liste gefunden */

FILE	*file;	/* Eingabedatei */


/* fuer Kopien */
int	ff_s;

int	charcnt_s,
	lncnt_s,
	sline_s,
	ssize_s,
	tabsize_s,
	start_s,
	endpage_s,
	pgcnt_s,
	lines_s,
	pglen_s,
	lwid_s,
	offs_s,
	upper_s;

unsigned int	plncnt_s;

char	*date_s,
	*fname_s,
	*sname_s,
	output_s[OUTPUTLEN+1];

BOOL	tabconv_s,
	lineno_s,
	katce_s,
	formf_s,
	emp_s,
	ul_s,
	hdr_s,
	banner_s,
	betw_ff_s;


/* Benutzerhinweise */
char	*usage[] = {
  /* Copyright */
  "pr, (c) 07-MAY-90 by Andreas Pidde, this program is Public Domain\n",
    
  /* SYNOPSIS */
  "SYNOPSIS:",
  "  pr [-f] [-b] [-p] [-0] [-h] [-u] [-e] [-k]",
  "     [-ban] [-man]",
  "     [-t [<n>]] [-n [<n>]] [-s [<n>]]",
  "     [+l [<n>]] [-l [<n>]]",
  "     [-o <n>] [-w <n>] [-pg <n>]",
  "     [-j <n>] [-q <n>] [-i <n>]",
  "     [-r [<name>]] [-stdin] [<filelist>]\n",
     
  "pr -man: printing manual to standard-output\n",    
   
  "ASCII- or Kat-Ce-files are printed out, FormFeeds are recognized.",
  "Files not found are skipped.\n",
   
  "" /* Endmarker */
};

/* Weiterfuehrende Benutzerhinweise */
char	*manual[] = {
    "\npr-Manual, CLI",
    "==============\n",
    
    "-f     : formfeed (FF) after each document, 72 lines/page (DIN A 4)",
    "-b     : FF between documents, 72 lines/page",
    "-p     : printer-output (header, 60(+2) lines/page, FF)",
    "-0     : nothing is done between files, 72 lines/page",
    "no opt : linefeed (CRLF) after each document\n",
    
    "-k     : read Kat-Ce-textfiles\n",

    "-ban   : (banner) print title-page\n",
    
    "-h     : don't print header (-p)",
    "-e     : (emphasized) boldfaced header (-p)",
    "-u     : underlined header (-p)\n",

    "-t <n> : set tab-size (1 <= n <= 30, default is 8)",
    "-t     : disable tab to blank conversion",
    "On default, tabs are replaced by maximal 8 blanks\n",
    
    "-n [<n>] : enable linenumbering, starting at <n>,",
    "           n >= 0, default is 1",
    "-s [<n>] : enable linenumbering,",
    "           set stepsize for linenumbering, n >= 1, default is 1",
    "Linenumbering is 5 digits wide, two characters are",
    "left blank between number and textline. On default",
    "no linenumbering is done.\n",
    
    "+l [<n>] : <n> lines/page (without header), FF",
    "-l [<n>] : <n> lines/page (without header), page filled with CRLF\n",

    "-w <n>   : linewidth <n> chars (without numbering, indent), def.: 80",
    "-o <n>   : (offset) indent <n> chars, def.: 0",
    "-pg <n>  : set pagehight, def.: 72\n", 

    "-j <n>   : (jump) starts output at page <n>",
    "-q <n>   : (quit) ends output after page <n>",
    "-i <n>   : inserts <n> blank lines at top of page",

    "-r [<name>] : replaces \'-stdin\' as <name>",
    "-stdin   : read from standard-input, (EOF by CTRL-\\)",
    "           You don't need to set this, if you use pipe or redirection.",
    "filelist : textfile(s) for input, wildcards: *, ?\n",
    
    "output is written to standard output file",
    "output to printer by >prt:\n",
    
    "Valid are the last options found.\n\n",
    
    "pr-Manual, WorkBench",
    "====================\n",
    
    "First click the files you want to print out, then double-click",
    "the PR-Icon, don't forget to press the <Shift>-Key",
    "during the whole action.\n",
    
    "PR may be a DEFAULT TOOL of a PROJECT, too.\n",

    "Following TOOL TYPES are valid (all possible values are shown,",
    "the argument shown on the first place is default):\n",
    

    "WINDOW=CON:<x0>/<y0>/<wid>/<ht>/<name>",
    "FORMAT=LF|AFF|BFF|PRINT|NOTHING",
    "BANNER=FALSE|TRUE",
    "FILETYPE=TEXT|KATCE",
    "HEADER=FALSE|TRUE|BOLD|ULINED|PLAIN",
    "TABCONV=TRUE|FALSE|<n>                     : standard <n> = 8",
    "LINESTART=<n>                              : <n> = 1",
    "LINESTEP=<n>                               : <n> = 1",
    "LINENUMBERING=FALSE|TRUE",    
    "FORMFEED=FALSE|TRUE",
    "LINES=<n>                                  : <n> = 72",
    "LINEWID=<n>                                : <n> = 80",
    "PAGELEN=<n>                                : <n> = 72",
    "TOP=<n>                                    : <n> = 0",
    "LINEIND=<n>                                : <n> = 0",
    "START=<n>                                  : <n> = 1",
    "END=<n>                                    : <n> = 32767",
    "OUTPUT=<filename>                          : <filename> = PRT:\n",

    "These options correspondent to the ones of the CLI-called PR.",
    "OUTPUT sets OUTPUT-file, the OUTPUT-file will be rewritten.",
    "The WINDOW TOOL TYPE (standard-IO-window) has to be set, e.g.:",
    "WINDOW=CON:0/0/640/200/pr\n",

    "BUGS:",
    "  My bad english...\n",

    "" /* Endmarker */
};


/* Funktionsdeklarationen */

char *scdir();	/* Manx-Funktion, Direktory scannen */

/* Amiga-Funktionen */
char *OpenLibrary();
struct FileLock *CurrentDir();


/*
 * Funktionsdefinitionen
 * ---------------------
 */


void putChar(c)
  char c;
{
  if (pgcnt > endpage || pgcnt < start) return;
  putchar(c);
} /* of putChar() */


void closeStdio() {
  if (!fromWB || wbToolStdio || !wbHasStdio) return;
  fclose(stdin);
  fclose(stdout);
  fclose(stderr);
} /* of closeStdio() */


BOOL openStdio(conSpec)
  char *conSpec;
{
  void cleanExit();  
  
  if (freopen(conSpec,"r+",stderr)) {
    fprintf(stderr, "Please set the WINDOW-ToolType in the programs icon\n");
    fprintf(stderr, "if you want it from WorkBench, eg.:\n");
    fprintf(stderr, "WINDOW=%s\n", conSpec);
    fromWB = wbHasStdio = TRUE;
    cleanExit("",10);
  }
  cleanExit(NULL,10);
  return FALSE;
} /* of openStdio() */


BOOL stdioSet() {
  struct DiskObject *diskobj;
  char **toolarray;
  char *wa_Name;

  wbToolStdio = FALSE;  
  wa_Name = WBenchMsg->sm_ArgList->wa_Name;
  if (IconBase = (struct IconBase *) OpenLibrary(ICONNAME,0L)) {
    diskobj = (struct DiskObject *) GetDiskObject(wa_Name);
    if (diskobj) {
      toolarray = diskobj->do_ToolTypes;
      wbToolStdio = (FindToolType(toolarray, "WINDOW")!=NULL) &&
                    isatty(fileno(stdin));
      FreeDiskObject(diskobj);
    }
    CloseLibrary(IconBase);
    IconBase = NULL;
  }

  return wbToolStdio;
} /* of stdioSet() */


void cleanExit(msg, rc)
  char *msg;
  int rc;
{
  char c;

  if (msg) {
    if (fromWB && !wbHasStdio) wbHasStdio = openStdio(conSpec);
    if (!fromWB || wbHasStdio) fprintf(stderr,"%s\n", msg);
    if (fromWB) {
      fprintf(stderr,"Please PRESS <Return> to EXIT\n"); 
      waitCR();
    }
  }
  if (fromWB && wbHasStdio) closeStdio();
  exit(rc);
} /* of cleanExit() */


void _abort () {
  cleanExit("\n^C - ABORT\n", 1);
} /* of _abort() */


void fPutSL(fp, sl)
  FILE *fp;
  char **sl;
{
  char **sp;

  for (sp = sl; sp ? *sp ? **sp : 0 : 0; ++sp) {
    fprintf(fp, "%s\n", *sp);
  }
} /* fPutSL() */


void printUsage(man)
  int man;
{
  fPutSL(stdout, usage);
  if (man==1) fPutSL(stdout, manual);
} /* of printUsage() */


int *mayGetNum (i, argc, argv, opt)
  int *i, argc;
  char *argv[], *opt;
{
  static int mgn_help;	/* Hilfsvariable fuer mayGetNum() */

  if (strlen(argv[*i]) > strlen(opt)) {
    mgn_help = atoi(&argv[*i][strlen(opt)]);
    mgn_help = ABS(mgn_help);
    return &mgn_help;
  }

  ++(*i);
  if (*i>=argc) {
    --(*i);
    return NULL;
  }
  if ( !(isdigit(argv[*i][0]) || isdigit(argv[*i][1])) ){
    --(*i);
    return NULL;
  }

  mgn_help = atoi(argv[*i]);
  mgn_help = ABS(mgn_help);

  return &mgn_help;
} /* of mayGetNum() */


int getNum(i, argc, argv, opt)
  int *i, argc;
  char *argv[], *opt;
{
  int *mayGetNum();
  int *help;

  help = mayGetNum(i, argc, argv, opt);

  if (!help) {
    fprintf(stderr,"\n%s: option %s <n>: <n> not found\n\n",
	    argv[0], opt);
    cleanExit(NULL, 1);
  }

  return *help;
} /* of getNum() */


char *mayGetStr(i, argc, argv, opt)
  int *i, argc;
  char *argv[], *opt;
{
  if (strlen(argv[*i]) > strlen(opt)) {
    return &argv[*i][strlen(opt)];
  }

  ++(*i);
  if (*i>=argc) {
    --(*i);
    return NULL;
  }

  return argv[*i];
} /* of mayGetStr() */


char *getStr(i, argc, argv, opt)
  int *i, argc;
  char *argv[], *opt;
{
  char *mayGetStr();
  char *help;

  help = mayGetStr(i, argc, argv, opt);

  if (!help) {
    fprintf(stderr,"\n%s: option %s <str>: <str> not found\n\n",
	    argv[0], opt);
    cleanExit(NULL, 1);
  }

  return help;
} /* of getStr() */


int *mayGetToolNum(value)
  char *value;
{
  static int num;
  
  num = 0;
  
  while(*value) {
    if (isdigit(*value)) {
      num = atoi(value);
      num = ABS(num);
      return &num;
    }
    ++value;
  }
  
  return NULL;
} /* of mayGetToolNum() */


int getToolNum(opt, value)
  char *opt, *value;
{
  int *num;
  
  num = mayGetToolNum(value);
  if (num) return *num;
  
  fprintf(stderr,"\npr: TOOL TYPE %s=%s <n>: <n> not found\n\n",
	  opt, value);
  return -1; /* Fehler */

} /* of getToolNum() */


char *getDate() {
  unsigned long t;

  t = time(NULL);
  return ctime(&t);
} /* of getDate() */


void saveValues() {
  start_s	= start		;
  endpage_s	= endpage	;
  tabsize_s	= tabsize	;
  tabconv_s	= tabconv	;
  ff_s		= ff		;
  sline_s	= sline		;
  ssize_s	= ssize		;
  lineno_s	= lineno	;
  katce_s	= katce		;
  hdr_s		= hdr		;
  emp_s		= emp		;
  ul_s		= ul		;
  formf_s	= formf		;
  offs_s	= offs		;
  pglen_s	= pglen		;
  lines_s	= lines		;
  lwid_s	= lwid		;
  upper_s	= upper		;
  sname_s	= sname		;
  banner_s	= banner	;
  strncpy(output_s, output, OUTPUTLEN);
} /* of saveValues() */


void restoreValues() {
  start		= start_s	;
  endpage	= endpage_s	;
  tabsize	= tabsize_s	;
  tabconv	= tabconv_s	;
  ff		= ff_s		;
  sline		= sline_s	;
  ssize		= ssize_s	;
  lineno	= lineno_s	;
  katce		= katce_s	;
  hdr		= hdr_s		;
  emp		= emp_s		;
  ul		= ul_s		;
  formf		= formf_s	;
  offs		= offs_s	;
  pglen		= pglen_s	;
  lines		= lines_s	;
  lwid		= lwid_s	;
  upper		= upper_s	;
  sname		= sname_s	;
  banner	= banner_s	;
  strncpy(output, output_s, OUTPUTLEN);
} /* of restoreValues() */


void printHeader(fn, pgcnt, date)
  char *fn;
  unsigned int pgcnt;
  char *date;
{
  register int i;

  for (i=0; i<upper; ++i) putChar(LF);

  if (hdr) {
    if (pgcnt<start || pgcnt>endpage) {
      putChar(LF);
      putChar(LF);
      return;
    }
    for (i=0; i<offs; ++i) putChar(BLANK);

    if (emp) printf("%c[1m", ESC);
    if (ul) printf("%c[4m", ESC);
    printf("filename: \'%s\' - page: %u - date : %s", fn, pgcnt, date);
    if (emp || ul) printf("%c[0m", ESC);
    putChar(LF);
  }
} /* of printHeader() */


void putFF() {
  register int i, help;

    if (formf) putChar(FF);
    else {
      help = lncnt;
      for (i=0; i<(pglen-lines) + (lines-help); ++i, ++lncnt)
	putChar(LF);
    }      
    ++pgcnt;
} /* of putFF() */


void putCRLF() {
  register int i;

  putChar(LF);
  charcnt = 0;
  if (++lncnt >= lines) {
    putFF();
    lncnt=0;
  }
} /* of putCRLF() */


void printLeftMargin() {

  int i;
  for (i=0; i<offs; ++i) {
    putchar(BLANK);
  }
} /* of printLeftMargin() */


BOOL myPutChar (c)
  char c;
{
  register int i;

  if ( !lncnt && !charcnt) printHeader(fname, pgcnt, date);

  if (c == FF) {
    /* FormFeed */
    putCRLF();
    if (lncnt!=0) putFF();
    lncnt = charcnt = 0;
    if (pgcnt>endpage) return TRUE;
  } else {
    if (charcnt == 0) {
      printLeftMargin();
      if (lineno) {
	if (pgcnt >= start && pgcnt <= endpage) printf("%5u  ", plncnt);
	plncnt += ssize;
      }
    }

    if (c == LF || katce && c == '\r') {
      putCRLF();
      if (pgcnt>endpage) return TRUE;
    }
    else {
      if (charcnt >= lwid) {
	putCRLF();
	if (pgcnt>endpage) return TRUE;
	for (i=lineno ? offs+7 : offs; i; --i) {
	  putChar(BLANK);
	}
      }
      /* isprint(c) funktioniert nicht bei sz */
      putChar(c); ++charcnt;
    }
  }

  return FALSE;
} /* of myPutChar() */


/* BANNER, Titelseite ausgeben */
void printBanner(fn, date)
  char *fn, *date;
{
  int blankLines, i, slen, help;

  help = hdr ? pglen+2 : pglen;

  blankLines = (lines-3) / 2;

  for (i=0; i<blankLines+offs; ++i) {
    putchar(LF);
  }
  
  /* Drucken Filename, ----, Datum : drei Zeilen */
  printLeftMargin();
  slen = strlen(fn);
  for(i=0; i<(lwid-slen)/2; ++i) {
    putchar(BLANK);
  }
  printf("%s\n", fn);

  printLeftMargin();
  for (i=0; i<lwid; ++i) {
    putchar('-');
  }
  putchar(LF);

  slen = strlen(date);
  for(i=0; i<(lwid-slen)/2; ++i) {
    putchar(BLANK);
  }
  printf("%s", date); /* date ist mit LF */
  
  
  if (formf) {
    putchar(FF);
  }
  else
    for (i=0; i< help - blankLines - 3; ++i) {
      putchar(LF);
    }
    
} /* of printBanner() */


/* Kat-Ce-Datei lesen und ausgeben */
void katType(file)
  FILE *file;
{
  int j;
  char c;

  for (j=0; j<8; ++j) c = getc(file);

  for (c = getc(file); c!=EOF && c!=NUL; c=getc(file)) {
    if (c!=16) {
      if (c==TAB) {
	if (tabconv)
	  for (j=charcnt%tabsize; j<tabsize; ++j)
	    myPutChar(BLANK);
	else { 
	  myPutChar(TAB);
	  charcnt += charcnt%tabsize;
        }
      }
      else if (myPutChar((char) c)) return;
    }
    else {
      c = getc(file);
      for (j=c-32; j; --j) myPutChar(BLANK);
    }
  } /* of for */
} /* of katType() */


/* ASCII-Datei lesen und ausgeben */
void asciiType(file)
  FILE *file;
{
  int j;
  char c;

  while ((c=getc(file)) != EOF) {
    if (c==TAB) {
      if (tabconv)
	for (j=charcnt%tabsize; j<tabsize; ++j)
	  myPutChar(BLANK);
      else { 
	myPutChar(TAB);
	charcnt += charcnt%tabsize;
      }
    }
    else if(myPutChar((char) c)) return;
  } /* of while */
} /* of asciiType() */


void printOut() {
  if (betw_ff) putFF();
  if (ff!=NO_FF && ff!=NOTH_FF) {
    lncnt = 0;
    pgcnt = 1;
    charcnt = 0;
  }
  plncnt = sline;
  date = getDate();
  if (banner) printBanner(fname, date);

  if (katce) katType(file);
  else asciiType(file);

  if (file!=stdin) fclose(file);

  if (lncnt<pglen || charcnt) {
    switch(ff) {
      case BTWN_FF : betw_ff = TRUE; break;
      case PRT_FF  :
      case END_FF  : 
          putCRLF();
          if (lncnt!=0) putFF();
        break;
    } /* of switch */
  }
  if (ff==NO_FF) putCRLF();
} /* of printOut() */ 


void examinePgHt() {
  if (hdr) pglen -= 2;
  pglen -= upper;

  if (pglen<1) {
    pglen += upper;
    upper = 0;
  }

  if (pglen<=0) pglen = 1; /* Mind. eine Textzeile */
  if (pglen<lines) lines = pglen;
} /* of examinePgHt() */


#ifdef COMMENT
char *myFindToolType(toolarray, value)
  char **toolarray, *value;
{
  register int i;

  if (!toolarray || !value) return NULL;

  for (i=strlen(value); **toolarray; ++toolarray)
    if (!strncmp(*toolarray, value, i))
      if ( *((*toolarray)+i) == '=' )
        if (*((*toolarray)+i+1)) return (*toolarray)+i+1;
        else return NULL;

  return NULL;
} /* of myFindToolType() */
#endif


void getWBOpts(wa_Name)
  char *wa_Name;
{
  struct DiskObject *diskobj;
  char **toolarray;
  char *s;
  int *pnum, num;
  
  if (IconBase = (struct IconBase *) OpenLibrary(ICONNAME,0L)) {
    diskobj = (struct DiskObject *) GetDiskObject(wa_Name);
    if (diskobj) {
      toolarray = diskobj->do_ToolTypes;
      /*
      printf("TOOL TYPES:\n");
      fPutSL(stdout, toolarray);
      */
	if (s = FindToolType(toolarray, FORMAT)) {
	  if (MatchToolValue(s, NOTHING_A)) {
	    formf = FALSE;
	    ff = NOTH_FF;
	    hdr = FALSE;
	    lines = 72;
	  }
	  if (MatchToolValue(s, LF_A)) {
	    formf = FALSE;
	    ff = NO_FF;
	    hdr = FALSE;
	    lines = 72;
	  }
	  if (MatchToolValue(s, BFF_A)) { 
	    formf = TRUE;
	    hdr = FALSE;
	    lines = 72;
	    ff=BTWN_FF;
	  }
	  if (MatchToolValue(s, AFF_A)) {
	    formf = TRUE;
	    hdr = FALSE;
	    lines = 72;
	    ff=END_FF;
	  }
	  if (MatchToolValue(s, PRINT_A)) { 
	    formf = TRUE;
	    hdr = TRUE;
	    lines = 60;
	    ff=PRT_FF;
	  }
	}
	if (s = FindToolType(toolarray, BANNER)) {
	  if (MatchToolValue(s, TRUE_A)) banner = TRUE;
	  if (MatchToolValue(s, FALSE_A)) banner = FALSE;
	}
	if (s = FindToolType(toolarray, FILETYPE)) {
	  if (MatchToolValue(s, KATCE_A)) katce = TRUE;
	  if (MatchToolValue(s, TEXT_A)) katce = FALSE;
	}
	if (s = FindToolType(toolarray, TABCONV)) {
	  tabconv = TRUE;
	  if (pnum = mayGetToolNum(s)) {
	    tabsize = *pnum;
	    tabsize = tabsize < 1 ? 1
		      : tabsize > MAXTAB ? MAXTAB
		      : tabsize;
	  }
	  if (MatchToolValue(s, TRUE_A)) tabconv = TRUE;
	  if (MatchToolValue(s, FALSE_A)) tabconv = FALSE;
	}
	if (s = FindToolType(toolarray, LINESTART)) {
	  lineno = TRUE;
	  if (pnum = mayGetToolNum(s)) sline = *pnum;
	}
	if (s = FindToolType(toolarray, LINESTEP)) {
	  lineno = TRUE;
	  if (pnum = mayGetToolNum(s)) {
	    ssize = *pnum;
	    if (ssize < 1) ssize = 1;
	  }
	}
	if (s = FindToolType(toolarray, LINENUMBERING)) {
	  if (MatchToolValue(s, TRUE_A)) lineno = TRUE;
	  if (MatchToolValue(s, FALSE_A)) lineno = FALSE;
	}
	if (s = FindToolType(toolarray, LINES)) {
	  if (pnum = mayGetToolNum(s)) {
	    lines = *pnum;
	    if (lines < 1) lines = 1;
	  }
	}
	if (s = FindToolType(toolarray, FORMFEED)) {
	  if (MatchToolValue(s, TRUE_A)) formf = TRUE;
	  if (MatchToolValue(s, FALSE_A)) formf = FALSE;
	}
	if (s = FindToolType(toolarray, LINEWID)) {
	  if (pnum = mayGetToolNum(s)) {
	    lwid = *pnum;
	    if (lwid < 1) lwid = 1;
	  }
	}
	if (s = FindToolType(toolarray, LINEIND)) {
	  if (pnum = mayGetToolNum(s)) {
	    offs = *pnum;
	    if (offs > 80) offs = 80;
	  }
	}
	if (s = FindToolType(toolarray, PAGELEN)) {
	  if (pnum = mayGetToolNum(s)) {
	    pglen = *pnum;
	    if (pglen < 1) pglen = 1;
	  }
	}
	if (s = FindToolType(toolarray, TOP)) {
	  if (pnum = mayGetToolNum(s)) {
	    upper = *pnum;
	  }
	}
	if (s = FindToolType(toolarray, START)) {
	  if (pnum = mayGetToolNum(s)) {
	    start = *pnum;
	    if (start < 1) start = 1;
	  }
	}
	if (s = FindToolType(toolarray, END)) {
	  if (pnum = mayGetToolNum(s)) {
	    endpage = *pnum;
	    /* if (endpage < start) start = endpage; */
	  }
	}
	if (s = FindToolType(toolarray, OUTPUT)) {
	  strncpy(output,s,OUTPUTLEN);
	}
	if (s = FindToolType(toolarray, HEADER)) {
	  hdr = TRUE;
	  if (MatchToolValue(s, BOLD_A)) emp = TRUE;
	  if (MatchToolValue(s, ULINED_A)) ul = TRUE;
	  if (MatchToolValue(s, PLAIN_A)) emp = ul = FALSE;
	  if (MatchToolValue(s, TRUE_A)) hdr = TRUE;
	  if (MatchToolValue(s, FALSE_A)) hdr = FALSE;
	}

      FreeDiskObject(diskobj);
    } 
    CloseLibrary(IconBase);
    IconBase = NULL;
  }

  if (!freopen(output, "w", stdout)) {
    fprintf(stderr,"Can't reopen %s as stdout\n", output);
    waitCR();
    cleanExit (NULL,1);   
  }
} /* of getWBOpts() */


void getCLIOpts(argc, argv)
  int argc;
  char *argv[];
{
  int	i;
  int	*help;		/* Hilfsvariable, Wert lesen */
  char *string, c;

  stdin_set = FALSE;

  /* CLI-Optionen scannen */
  for (i=1; i<argc; ++i) {

    if (!strcmp(argv[i], manstr)) {
      printUsage(1);
      exit(10);
    }

    if (!strcmp(argv[i], sinstr)) {
      stdin_set = TRUE;
    }

    if (!strncmp(argv[i], replstr, strlen(replstr))) {
      sname = mayGetStr(&i, argc, argv, replstr);
      if (!sname) sname = "";
    }

    if (!strncmp(argv[i], jumpstr, strlen(jumpstr))) {
      start = getNum(&i, argc, argv, jumpstr);
      if (start<1) start = 1;
      continue;
    } 

    if (!strncmp(argv[i], quitstr, strlen(quitstr))) {
      endpage = getNum(&i, argc, argv, quitstr);
      continue;
    } 

    if (!strncmp(argv[i], upperstr, strlen(upperstr))) {
      upper = getNum(&i, argc, argv, upperstr);
      if (upper<0) upper = 0;
      continue;
    } 

    if (!strcmp(argv[i], nothstr)) {
      formf = TRUE;
      hdr = FALSE;
      lines = 72;
      ff=NOTH_FF;
      continue;
    }
    if (!strcmp(argv[i], ffstr)) {
      formf = TRUE;
      hdr = FALSE;
      lines = 72;
      ff=END_FF;
      continue;
    }
    if (!strcmp(argv[i], btwnstr)) {
      formf = TRUE;
      hdr = FALSE;
      lines = 72;
      ff=BTWN_FF;
      continue;
    }
    if (!strcmp(argv[i], prtstr)) {
      formf = TRUE;
      hdr = TRUE;
      lines = 60;
      ff=PRT_FF;
      continue;
    }
    
    if (!strcmp(argv[i], katstr)) {
      katce = TRUE;
      continue;
    }
    if (!strcmp(argv[i], empstr)) {
      emp = TRUE;
      continue;
    }
    if (!strcmp(argv[i], ulstr)) {
      ul = TRUE;
      continue;
    }
    if (!strcmp(argv[i], hdrstr)) {
      hdr = FALSE;
      continue;
    }

    if (!strcmp(argv[i], banstr)) {
      banner = TRUE;
      continue;
    }

    if (!strncmp(argv[i], tabstr, strlen(tabstr))) {
      help = mayGetNum(&i, argc, argv, tabstr);
      if (!help) {
	tabconv = FALSE;
	tabsize = TABSIZE;
      } else {
	tabconv = TRUE;
	tabsize = *help;
	if (tabsize>MAXTAB) tabsize = MAXTAB;
	if (tabsize<1)  tabsize = 1;
      }
      continue;
    }

    if (!strncmp(argv[i], lineffstr,strlen(lineffstr))) {
      help = mayGetNum(&i, argc, argv, lineffstr);
      formf = TRUE;
      if (help) {
	lines = *help;
	if (lines<1) lines = 1;
      }
      continue;
    } 

    if (!strncmp(argv[i], linestr,strlen(linestr))) {
      help = mayGetNum(&i, argc, argv, linestr);
      formf = FALSE;
      if (help) {
	lines = *help;
	if (lines<1) lines = 1;
      }
      continue;
    } 

    if (!strncmp(argv[i], pgstr, strlen(pgstr))) {
      pglen = getNum(&i, argc, argv, pgstr);
      if (pglen<1) pglen = 1;
      continue;
    } 

    if (!strncmp(argv[i], offstr,strlen(offstr))) {
      offs = getNum(&i, argc, argv, offstr);
      if (offs<0) offs = 0;
      if (offs>80) offs = 80;
      continue;
    } 

    if (!strncmp(argv[i], widstr,strlen(widstr))) {
      lwid = getNum(&i, argc, argv, widstr);
      if (lwid<1) lwid = 1;
      continue;
    } 

    if (!strncmp(argv[i], numlstr,strlen(numlstr))) {
      help = mayGetNum(&i, argc, argv, numlstr);
      if (!help) {
	lineno = TRUE;
	sline = 1;
      } else {
	lineno = TRUE;
	sline = *help;
	if (sline<0) sline = 0;
      }
      continue;
    } 

    if (!strncmp(argv[i], stepstr, strlen(stepstr))) {
      if (strncmp(argv[i], sinstr, strlen(sinstr)) != 0) {
        help = mayGetNum(&i, argc, argv, stepstr);
	if (!help) {
	  lineno = TRUE;
	  ssize = 1;
	} else {
	  lineno = TRUE;
	  ssize = *help;
	  if (ssize<1) ssize = 1;
	}
      }
      continue;
    }
  } /* for */
} /* of getCLIOpts */


void doCLI(argc, argv)
  int argc;
  char *argv[];
{
  BOOL stay;
  int i, *help;
  char c, *str;

  if (argc==1 && isatty(fileno(stdin))) return;

  getCLIOpts(argc, argv);
  
  examinePgHt();

  lncnt = 0;
  pgcnt = 1;
  charcnt = 0;

  /* stdin von Pipe oder Datei drucken ? */
  if (!isatty(fileno(stdin)) && !stdin_set) {
    file = stdin;
    fname = sname;
    fprintf(stderr, "PRINTING standard-input as \'%s\' !\n", fname);
    printOut();
    stdin_set = TRUE;
  } else {
    stdin_set = FALSE;
  }

  /* Optionen ueberlesen und Dateien drucken */
  for (i=1; i<argc; ++i) {

    if (! (strcmp(argv[i], ffstr) && 
	   strcmp(argv[i], btwnstr) &&
	   strcmp(argv[i], prtstr)
	  )
       ) continue;

    if (! (strcmp(argv[i], nothstr) &&
	   strcmp(argv[i], banstr)
	  )
       ) continue;

    if (! (strcmp(argv[i], katstr) &&
	   strcmp(argv[i], hdrstr) &&
	   strcmp(argv[i], empstr) &&
	   strcmp(argv[i], ulstr)
	  )
       ) continue;

    if (!strncmp(argv[i], replstr, strlen(replstr))) {
      str = mayGetStr(&i, argc, argv, replstr);
      continue;
    }
    if (!strncmp(argv[i], jumpstr, strlen(jumpstr))) {
      help = mayGetNum(&i, argc, argv, jumpstr);
      continue;
    }
    if (!strncmp(argv[i], quitstr, strlen(quitstr))) {
      help = mayGetNum(&i, argc, argv, quitstr);
      continue;
    }
    if (!strncmp(argv[i], upperstr, strlen(upperstr))) {
      help = mayGetNum(&i, argc, argv, upperstr);
      continue;
    }
    if (!strncmp(argv[i], tabstr, strlen(tabstr))) {
      help = mayGetNum(&i, argc, argv, tabstr);
      continue;
    }
    if (!strncmp(argv[i], lineffstr, strlen(lineffstr))) {
      help = mayGetNum(&i, argc, argv, lineffstr);
      continue;
    }
    if (!strncmp(argv[i], linestr, strlen(linestr))) {
      help = mayGetNum(&i, argc, argv, linestr);
      continue;
    }
    if (!strncmp(argv[i], widstr, strlen(widstr))) {
      help = mayGetNum(&i, argc, argv, widstr);
      continue;
    }
    if (!strncmp(argv[i], offstr, strlen(offstr))) {
      help = mayGetNum(&i, argc, argv, offstr);
      continue;
    }
    if (!strncmp(argv[i], pgstr, strlen(pgstr))) {
      help = mayGetNum(&i, argc, argv, pgstr);
      continue;
    }
    if (!strncmp(argv[i], numlstr, strlen(numlstr))) {
      help = mayGetNum(&i, argc, argv, numlstr);
      continue;
    }

    if (!strncmp(argv[i], stepstr, strlen(stepstr))) {
      if (strncmp(argv[i], sinstr, strlen(sinstr)) != 0) {
        help = mayGetNum(&i, argc, argv, stepstr);
        continue;
      }
    }

    /* Drucken */
    stay = TRUE;

    while((fname = strncmp(argv[i], sinstr, strlen(sinstr))
		  ? scdir(argv[i])
		  : argv[i])
	  && stay) {

      if (!strncmp(fname, sinstr, strlen(sinstr))) {
	if (stdin_set) {
	  stay = FALSE;
          continue;
	}
	file = stdin;
	fname = sname;
	stdin_set = TRUE;
      }
      else if (!(file=fopen(fname, "r"))) {
	fprintf(stderr, "Can't open \'%s\' ! ( CANCELED )\n", fname);
	continue;
      }

      fprintf(stderr, "PRINTING ");
      if (stdin==file) fprintf(stderr, "standard-input as ");
      fprintf(stderr, "\'%s\' !\n", fname);
      
      printOut();
      if (file==stdin) stay = FALSE;
    } /* of while */
  } /* of for */
} /* of do_CLI()) */


void currentSettings(wa_Name)
  char *wa_Name;
{
  struct DiskObject *diskobj;
  char **toolarray;

  fprintf(stderr,"TOOL TYPES set:\n");
  fprintf(stderr,"---------------\n\n");
  
  if (IconBase = (struct IconBase *) OpenLibrary(ICONNAME,0L)) {
    diskobj = (struct DiskObject *) GetDiskObject(wa_Name);
    if (diskobj) {
      toolarray = diskobj->do_ToolTypes;
      fPutSL(stderr,toolarray);    
      FreeDiskObject(diskobj);
    }
    CloseLibrary(IconBase);
  }
  fprintf("\n");
} /* of currentSettings() */


void doWB() {
  struct WBArg *arg;
  struct FileLock *newLock, *startLock;
  int i;
  char c;
  BOOL waiting;
  static char argv[2][100] = { "pr", "" };
    
    fprintf(stderr,"%s", usage[0]);
    fprintf(stderr, "You get some hints by typing 'pr -man' in your\n");
    fprintf(stderr, "CLI-Environement.\n\n");

    startLock = NULL;
    arg = WBenchMsg->sm_ArgList;
    /* WB-Optionen scannen */
    if (arg) {
      getWBOpts(arg->wa_Name);    
      newLock   = (struct FileLock *) arg->wa_Lock;
      startLock = (struct FileLock *) CurrentDir(newLock);
    }
 
    saveValues();

    if (WBenchMsg->sm_NumArgs == 1 || !arg) {
      if (arg) currentSettings(arg->wa_Name);
      fprintf(stderr,"\nPlease enter <filename>, <Return> to quit\n");
      fprintf(stderr,"Filename: ");
      if (gets(argv[1])) {
	if (strlen(argv[1])) {
	  if (*argv[1]) {
	    getWBOpts(argv[1]);
	    fname = argv[1];
	    if (!(file=fopen(fname, "r"))) {
	      fprintf(stderr, "Can't open \'%s\' !\n", fname);
	      fini();
	    } else {
	      fprintf(stderr,"PRINTING: %s\n", fname);
	      lncnt = 0;
	      pgcnt = 1;
	      charcnt = 0;
	      examinePgHt();
	      printOut();
	      if (startLock) CurrentDir(startLock);
	    }
	    return;
	  } else {
	    if (startLock) CurrentDir(startLock);
	    return;
	  }
	} else {
	  if (startLock) CurrentDir(startLock);
	  return;
	}
      }
    }

    lncnt = 0;
    pgcnt = 1;
    charcnt = 0;
    waiting = FALSE;

    for (i=1, ++arg; i<WBenchMsg->sm_NumArgs; ++i, ++arg, restoreValues()) {
      getWBOpts(arg->wa_Name);
      newLock = (struct FileLock *) arg->wa_Lock;
      CurrentDir(newLock);
      fname = (char *) arg->wa_Name;
      if (!(file=fopen(fname, "r"))) {
	fprintf(stderr, "Can't open \'%s\' ! ( CANCELED )\n", fname);
	waiting = TRUE;
	continue;
      }

      getWBOpts(arg->wa_Name);

      fprintf(stderr, "PRINTING %s \'%s\' !\n",
	      katce ? KATCE_A : TEXT_A, fname);

      examinePgHt();
      printOut();

    } /* for */

    if (startLock) CurrentDir(startLock);
    if (waiting) fini();

} /* of doWB() */


void main(argc, argv)
  int argc;
  char *argv[];
{
  char c;

  Enable_Abort = 1;

  if (fromWB = argc==0) {
    if (!(wbHasStdio = stdioSet())) wbHasStdio = openStdio(conSpec);
  }

  if (argc==1 && isatty(fileno(stdin))) {
    printUsage(0);
    exit(10);
  }

  /* Defaultwerte setzen */
  start = 1;
  tabsize = TABSIZE;
  tabconv = TRUE;
  ff = NO_FF;
  sline = 1;
  ssize = 1;
  lineno = FALSE;
  katce = FALSE;
  hdr = FALSE;
  emp = FALSE;
  ul = FALSE;
  formf = FALSE;
  offs = 0;
  pglen = 72;
  lines = 72;
  lwid = 80;
  upper = 0;
  sname = sinstr;
  banner = FALSE;
  endpage = 0x7fff;  

  strncpy(output,"PRT:",OUTPUTLEN);

  betw_ff = FALSE;

  if (fromWB) {
    if (wbHasStdio)
      doWB();
  }
  else doCLI(argc, argv);

  cleanExit(NULL, 0);

} /* of main() */
