#include "defs.h"

Prototype __regargs void  split_bufs(PE *, PE *);
Prototype           SHORT do_process(void);
Prototype __regargs SHORT read_file(PE *);
Prototype __regargs SHORT alloc_buf(PE *);
Prototype           PE   *do_open(void);
Prototype __regargs PE   *double_pe(PE *);
Prototype           PE   *init_pe(void);
Prototype __regargs void  count_pages(PE *);
Prototype __regargs void  do_name(PE *, UBYTE *);
Prototype           void  get_date(void);
Prototype __regargs void  ask_print(UBYTE *);

Prototype const UBYTE resume[];
Prototype UBYTE date_buf[30];

UBYTE date_buf[30];


/***********************  double_pe(void) ****************************/
__regargs PE    *
double_pe(PE * old)
{
  PE    *pe;

  if (pe = init_pe())
  {
    strcpy(pe->FullName, old->FullName);
    strcpy(pe->pe_node.ln_Name, old->pe_node.ln_Name);
    pe->Size        = old->Size;
    pe->pagesize    = old->pagesize;
    pe->linelength  = old->linelength;
    return (pe);
  }
  return (NULL);
}

/***********************  read_file()  **************************/
const UBYTE readerror[] = "***Error: Reading %s failed !";
const UBYTE resume[]    = "resume";
__regargs SHORT
read_file(PE * pe)
{                                       /* read file into buffer  */
  SHORT  done = FALSE;

  if (pe->Size == Read(pe->Handle, pe->SplitBuffer, pe->Size))
    done = TRUE;
  else
    do_request(readerror, resume, pe->FullName);

  Close(pe->Handle);
  return (done);
}

/***********************  do_open(void) ******************************/
const UBYTE openerror[] = "***Error: Opening %s failed !";

PE *
do_open(void)
{
  PE    *pe    = NULL;
  SHORT  memok = FALSE;
  SHORT  open  = FALSE;
  FIB   *fib_ptr;

  if (fib_ptr = (FIB *) AllocMem(sizeof(FIB), MPC))
  {
    memok = TRUE;
    FL    *lock;

    if (lock = (FL *) Lock(Buf_storage_str, SHARED_LOCK))
    {
      if (Examine(lock, fib_ptr))
      {
        if (pe = init_pe())
        {
          if (pe->Handle = (FH *) Open(Buf_storage_str, MODE_OLDFILE))
          {
            pe->Size = fib_ptr->fib_Size;

            UBYTE  *d = pe->pe_node.ln_Name;
            UBYTE  *s = fib_ptr->fib_FileName;

            for (; *d = *s; ++s, ++d) ;

            for (d = pe->FullName, s = Buf_storage_str;
                 *d = *s; ++s, ++d) ;

            open = TRUE;
          }
          else
            FreeRem(pe->memory);
        }
        else
          memok = FALSE;
      }
      UnLock(lock);
    }
    FreeMem(fib_ptr, sizeof(FIB));
  }

  if (!memok)
    quit = autom = TRUE;

  if (!open)
    do_request(openerror, resume, Buf_storage_str);

  return (pe);
}

/***********************  init_pe(void) ******************************/
PE  *
init_pe(void)
{
  LONG  *pet;

  if (pet = (LONG *) AllocMem(sizeof(PE) + 8, MPC))
  {
    pet[1] = sizeof(PE) + 8;
    PE *pe = (PE *) (pet + 2);
    pe->memory = pet;

    if (pe->pe_node.ln_Name = (UBYTE *) AllocRem(pe, MAXPATH))
    {
      if (pe->FullName = (UBYTE *) AllocRem(pe, MAXPATH))
      {
        pe->pagesize   = pagesize;
        pe->linelength = linelength;
        return (pe);
      }
      FreeRem(pe->memory);
    }
    FreeMem(pe, sizeof(PE) + 8);
  }
  return (NULL);
}


/***********************  alloc_buf()  **************************/
__regargs SHORT
alloc_buf(PE * pe)                      /* each buffer needs size of file   */
{
  int    bsize = max(pe->Size, MIN_BUF_SIZE);

  if ((bsize << 1) < AvailMem(MEMF_PUBLIC))
  {
    if ((pe->SplitBuffer = (UBYTE *) AllocRem(pe, bsize)) != 0)
      return (TRUE);
  }
  return (FALSE);
}

