/*Pageit_D.c Sends paged output to printer, optionally with a header or
footer, with page numbers. Revised May 1 '86 to prevent bf, underline,
and italic from carrying over to next line and to provide | for paging.
Modified 21 May for ] as ESC to print the formatting characters. Revised
May 22 to DEFINE all variables which control printing, and to use ESPERANTO
for output to PRT: Final May 26. Uses Visible Chars to control formatting */

#define LIMIT  56
#define TRUE   1
#define FALSE  0
#define CLRS   12

#define PRINTER   "prt:"        /* Output must go to PRT: with Esperanto */

#define BOLD      "\x9B1m"      /* ESPERANTO BOLD ON, etc. */
#define SBOLD     " \x9B1m"     /* Be sure to enter spaces as shown! */
#define BOLDOFF   "\x9B22m "

#define UNDER     "\x9B4m"
#define SUNDER    " \x9B4m"
#define UNDEROFF  "\x9B24m "

#define ITALIC    "\x9B3m"
#define SITALIC   " \x9B3m"
#define ITALICOFF "\x9B23m "
                               /* User-defined signals for toggling */
#define SIGBOLD    '~'         /* Turns BOLDFACE on and off in text */
#define SIGUNDER   '`'         /* Underline toggle */
#define SIGITALIC  '@'         /* Italic toggle */
#define SIGPLAIN   ']'         /* Toggles formatted printing off/on */
#define SIGPAGE    '|'         /* Ends page; starts new one */

#define PERF      "\x9B9q"     /* Perf skip set at 9 lines from bottom */
#define PERFOFF   "\x9B0q"     /* or 1.5 inches from bottom of form  */

#include <stdio.h>
#include <df1:include/lattice/fcntl.h>

extern int Enable_Abort;
extern int Chk_Abort();
FILE *printer;
int pagenum, lenleft, lenright, numlen, limit, under;
int linecount, lines;
char lterm[37], rterm[37];

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

FILE *fp;
char which, chlines[3], inbuff[160], outbuff[160];
char opt, chnum[6], chlim[2];
int c, i, out, nextpage, maxchars, skip, plainprint, printed, count;
void doprint();
void fancydo();
void godown();

under = 0;
putchar(CLRS);
Enable_Abort = 1;

if (argc != 2) {
   printf("Call PAGEIT again with name of file to print.\n");
   exit (FALSE); }

printf("If your printer is on-line, press <RETURN>\n");
while ((c = getchar()) != '\n');     /* get CLI garbage */

/* ~~~~~~~~~~~~~~~~~~~~~~    OPEN files  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  */

if ((fp = fopen(argv[1], "r")) == NULL) {
   printf("Can't open file %s\n", argv[1]);
   exit (FALSE); }

if ((printer = fopen(PRINTER, "w")) == NULL) {
   printf("Can't open printer.\n");
   exit (FALSE); }

/* ~~~~~~~~~~~~~~~~~~~~~ Get LINES per PAGE ~~~~~~~~~~~~~~~~~~~~~~~~ */

printf("Enter number of lines per page (max: 99):\n");
i = 0;
while ((c = getchar()) && c != '\n' && c != EOF)
   if (c >= '0' && c <= '9' && i < 2)
      chlines[i++] = c;
if (c == EOF) exit(FALSE);
chlines[i] = '\0';
lines = atoi(chlines);

/* ~~~~~~~~~~~~~~~~~~  Determine HEADER or FOOTER ~~~~~~~~~~~~~~~~~~~   */

printf("\nEnter 'h' for a header, 'f' for a footer, or 'n' for none:\n");
while ((c = getchar()) != 'h' && c != 'f' && c != 'n' && c != EOF)
   ;
if (c == EOF) exit(FALSE);
which = c;
while((c = getchar()) != '\n');       /* collect CLI buffer garbage */

