/*----------------------------------------------------------------------------*

         __                                         $RCSfile: banner.c,v $
        / /                                         $Revision: 1.5 $
       / /___ ______ ______ ______ ______ _____     $Date: 93/08/04 22:26:05 $
      / __  // __  // __  // __  // ____// ___/     $Author: tf $
     / /_/ // __  // / / // / / // __/_ / /         $Locker:  $
    /_____//_/ /_//_/ /_//_/ /_//_____//_/          $State: Exp $


          (c) Copyright 1992-93 Tobias Ferber, All Rights Reserved.

 *----------------------------------------------------------------------------*/

#include <stdio.h>

static char rcs_id[]= "$VER: $Id: banner.c,v 1.5 93/08/04 22:26:05 tf Exp $";
#define BANNER &rcs_id[6] /* confusion! */

extern char *ascii32[];

#ifdef AMIGA
#include <exec/types.h>
extern int render_banner();

#else /* !AMIGA */
typedef int BOOL;
#define TRUE  (0==0)
#define FALSE (0!=0)

#endif /* ?AMIGA */

#define IHEIGHT 11  /* height of the internal font */
#define IWIDTH  50  /* maximum width of an internal character */

static char *bstr[IHEIGHT]; /* line buffers for the banner */
static int bpos[IHEIGHT];   /* current position index in each line */

#include <stdarg.h>

void fatal(const char *fmt, ...)
{
  va_list argp;
  va_start(argp,fmt); /* name the last known argument */
  fprintf(stderr,"\rBANNER Failure: ");
  vfprintf(stderr,fmt,argp);
  fprintf(stderr,"\n");
  fflush(stderr);
  va_end(argp); /* just to be sure... */
}

/* free all line buffers in bstr[] */
void free_bstr(void)
{ int i;
  for(i=0;i<IHEIGHT;i++)
    if(bstr[i]) free(bstr[i]);
}

/* allocate line buffers for each line in bstr */
BOOL alloc_bstr(int w)
{ int i;
  BOOL ok=TRUE;
  for(i=0;i<IHEIGHT;i++)
  { bstr[i]= (char *)NULL;
    bpos[i]= 0;
  }
  for(i=0;i<IHEIGHT && ok;i++)
    ok= ((bstr[i]= (char *)malloc(w*IWIDTH))!=NULL);
  if(!ok) free_bstr();
  return ok;
}

/* compute the banner length, which is the #of chars in the longest line
 * of bstr[] minus its italic indention.  This function is needed to perform
 * the italic correction in bfmt()
 */
int blen(void)
{ int i,l=0;
  for(i=0;i<IHEIGHT;i++)
  { int n=bpos[i]+i-IHEIGHT+1;
    if(n>l) l=n;
  }
  return l;
}

/* perform bstr italic correction */
void bfmt(int m)
{ int i,j,l=blen();
  for(i=0;i<IHEIGHT;i++)
  { int n= l- (bpos[i]+i-IHEIGHT+1);
    if(n+m>0)
    { for(j=bpos[i];j<bpos[i]+n+m;j++)
        bstr[i][j]=' ';
      bpos[i]+= n+m;
    }
  }
}

/* compute the height of an internal character */
int cheight(char *t)
{ int h=0;
  while(*t!=(char)-1)
    if(*t++=='\0') ++h;
  return h;
}

void bprint(char *s)
{
  if(alloc_bstr(strlen(s)))
  { int l;
    while(*s!='\0')
    { bfmt(0);
      if((char)31<*s && *s<(char)127)
      { char *t= ascii32[*s-32];
        int i= (int)*t++,
            j= cheight(t)-1;
        while(*t!=(char)-1)
        { char *r= &(bstr[i][bpos[i]]);
          /*printf("i=%d, j=%d, bpos[i]=%d\n",i,j,bpos[i]);*/
          int n=0;
          if(*t==' ') t=&t[j--];
          while(*t!='\0')
          { *r++=*t++;
            ++n;
          }
          ++t; /* skip '\0' */
          bpos[i++]+=n;
        }
      }
      ++s;
    }
    for(l=0;l<IHEIGHT;l++)
    { bstr[l][bpos[l]]='\0';
      puts(bstr[l]);
    }
    free_bstr();
  }
  else fatal("not enough memory!");
}

#ifdef AMIGA
static char *howtouse[]= {
 "STRING",     "/A", "-o", "force next argument to be the banner string",
 "RENDER",     "/S", "-r", "render output from a font's bitmap",
 "NORENDER",   "/S", "-R", "use internal character table (default)",
 "FONT",       "/K", "-f", "set rendering font (default: topaz.font)",
 "SIZE",       "/N", "-s", "specify font size (default: 8)",
 "NORMAL",     "/S", "-n", "set font style to fs_normal (default)",
 "ITALIC",     "/S", "-i", "                  fsf_italic",
 "BOLD",       "/S", "-b", "                  fsf_bold",
 "UNDERLINED", "/S", "-u", "                  fsf_underlined",
 "SET",        "/K", "-1", "set character used for set pixels (default: '*')",
 "UNSET",      "/K", "-0", "set character used for unset pixels (default: ' ')",
 "SMART",      "/S", "-c", "compute characters to use for set/unset pixels",
 "ASPECT",     "/K", "-a", "set rendering aspect (x/y)",
 NULL, NULL, NULL, NULL
};
#endif /* AMIGA */