/***********************  do_process()  **************************/
SHORT
do_process(void)
{
  PE    *prieve;

  if (prieve = do_open())
  {
    if (alloc_buf(prieve))
    {
      if (read_file(prieve))
      {
        if (split || title)
        {
          PE    *priodd;

          if (priodd = double_pe(prieve))
          {
            if (!split)               /*  add space for titling */
              priodd->Size <<= 1;

            if (alloc_buf(priodd))
            {
              split_bufs(prieve, priodd);

              if (prieve->Size && priodd->Size)
              {
                priodd->pe_node.ln_Type = ODD;
                do_name(priodd, "ODD ");
                prieve->pe_node.ln_Type = EVEN;
                do_name(prieve, "EVEN");
              }
              else
              {
                if (priodd->Size)
                {
                  priodd->pe_node.ln_Type = ALL;
                  do_name(priodd, "TITL");
                  FreeRem(prieve->memory);
                }
              }
              return (TRUE);
            }
          }
        }
        else
        {
          prieve->pe_node.ln_Type = ALL;
          count_pages(prieve);
          do_name(prieve, "ALL ");
        }
      }
    }
  }
  return (FALSE);
}

/***********************  do_name  ********************************/
__regargs void
do_name(PE *pe, UBYTE *page)
{
  UBYTE  *buf;

  if (buf = (UBYTE *) AllocMem(MAXPATH, MPC))
  {
    UBYTE *d = buf;
    UBYTE *s = pe->pe_node.ln_Name;
    SHORT  i = 0;

    for (; *d = *s; ++s, ++d, ++i);

    for (; i < 15; *d++ = ' ', ++i);

    sprintf(d, "<%s %2dpg>", page, pe->pagenum);

    strcpy(pe->pe_node.ln_Name, buf);

    pe->pe_node.ln_Pri = 4 - pe->pe_node.ln_Type;

    update_list(pe);

    if (autom)
      ask_print(buf);

    FreeMem(buf, MAXPATH);
  }
  else
    quit = autom = TRUE;
}


/***********************  ask_print() ******************************/
const UBYTE printnow0[] = "Print %s now ???";
const UBYTE printnow1[] = "Yes, print it|No, skip it";

__regargs void
ask_print(UBYTE *name)
{
  if (do_request(printnow0, printnow1, name))
  {
    if (name != Buf_storage_str)
      strcpy(Buf_storage_str, name);
    do_print_it();
  }
}

/***********************  count_pages ****************************/
const SHORT psize[2] = { 66, 88 };

__regargs void
count_pages(PE *pe)
{
  SHORT maxline = psize[pagesize];
  LONG  chars   = 1;
  UBYTE *ptr    = pe->SplitBuffer;

  while (chars < pe->Size)
  {
    SHORT lines = 0;
    ++pe->pagenum;
    while (lines++ < maxline)
      while ((*ptr++ != '\n') && (chars++ < pe->Size));
  }
}

/***********************  split_bufs()  **************************/
const UBYTE pagestr[] = "Page %3d";
const UBYTE normal[]  = "\x9B0m\n\n\n";
const UBYTE dobold[]  = "\n\x9B1m";
const SHORT mchars[]  = { 80, 80, 96 };