if (which == 'h' || which == 'f')
{
               /* ~~~~~~~~~~~~~~~ Get Details ~~~~~~~~~~~~~~ */
   limit = 81;
   while (limit > 80) {
      printf("\nEnter footer/header characters per line (80 maximum):\n");
      i = 0;
      while ((c = getchar()) && c != '\n' && c != EOF)
         if (c >= '0' && c <= '9' && i < 2)
            chlim[i++] = c;
      if (c == EOF) exit(FALSE);
      chlim[i] = '\0';
      limit = atoi(chlim);
      if (limit > 80)
         printf("\nFooters/headers of more than 80 chars not supported.\n");
   }
   limit /= 2;
   maxchars = limit - 5;

   printf("\nEnter left field of no more than %d chars or RETURN for none:\n", maxchars);
   i = 0;
   while((c = getchar()) && c != '\n' && c != EOF)
      if (i < maxchars)
         lterm[i++] = c;
   if (c == EOF) exit(FALSE);
   lterm[i] = '\0';
   lenleft = i;
   if (lenleft > 0)
      printf("Left term is: %s\n", lterm);

   printf("\nEnter right field of no more than %d chars or RETURN for none:\n", maxchars);
   i = 0;
   while((c = getchar()) && c != '\n' && c != EOF)
      if (i < maxchars) rterm[i++] = c;
   if (c == EOF) exit(FALSE);
   rterm[i] = '\0';
   lenright = i;
   if (lenright > 0)
      printf("Right term is: %s\n", rterm);

   numlen = 0;
   while (numlen == 0) {
      printf("\nEnter starting page number:\n");
      i = 0;
      while((c = getchar()) && c != '\n' && c != EOF)
         if (c >= '0' && c <= '9' && i < 5)
            chnum[i++] = c;
      if (c == EOF) exit(FALSE);
      chnum[i] = '\0';
      numlen = i;
   }
   pagenum = atoi(chnum);
   printf("Starting page number is: %d\n", pagenum);

   if (which == 'h') {
      printf("\nDo you want a header on the first page? y/n\n");
      while ((c = getchar()) != '\n' && c != EOF)
         if (c == 'y') opt = c;
      if (c == EOF) exit(FALSE);
   }
   if (lenleft && lenright) {
      printf("\nDo you want to underline header/footer? y/n\n");
      while ((c = getchar()) != '\n' && c != EOF)
         if (c == 'y') under = 1;
      if (c == EOF) exit(FALSE);
      }

}  /* end IF header or footer /*

/* ~~~~~~~~~~~~~~~~~~~~~~  Set Up and PRINT ~~~~~~~~~~~~~~~~~~~~~~~~~~~  */

if (which == 'f' && lines > 3) lines -= 3;     /* adjust for footer */
linecount = 1;
fprintf (printer,PERFOFF);                    /* perf skip off */
nextpage = plainprint = printed = 0;

