#include "FIGlib.h"

#ifdef TIOCGWINSZ
/****************************************************************************

  get_columns

  Determines the number of columns of /dev/tty.  Returns the number of
  columns, or -1 if error.  May return 0 if columns unknown.
  Requires include files <fcntl.h> and <sys/ioctl.h>.
  by Glenn Chappell & Ian Chai 14 Apr 1993

****************************************************************************/

int get_columns()
{
  struct winsize ws;
  int fd,result;

  if ((fd = open("/dev/tty",O_WRONLY))<0) return -1;
  result = ioctl(fd,TIOCGWINSZ,&ws);
  close(fd);
  return result?-1:ws.ws_col;
}
#endif /* ifdef TIOCGWINSZ */


/****************************************************************************

  getparams

  Handles all command-line parameters.  Puts all parameters within
  bounds.

****************************************************************************/

void getparams()
{
  extern char *optarg;
  extern int optind;
  int c; /* "Should" be a char -- need int for "!= -1" test*/
  int columns,infoprint;
  char *controlname,*env;

  env = getenv("FIGLET_FONTDIR");
  if (env!=NULL) {
	fontdirname = env;
	}
  infoprint = -1;
  while ((c = getopt(Myargc,Myargv,"ADEXLRI:xlcrpntvm:w:d:f:C:NFskSWo"))!= -1) {
	  /* Note: -F is not a legal option -- prints a special err message.  */
	switch (c) {
	  case 'A':
		cmdinput = 1;
		break;
	  case 'D':
		deutschflag = 1;
		break;
	  case 'E':
		deutschflag = 0;
		break;
	  case 'X':
		right2left = -1;
		break;
	  case 'L':
		right2left = 0;
		break;
	  case 'R':
		right2left = 1;
		break;
	  case 'x':
		justification = -1;
		break;
	  case 'l':
		justification = 0;
		break;
	  case 'c':
		justification = 1;
		break;
	  case 'r':
		justification = 2;
		break;
	  case 'p':
		paragraphflag = 1;
		break;
	  case 'n':
		paragraphflag = 0;
		break;
	  case 's':
		smushoverride = SMO_NO;
		break;
	  case 'k':
		smushmode = SM_KERN;
		smushoverride = SMO_YES;
		break;
	  case 'S':
		smushmode = SM_SMUSH;
	smushoverride = SMO_FORCE;
		break;
	  case 'o':
		smushmode = SM_SMUSH;
	smushoverride = SMO_YES;
		break;
	  case 'W':
		smushmode = 0;
	smushoverride = SMO_YES;
		break;
	  case 't':
#ifdef TIOCGWINSZ
		columns = get_columns();
		if (columns>0) {
		  outputwidth = columns;
		  }
#else /* ifdef TIOCGWINSZ */
		fprintf(stderr,
		  "%s: \"-t\" is disabled, since ioctl is not fully implemented.\n",
		  myname);
#endif /* ifdef TIOCGWINSZ */
		break;
	  case 'v':
		infoprint = 0;
		break;
	  case 'I':
		infoprint = atoi(optarg);
		break;
	  case 'm':
		smushmode = atoi(optarg);
		if (smushmode < -1) {
		  smushoverride = SMO_NO;
		  break;
		  }
	if (smushmode == 0) smushmode = SM_KERN;
	else if (smushmode == -1) smushmode = 0;
	else smushmode = (smushmode & 63) | SM_SMUSH;
	smushoverride = SMO_YES;
		break;
	  case 'w':
		columns = atoi(optarg);
		if (columns>0) {
		  outputwidth = columns;
		  }
		break;
	  case 'd':
		fontdirname = optarg;
		break;
	  case 'f':
		fontname = optarg;
		if (suffixcmp(fontname,FONTFILESUFFIX)) {
		  fontname[MYSTRLEN(fontname)-FSUFFIXLEN] = '\0';
		  }
#ifdef TLF_FONTS
		else if (suffixcmp(fontname,TOILETFILESUFFIX)) {
		  fontname[MYSTRLEN(fontname)-TSUFFIXLEN] = '\0';
		  }
#endif
		break;
	  case 'C':
		controlname = optarg;
		if (suffixcmp(controlname, CONTROLFILESUFFIX)) {
		  controlname[MYSTRLEN(controlname)-CSUFFIXLEN] = '\0';
		  }
		(*cfilelistend) = (cfnamenode*)myalloc(sizeof(cfnamenode));
		(*cfilelistend)->thename = controlname;
		cfilelistend = &(*cfilelistend)->next;
		(*cfilelistend) = NULL;
		break;
	  case 'N':
		clearcfilelist();
		multibyte = 0;
		gn[0] = 0;
		gn[1] = 0x80;
		gn[2] = gn[3] = 0;
		gndbl[0] = gndbl[1] = gndbl[2] = gndbl[3] = 0;
		gl = 0;
		gr = 1;
		break;
	  case 'F': /* Not a legal option */
		fprintf(stderr,"%s: illegal option -- F\n",myname);
		printusage(stderr);
		fprintf(stderr,
		  "\nBecause of numerous incompatibilities, the"
		  " \"-F\" option has been\n"
		  "removed.  It has been replaced by the \"figlist\""
		  " program, which is now\n"
		  "included in the basic FIGlet package.  \"figlist\""
		  " is also available\n"
		  "from  http://www.figlet.org/"
		  "under UNIX utilities.\n");
		exit(1);
		break;
	  default:
		printusage(stderr);
		exit(1);
	  }
	}
  if (optind!=Myargc) cmdinput = 1; /* force cmdinput if more arguments */
  if (infoprint>=0) {
	printinfo(infoprint);
	exit(0);
	}
}


/****************************************************************************

  main

  The main program, of course.
  Reads characters 1 by 1 from stdin, and makes lines out of them using
  addchar. Handles line breaking, (which accounts for most of the
  complexity in this function).

****************************************************************************/

int main(argc,argv)
int argc;
char *argv[];
{
  inchr c,c2;
  int last_was_eol_flag;

  fig_init(argc, argv);
  getparams();
  readcontrolfiles();
  readfont();
  linealloc();

  last_was_eol_flag = 0;

#ifdef TLF_FONTS
  toiletfont = 0;
#endif

  while ((c = getinchr())!=EOF) {

    if (c=='\n'&&paragraphflag&&!last_was_eol_flag) {
      ungetinchr(c2 = getinchr());
      c = ((isascii(c2)&&isspace(c2))?'\n':' ');
      }
    last_was_eol_flag = (isascii(c)&&isspace(c)&&c!='\t'&&c!=' ');

    if (deutschflag) {
      if (c>='[' && c<=']') {
        c = deutsch[c-'['];
        }
      else if (c >='{' && c <= '~') {
        c = deutsch[c-'{'+3];
        }
      }

    c = handlemapping(c);

    if (isascii(c)&&isspace(c)) {
      c = (c=='\t'||c==' ') ? ' ' : '\n';
      }

    if ((c>'\0' && c<' ' && c!='\n') || c==127) continue;

	fig_puts(c);
  }

  if (outlinelen!=0) {
    fig_flush();
    }

  return 0;
}