__regargs void
split_bufs(PE * prieve, PE * priodd)    /* does titling here if ordered  */
{
  SHORT maxchars = mchars[linelength];
  SHORT maxline  = psize[pagesize];

  UBYTE *ptr[2];
  ptr[ODD]       = priodd->SplitBuffer;
  ptr[EVEN]      = prieve->SplitBuffer;
  UBYTE *filptr  = prieve->SplitBuffer;

  int    pagenum = 1;                   /* start positions */
  SHORT  side    = ODD;

  if (title)
  {
    UBYTE *fname_ptr = ptr[ODD] + ((maxchars -
                            strlen(prieve->pe_node.ln_Name)) >> 1);

    UBYTE *end_ptr   = ptr[ODD] + maxchars - 8;

    ptr[ODD] = (UBYTE *) stpcpy(ptr[ODD], dobold);
    ptr[ODD] = (UBYTE *) stpcpy(ptr[ODD], date_buf);

    for (; ptr[ODD] < fname_ptr; *ptr[ODD]++ = ' ');

    ptr[ODD] = (UBYTE *) stpcpy(ptr[ODD], prieve->pe_node.ln_Name);

    for (; ptr[ODD] < end_ptr;   *ptr[ODD]++ = ' ');

    ptr[ODD] += sprintf(ptr[ODD], pagestr, pagenum);

    ptr[ODD] = (UBYTE *) stpcpy(ptr[ODD], normal);

    maxline -= 4;
  }

  SHORT  linenum = 1;                   /* start positions */
  SHORT  charnum = 0;

  while (*filptr)                       /* counter */
  {
    *ptr[side]++ = *filptr;             /* UBYTE copy */

    if (*filptr == '\n')                /* end of line */
    {
      ++linenum;
      if (linenum > maxline)           /* end of page */
      {
        ++pagenum;

        if (split)                      /* both sides ordered ?  */
          toggle(side);

        if (title)
        {
          UBYTE *fname_ptr = ptr[side] + ((maxchars -
                                   strlen(prieve->pe_node.ln_Name)) >> 1);

          UBYTE *end_ptr   = ptr[side] +   maxchars;

          ptr[side] = (UBYTE *) stpcpy(ptr[side], dobold);

          if (!side)                    /* ODD:  date,   filename, pageno */
          {
            ptr[ODD] = (UBYTE *) stpcpy(ptr[ODD], date_buf);
            end_ptr -= 8;               /* len of "Page ###"  */
          }
          else                          /* EVEN: pageno, filename, date  */
          {
            ptr[EVEN] += sprintf(ptr[EVEN], pagestr, pagenum);
            end_ptr   -= strlen(date_buf);
          }

          for (; ptr[side] < fname_ptr; *ptr[side]++ = ' ');

          ptr[side] = (UBYTE *) stpcpy(ptr[side], prieve->pe_node.ln_Name);

          for (; ptr[side] < end_ptr;   *ptr[side]++ = ' ');

          if (!side)
            ptr[ODD] += sprintf(ptr[ODD], pagestr, pagenum);
          else
            ptr[EVEN] = (UBYTE *) stpcpy(ptr[EVEN], date_buf);

          ptr[side] = (UBYTE *) stpcpy(ptr[side], normal);
        }
        linenum = 1;                    /* new page  */
      }
      charnum = 0;                      /* checks for line too long  */
    }
    if (++charnum > maxchars)           /* input line too long   */
    {
      *filptr = '\n';                   /* split line  */
      continue;                         /* go copy it into buffer  */
    }
    ++filptr;
  }                                     /*  all copied  */
  if (linenum > 1)
    *ptr[side]++ = '\f';                /* do formfeed */

  if (!side && split)                   /* make even pagenumber anyway */
  {
    *ptr[EVEN]++ = '\f';
    ++pagenum;
  }
  prieve->Size = ptr[EVEN] - prieve->SplitBuffer;
  priodd->Size = ptr[ODD]  - priodd->SplitBuffer;
  prieve->pagenum = priodd->pagenum = pagenum;
}


/***********************  get_date()  **************************/
const UBYTE *mname[13] = { 0,
                        "Jan.", "Febr.", "Mar.", "Apr.",
                        "May",  "June",  "July", "Aug.",
                        "Sept.","Oct.",  "Nov.", "Dec." };

const UBYTE *dname[8]  = { 0,
                        "Sunday",   "Monday",   "Tuesday",  "Wednesday",
                        "Thursday", "Friday",   "Saturday" };
const UBYTE *dayext[4] = {
                        "th", "st", "nd", "rd" };

void
get_date()
{
  DATE  *datestamp;

  if (datestamp = (DATE *) AllocMem(sizeof(DATE), MPC))
  {
    DateStamp(datestamp);
    ULONG  allday = datestamp->ds_Days;

    FreeMem(datestamp, sizeof(DATE));

    UWORD  year   = 1978;
    UBYTE  month  =  1;
    UBYTE  day    =  1;
    UBYTE  today  =  1;
    UBYTE  maxday = 31;

    while (allday--)
    {
      if (day++ == maxday)              /* next month  */
      {
        switch (++month)
        {
        case 2:
          if (year % 4)                 /* no leap-year ?  */
            maxday = 28;
          else
            maxday = 29;
          break;

        case 13:                        /* happy new year  */
          ++year;
          month = 1;

        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
          maxday = 31;
          break;

        default:
          maxday = 30;
          break;
        }
        day = 1;
      }

      if (++today == 8)                 /* next week */
        today = 1;
    }

    int i;

    switch (day)
    {
    case  1:
    case 21:
    case 31:
      i = 1;
      break;
    case  2:
    case 22:
      i = 2;
      break;
    case  3:
    case 23:
      i = 3;
      break;
    default:
      i = 0;
      break;
    }
    sprintf(date_buf, "%s, %d%s %s %d",
            dname[today], day, dayext[i], mname[month], year);
  }
  else
  {
    quit  = TRUE;
    autom = TRUE;
  }
}