main(int argc, char *argv[])
{
  BOOL badopt= FALSE;
  char *string= (char *)NULL;

#ifdef AMIGA
  char *fname= "topaz.font",
       c1= '\0',  /* use current character */
       c0= ' ';
  int fsize= 8,
      fstyle= 0,
      aspect= 0;
  BOOL render= FALSE;
#endif /* AMIGA */

  while(--argc>0 && !badopt)
  { char *arg= *++argv;

#ifdef AMIGA
    if(isalpha(*arg))
    { char **aopt= &howtouse[0];
      while(*aopt && stricmp(arg,*aopt))
        aopt= &aopt[4];
      if(*aopt) arg= aopt[2];
      /*if(*aopt) printf("AmigaDOS option %s changed to '%s'\n",aopt[0],aopt[2]);*/
    }

    if(*arg=='-')
    { arg++;
      switch(*arg)
      {
        case 'r':
          render= TRUE;
          break;
        case 'R':
          render= FALSE;
          break;
        case 'f': case 'F':
          if(arg[1]) fname= &arg[1];
          else
          { argv++;
            argc--;
            if(argc>0) fname= argv[0];
            else { fatal("missing font name after keyword");
                   badopt=TRUE;
                 }
          }
          render=TRUE;
          if(stricmp(&fname[strlen(fname)-5],".font"))
          { static char _fname[256];
            sprintf(_fname,"%s.font",fname);
            fname= _fname;
          }
          break;
        case 's': case 'S':
          if(arg[1]) fsize= atol(&arg[1]);
          else
          { argv++;
            argc--;
            if(argc>0) fsize= atol(argv[0]);
            else { fatal("missing font size value after keyword");
                   badopt=TRUE;
                 }
          }
          break;
        case 'n': case 'N':
          fstyle= 0x00;
          break;
        case 'u': case 'U':
          fstyle|= 0x01;
          break;
        case 'b': case 'B':
          fstyle|= 0x02;
        case 'i': case 'I':
          fstyle|= 0x04;
          break;
        case '1':
          if(arg[1]) c1=arg[1];
          else
          { argv++;
            argc--;
            if(argc>0) c1=argv[0][0];
            else { fatal("missing set character after keyword");
                   badopt=TRUE;
                 }
          }
          break;
        case '0':
          if(arg[1]) c0=arg[1];
          else
          { argv++;
            argc--;
            if(argc>0) c0=argv[0][0];
            else { fatal("missing unset character after keyword");
                   badopt=TRUE;
                 }
          }
          break;
        case 'c': case 'C':
          aspect= 2;
          break;
        case 'a': case 'A':
          if(arg[1]) arg= &arg[1];
          else
          { argv++;
            argc--;
            if(argc>0) arg= argv[0];
            else { arg= &arg[1]; /* == '\0' */
                   badopt=TRUE;
                 }
          }
          switch(*arg)
          { case '\0':
              fatal("missing aspect axis (try x or y)");
              badopt=TRUE;
              break;
            case 'x': case 'X':
              aspect=0;
              break;
            case 'y': case 'Y':
              aspect=1;
              break;
            default:
              fatal("illegal aspect '%c'",*arg);
              badopt=TRUE;
              break;
          }
          break;
        case 'o': case 'O':
          if(arg[1]) string= &arg[1];
          else
          { argv++;
            argc--;
            if(argc>0)
            { if(string)
              { if(render)
                  render_banner(string,fname,fsize,fstyle,aspect,c1,c0);
                else
                  bprint(string);
              }
              string= argv[0];
            }
            else { fatal("missing string after keyword");
                   badopt= TRUE;
                 }
          }
          break;
        default:
          fatal("bad option -%c.",*arg);
          badopt=TRUE;
          break;
      }
    }
    else if(*arg=='?')
    { char **usage= &howtouse[0];
      while(*usage)
      { printf("%s%s,",usage[0],usage[1]);
        usage= &usage[4];
      }
      printf("\b:\n\n");
      usage= &howtouse[0];
      while(*usage)
      { printf("%-10s or '%s'  %s\n",usage[0],usage[2],usage[3]);
        usage= &usage[4];
      }
      exit(0);
    }
    else

#endif /* AMIGA */

    { if(string)
      {
#ifdef AMIGA
        if(render)
          render_banner(string,fname,fsize,fstyle,aspect,c1,c0);
        else
#endif
          bprint(string);
      }
      string= arg;
    }
  }
  if(!badopt)
  { if(string)
    {
#ifdef AMIGA
      if(render)
        render_banner(string,fname,fsize,fstyle,aspect,c1,c0);
      else
#endif
        bprint(string);
    }
    else
    { /* fatal("required argument missing");
         badopt=TRUE;
       */
      static char sbuffer[256];
      while(gets(sbuffer)!=0)
      { if(sbuffer[0])
        {
#ifdef AMIGA
          if(render)
            render_banner(sbuffer,fname,fsize,fstyle,aspect,c1,c0);
          else
#endif
            bprint(sbuffer);
        }
      }
    }
  }
  exit(badopt ? 20:0);
}