while (fgets(&inbuff, 144, fp) != NULL)
{
   if (inbuff[0] == SIGPLAIN) {      /* Abandon formatted printing. */
     plainprint = 1 - plainprint;    /* Toggle on and off. */
     continue;
   }
   skip = 0;
   if ((i = Chk_Abort()) != '\0')  {   /* See if ^C or ^D have been pressed */
      fclose(fp);
      fprintf(printer, PERF);                /* reset perfskip */
      fclose(printer);
      exit(0);
   }
   if (linecount == 1 && which == 'h') {              /* Do header */
      if (opt == 'y') {
         if (inbuff[0] == '\n' && nextpage) continue; /* No blank lines */
         doprint();                                   /* at top of 2nd and */
         fprintf(printer, "\n\n");                   /* following pages */
         linecount = 4;
      }
      else
         opt = 'y';
   }
   setmem (outbuff, 160, ' ');                /* Fill buffer with spaces */
   out = 0;
   i = 0;
   while ((c = inbuff[i++]) !='\0') {
      if (i == 1 && c == SIGPAGE) {           /* Page if ENDPAGE is seen. */
         skip = 1;
         break;
      }
      if (c == 9)
         out += 5;                            /* Convert 09 tabs to spaces */
      else
         outbuff[out++] = c;
   }
   outbuff[out] = '\0';

   if (linecount == 1 && which == 'f' && nextpage) /* No blank lines at top of */
      if (outbuff[0] == '\n')                      /* page, except page 1 */
         continue;

   if (!skip) {
      fancydo(&outbuff, plainprint);    /* Call print routine. */
      if (outbuff[0] != '\n')
         printed = 1;                   /* Mark printable page */
   }
   if (++linecount > lines || skip) {    /* page at linecount or SIGPAGE */
      if (which == 'f') {
         if (skip && linecount < lines) godown();
         doprint();                                /* do footer */
      }
      fputc(CLRS, printer);
      linecount = nextpage = 1;
      printed = 0;
      ++pagenum;
      for (i = 10, count = 1; ; i *= 10, count++)
         if (pagenum < i) {
            numlen = count;
            break;
         }
   }

}  /* ~~~~~~~~~ endwhile...    And SHUT HER DOWN ~~~~~~~~~~~~~~~~~     */

   if (linecount < lines && which == 'f' && printed == 1) {
        godown();
        doprint();
   }
   fclose(fp);
   fprintf(printer, PERF);                /* reset to perfskip */
   fclose(printer);

} /* end MAIN */


void doprint()                   /* prints footer */
{
int i;
extern FILE *printer;
extern int pagenum, lenleft, lenright, numlen, limit, under;
extern char lterm[], rterm[];

fprintf(printer, "\n\n");              /* space down for footer */

if (under) fprintf(printer, UNDER);    /* set underline mode */

fprintf(printer,"%s", lterm);          /* print left term */

for (i = lenleft + 1; i < (limit-2); i++)    /* space over to page no. */
   fputc(' ', printer);

fputc('-', printer);

fprintf(printer, "%d-", pagenum);           /* do page number */

for (i = 1; i <= limit + 1 - lenright - numlen; i++)
   fputc(' ', printer);                     /* space over again */

fprintf(printer, "%s\n", rterm);            /* print right term */

if (under) fprintf(printer, UNDEROFF);      /* turn off underline */
}

void fancydo(source,plain)
char *source;
int plain;
{
int c;
int bold, t_under, start, italic;
bold = t_under = italic = 0;
start = 1;

   while ((c = *source++) != '\0') {
      if (plain) fputc(c,printer);   /* If plainprint is on, print as-is */
      else if (c == SIGBOLD) {
         if (bold == 0) {
            if (start)
               fprintf(printer, BOLD); /* If at start of line... */
            else
               fprintf(printer, SBOLD);
            bold = 1;
         }
         else {
            fprintf(printer, BOLDOFF);
            bold = 0;
         }
      }
      else if (c == SIGUNDER) {
         if (t_under == 0) {
            if (start)
               fprintf(printer, UNDER);
            else
               fprintf(printer, SUNDER);
            t_under = 1;
         }
         else {
            fprintf(printer, UNDEROFF);
            t_under = 0;
         }
      }
      else if (c == SIGITALIC) {      /* If @ sign, do italic */
         if (italic == 0) {
            if (start)
               fprintf(printer, ITALIC);
            else
               fprintf(printer, SITALIC);
            italic = 1;
         }
         else {
            fprintf(printer, ITALICOFF);
            italic = 0;
         }
      }
      else if (c == '\x0A') {                      /* Kill modes at end line */
         if (t_under) fprintf(printer, UNDEROFF);
         else if (bold) fprintf(printer, BOLDOFF);
         else if (italic) fprintf(printer, ITALICOFF);
         fputc(c,printer);
      }
      else {
         fputc(c, printer);
      }
      start = 0;

   } /* end while */
}  /* end function */

/*                      Space down for footer                         */

void godown()
{
int i;
extern int linecount,lines;
extern FILE *printer;

      for (i = linecount; i < lines+1; i++)
         fputc('\n',printer);
}
