diff --git a/FIGlib-test b/FIGlib-test
index 2aa363b..65bfdd2 100755
Binary files a/FIGlib-test and b/FIGlib-test differ
diff --git a/FIGlib.h b/FIGlib.h
index 098d132..61e7449 100644
--- a/FIGlib.h
+++ b/FIGlib.h
@@ -170,1922 +170,1721 @@ outchr **outputline;   /* Alloc'd char outputline[charheight][outlinelenlimit+1]
 	int outlinelen;
 
 
-	/****************************************************************************
+/****************************************************************************
 
-	  Globals dealing with command file storage
+  Globals dealing with command file storage
 
-	****************************************************************************/
+****************************************************************************/
 
-	typedef struct cfn {
-	  char *thename;
-	  struct cfn *next;
-	  } cfnamenode;
+typedef struct cfn {
+  char *thename;
+  struct cfn *next;
+  } cfnamenode;
 
-	cfnamenode *cfilelist,**cfilelistend;
+cfnamenode *cfilelist,**cfilelistend;
 
-	typedef struct cm {
-	  int thecommand;
-	  inchr rangelo;
-	  inchr rangehi;
-	  inchr offset;
-	  struct cm *next;
-	  } comnode;
+typedef struct cm {
+  int thecommand;
+  inchr rangelo;
+  inchr rangehi;
+  inchr offset;
+  struct cm *next;
+  } comnode;
 
-	comnode *commandlist,**commandlistend;
+comnode *commandlist,**commandlistend;
 
-	/****************************************************************************
+/****************************************************************************
 
-	  Globals affected by command line options
+  Globals affected by command line options
 
-	****************************************************************************/
+****************************************************************************/
 
-	int deutschflag,justification,paragraphflag,right2left,multibyte;
-	int cmdinput;
+int deutschflag,justification,paragraphflag,right2left,multibyte;
+int cmdinput;
 
-	#define SM_SMUSH 128
-	#define SM_KERN 64
-	#define SM_EQUAL 1
-	#define SM_LOWLINE 2
-	#define SM_HIERARCHY 4
-	#define SM_PAIR 8
-	#define SM_BIGX 16
-	#define SM_HARDBLANK 32
+#define SM_SMUSH 128
+#define SM_KERN 64
+#define SM_EQUAL 1
+#define SM_LOWLINE 2
+#define SM_HIERARCHY 4
+#define SM_PAIR 8
+#define SM_BIGX 16
+#define SM_HARDBLANK 32
 
-	int smushmode;
+int smushmode;
 
-	#define SMO_NO 0     /* no command-line smushmode */
-	#define SMO_YES 1    /* use command-line smushmode, ignore font smushmode */
-	#define SMO_FORCE 2  /* logically OR command-line and font smushmodes */
+#define SMO_NO 0     /* no command-line smushmode */
+#define SMO_YES 1    /* use command-line smushmode, ignore font smushmode */
+#define SMO_FORCE 2  /* logically OR command-line and font smushmodes */
 
-	int smushoverride;
+int smushoverride;
 
-	int outputwidth;
-	int outlinelenlimit;
-	char *fontdirname,*fontname;
+int outputwidth;
+int outlinelenlimit;
+char *fontdirname,*fontname;
 
 
-	/****************************************************************************
+/****************************************************************************
 
-	  Globals read from font file
+  Globals read from font file
 
-	****************************************************************************/
+****************************************************************************/
 
-	char hardblank;
-	int charheight;
+char hardblank;
+int charheight;
 
 
-	/****************************************************************************
+/****************************************************************************
 
-	  Name of program, used in error messages
+  Name of program, used in error messages
 
-	****************************************************************************/
+****************************************************************************/
 
-	char *myname;
+char *myname;
 
 
-	/*---------------------------------------------------------------------------
-	  Wordbreakmode:
-		-1: /^$/ and blanks are to be absorbed (when line break was forced
-		  by a blank or character larger than outlinelenlimit)
-		0: /^ *$/ and blanks are not to be absorbed
-		1: /[^ ]$/ no word break yet
-		2: /[^ ]  *$/
-		3: /[^ ]$/ had a word break
-	---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------
+  Wordbreakmode:
+	-1: /^$/ and blanks are to be absorbed (when line break was forced
+	  by a blank or character larger than outlinelenlimit)
+	0: /^ *$/ and blanks are not to be absorbed
+	1: /[^ ]$/ no word break yet
+	2: /[^ ]  *$/
+	3: /[^ ]$/ had a word break
+---------------------------------------------------------------------------*/
 
 
-	#ifdef TIOCGWINSZ
-	/****************************************************************************
+/****************************************************************************
 
-	  get_columns
+  myalloc
 
-	  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
+  Calls malloc.  If malloc returns error, prints error message and
+  quits.
 
-	****************************************************************************/
+****************************************************************************/
 
-	int get_columns()
-	{
-	  struct winsize ws;
-	  int fd,result;
+#ifdef __STDC__
+char *myalloc(size_t size)
+#else
+char *myalloc(size)
+int size;
+#endif
+{
+  char *ptr;
+#ifndef __STDC__
+  extern void *malloc();
+#endif
 
-	  if ((fd = open("/dev/tty",O_WRONLY))<0) return -1;
-	  result = ioctl(fd,TIOCGWINSZ,&ws);
-	  close(fd);
-	  return result?-1:ws.ws_col;
+  if ((ptr = (char*)malloc(size))==NULL) {
+	fprintf(stderr,"%s: Out of memory\n",myname);
+	exit(1);
 	}
-	#endif /* ifdef TIOCGWINSZ */
-
-
-	/****************************************************************************
-
-	  myalloc
-
-	  Calls malloc.  If malloc returns error, prints error message and
-	  quits.
-
-	****************************************************************************/
-
-	#ifdef __STDC__
-	char *myalloc(size_t size)
-	#else
-	char *myalloc(size)
-	int size;
-	#endif
-	{
-	  char *ptr;
-	#ifndef __STDC__
-	  extern void *malloc();
-	#endif
-
-	  if ((ptr = (char*)malloc(size))==NULL) {
-		fprintf(stderr,"%s: Out of memory\n",myname);
-		exit(1);
-		}
-	  else {
-		return ptr;
-		}
+  else {
+	return ptr;
 	}
-
-
-	/****************************************************************************
-
-	  hasdirsep
-
-	  Returns true if s1 contains a DIRSEP or DIRSEP2 character.
-
-	****************************************************************************/
-
-	int hasdirsep(s1)
-	char *s1;
-	{
-	  if (strchr(s1, DIRSEP)) return 1;
-	  else if (strchr(s1, DIRSEP2)) return 1;
-	  else return 0;
-	}
-
-	/****************************************************************************
-
-	  suffixcmp
-
-	  Returns true if s2 is a suffix of s1; uses case-blind comparison.
-
-	****************************************************************************/
-
-	int suffixcmp(s1, s2)
-	char *s1;
-	char *s2;
-	{
-	  int len1, len2;
-
-	  len1 = MYSTRLEN(s1);
-	  len2 = MYSTRLEN(s2);
-	  if (len2 > len1) return 0;
-	  s1 += len1 - len2;
-	  while (*s1) {
-		if (tolower(*s1) != tolower(*s2)) return 0;
-		s1++;
-		s2++;
-		}
-	  return 1;
-	}
-	   
-	/****************************************************************************
-
-	  skiptoeol
-
-	  Skips to the end of a line, given a stream.  Handles \r, \n, or \r\n.
-
-	****************************************************************************/
-
-	void skiptoeol(fp)
-	ZFILE *fp;
-	{
-	  int dummy;
-
-	  while (dummy=Zgetc(fp),dummy!=EOF) {
-		if (dummy == '\n') return;
-		if (dummy == '\r') {
-		  dummy = Zgetc(fp);
-		  if (dummy != EOF && dummy != '\n') Zungetc(dummy,fp);
-		  return;
-		  }
-	  }
-	}
-
-
-	/****************************************************************************
-
-	  myfgets
-
-	  Local version of fgets.  Handles \r, \n, and \r\n terminators.
-
-	****************************************************************************/
-
-	char *myfgets(line,maxlen,fp)
-	char *line;
-	int maxlen;
-	ZFILE *fp;
-	{
-	  int c = 0;
-	  char *p;
-
-	  p = line;
-	  while((c=Zgetc(fp))!=EOF&&maxlen) {
-		*p++ = c;
-		maxlen--;
-		if (c=='\n') break;
-		if (c=='\r') {
-		  c = Zgetc(fp);
-		  if (c != EOF && c != '\n') Zungetc(c,fp);
-		  *(p-1) = '\n';
-		  break;
-		  }
-		}
-	  *p = 0;
-	  return (c==EOF) ? NULL : line;
-	}
-
-
-	/****************************************************************************
-
-	  usageerr
-
-	  Prints "Usage: ...." line to the given stream.
-
-	****************************************************************************/
-
-	void printusage(out)
-	FILE *out;
-	{
-	  fprintf(out,
-		"Usage: %s [ -cklnoprstvxDELNRSWX ] [ -d fontdirectory ]\n",
-		"              [ -f fontfile ] [ -m smushmode ] [ -w outputwidth ]\n"
-		"              [ -C controlfile ] [ -I infocode ] [ message ]\n",
-		myname);
-	}
-
-
-	/****************************************************************************
-
-	  printinfo
-
-	  Prints version and copyright message, or utility information.
-
-	****************************************************************************/
-
-	void printinfo(infonum)
-	int infonum;
-	{
-	  switch (infonum) {
-		case 0: /* Copyright message */
-		  printf("FIGlet Copyright (C) 1991-2012 Glenn Chappell, Ian Chai, "
-				 "John Cowan,\nChristiaan Keet and Claudio Matsuoka\n"
-				 "Internet: <info@figlet.org> "
-				 "Version: %s, date: %s\n\n"
-				 "FIGlet, along with the various FIGlet fonts"
-				 " and documentation, may be\n"
-				 "freely copied and distributed.\n\n"
-				 "If you use FIGlet, please send an"
-				 " e-mail message to <info@figlet.org>.\n\n"
-				 "The latest version of FIGlet is available from the"
-				 " web site,\n\thttp://www.figlet.org/\n\n",
-		   VERSION,DATE);
-		  printusage(stdout);
-		  break;
-		case 1: /* Version (integer) */
-		  printf("%d\n",VERSION_INT);
-		  break;
-		case 2: /* Font directory */
-		  printf("%s\n",fontdirname);
-		  break;
-		case 3: /* Font */
-		  printf("%s\n",fontname);
-		  break;
-		case 4: /* Outputwidth */
-		  printf("%d\n",outputwidth);
-		  break;
-		case 5: /* Font formats */
-		  printf("%s", FONTFILEMAGICNUMBER);
-	#ifdef TLF_FONTS
-		  printf(" %s", TOILETFILEMAGICNUMBER);
-	#endif
-		  printf("\n");
-		}
-	}
-
-
-	/****************************************************************************
-
-	  readmagic
-
-	  Reads a four-character magic string from a stream.
-
-	****************************************************************************/
-	void readmagic(fp,magic)
-	ZFILE *fp;
-	char *magic;
-	{
-	  int i;
-
-	  for (i=0;i<4;i++) {
-		magic[i] = Zgetc(fp);
-		}
-	  magic[4] = 0;
-	  }
-	  
-	/****************************************************************************
-
-	  skipws
-
-	  Skips whitespace characters from a stream.
-
-	****************************************************************************/
-	void skipws(fp)
-	ZFILE *fp;
-	{
-	  int c;
-	  while (c=Zgetc(fp),isascii(c)&&isspace(c)) ;
-	  Zungetc(c,fp);
-	  }
-
-	/****************************************************************************
-
-	  readnum
-
-	  Reads a number from a stream.  Accepts "0" prefix for octal and
-	  "0x" or "0X" for hexadecimal.  Ignores leading whitespace.
-
-	****************************************************************************/
-	void readnum(fp,nump)
-	ZFILE *fp;
-	inchr *nump;
-	{
-	  int acc = 0;
-	  char *p;
-	  int c;
-	  int base;
-	  int sign = 1;
-	  char digits[] = "0123456789ABCDEF";
-
-	  skipws(fp);
-	  c = Zgetc(fp);
-	  if (c=='-') {
-		sign = -1;
-		}
-	  else {
-		Zungetc(c,fp);
-		}
-	  c = Zgetc(fp);
-	  if (c=='0') {
-		 c = Zgetc(fp);
-		 if (c=='x'||c=='X') {
-		   base = 16;
-		   }
-		 else {
-		   base = 8;
-		   Zungetc(c,fp);
-		   }
-		}
-	  else {
-		base = 10;
-		Zungetc(c,fp);
-		}
-
-	  while((c=Zgetc(fp))!=EOF) {
-		c=toupper(c);
-		p=strchr(digits,c);
-		if (!p) {
-		  Zungetc(c,fp);
-		  *nump = acc * sign;
-		  return;
-		  }
-		acc = acc*base+(p-digits);
-		}
-	  *nump = acc * sign;
-	  }  
-
-	/****************************************************************************
-
-	  readTchar
-
-	  Reads a control file "T" command character specification.
-
-	  Character is a single byte, an escape sequence, or
-	  an escaped numeric.
-
-	****************************************************************************/
-
-	inchr readTchar(fp)
-	ZFILE *fp;
-	{
-	  inchr thechar;
-	  char next;
-
-	  thechar=Zgetc(fp);
-	  if (thechar=='\n' || thechar=='\r') { /* Handle badly-formatted file */
-		Zungetc(thechar,fp);
-		return '\0';
-		}
-	  if (thechar!='\\') return thechar;
-	  next=Zgetc(fp);
-	  switch(next) {
-		case 'a':
-		  return 7;
-		case 'b':
-		  return 8;
-		case 'e':
-		  return 27;
-		case 'f':
-		  return 12;
-		case 'n':
-		  return 10;
-		case 'r':
-		  return 13;
-		case 't':
-		  return 9;
-		case 'v':
-		  return 11;
-		default:
-		  if (next=='-' || next=='x' || (next>='0' && next<='9')) {
-			Zungetc(next,fp);
-			readnum(fp,&thechar);
-			return thechar;
-			}
-		  return next;
-		}
-	}
-
-	/****************************************************************************
-
-	  charsetname
-
-	  Get a Tchar representing a charset name, or 0 if none available.
-	  Called in getcharset().
-
-	****************************************************************************/
-
-	inchr charsetname(fp)
-	ZFILE *fp;
-	{
-	  inchr result;
-
-	  result = readTchar(fp);
-	  if (result == '\n' || result == '\r') {
-		result = 0;
-		Zungetc(result,fp);
-		}
-	  return result;
-	  }
-
-	/****************************************************************************
-
-	  charset
-
-	  Processes "g[0123]" character set specifier
-	  Called in readcontrol().
-
-	****************************************************************************/
-
-	void charset(n, controlfile)
-	int n;
-	ZFILE *controlfile;
-	{
-	  int ch;
-
-	  skipws(controlfile);
-	  if (Zgetc(controlfile) != '9') {
-		skiptoeol(controlfile);
-		return;
-		}
-	  ch = Zgetc(controlfile);
-	  if (ch == '6') {
-		 gn[n] = 65536L * charsetname(controlfile) + 0x80;
-		 gndbl[n] = 0;
-		 skiptoeol(controlfile);
-		 return;
-		 }
-	  if (ch != '4') {
-		skiptoeol(controlfile);
-		return;
-		}
-	  ch = Zgetc(controlfile);
-	  if (ch == 'x') {
-		 if (Zgetc(controlfile) != '9') {
-		   skiptoeol(controlfile);
-		   return;
-		   }
-		 if (Zgetc(controlfile) != '4') {
-		   skiptoeol(controlfile);
-		   return;
-		   }
-		 skipws(controlfile);
-		 gn[n] = 65536L * charsetname(controlfile);
-		 gndbl[n] = 1;
-		 skiptoeol(controlfile);
-		 return;
-		 }
-	  Zungetc(ch, controlfile);
-	  skipws(controlfile);
-	  gn[n] = 65536L * charsetname(controlfile);
-	  gndbl[n] = 0;
-	  return;
-	  }
-
-	/****************************************************************************
-
-	  FIGopen
-
-	  Given a FIGlet font or control file name and suffix, return the file
-	  or NULL if not found
-
-	****************************************************************************/
-
-	ZFILE *FIGopen(name,suffix)
-	char *name;
-	char *suffix;
-	{
-	  char *fontpath;
-	  ZFILE *fontfile;
-	  struct stat st;
-	  int namelen;
-
-	  namelen = MYSTRLEN(fontdirname);
-	  fontpath = (char*)alloca(sizeof(char)*
-		(namelen+MYSTRLEN(name)+MYSTRLEN(suffix)+2));
-	  fontfile = NULL;
-	  if (!hasdirsep(name)) {  /* not a full path name */
-		strcpy(fontpath,fontdirname);
-		fontpath[namelen] = DIRSEP;
-		fontpath[namelen+1] = '\0';
-		strcat(fontpath,name);
-		strcat(fontpath,suffix);
-		if(stat(fontpath,&st)==0) goto ok;
-		}
-	  /* just append suffix */
-	  strcpy(fontpath,name);
-	  strcat(fontpath,suffix);
-	  if(stat(fontpath,&st)==0) goto ok;
-
-	  return NULL;
-
-	ok:
-	  fontfile = Zopen(fontpath,"rb");
-	  return fontfile;
-	}
-
-	/****************************************************************************
-
-	  readcontrol
-
-	  Allocates memory and reads in the given control file.
-	  Called in readcontrolfiles().
-
-	****************************************************************************/
-
-	void readcontrol(controlname)
-	char *controlname;
-	{
-	  inchr firstch,lastch;
-	  char dashcheck;
-	  inchr offset;
-	  int command;
-	  ZFILE *controlfile;
-
-	  controlfile = FIGopen(controlname,CONTROLFILESUFFIX);
-
-	  if (controlfile==NULL) {
-		fprintf(stderr,"%s: %s: Unable to open control file\n",myname,
-		  controlname);
-		exit(1);
-		}
-
-	  (*commandlistend) = (comnode*)myalloc(sizeof(comnode));
-	  (*commandlistend)->thecommand = 0; /* Begin with a freeze command */
-	  commandlistend = &(*commandlistend)->next;
-	  (*commandlistend) = NULL;
-
-	  while(command=Zgetc(controlfile),command!=EOF) {
-		switch (command) {
-		  case 't': /* Translate */
-			skipws(controlfile);
-			firstch=readTchar(controlfile);
-			if ((dashcheck=Zgetc(controlfile))=='-') {
-			  lastch=readTchar(controlfile);
-			  }
-			else {
-			  Zungetc(dashcheck,controlfile);
-			  lastch=firstch;
-			  }
-			skipws(controlfile);
-			offset=readTchar(controlfile)-firstch;
-			skiptoeol(controlfile);
-			(*commandlistend) = (comnode*)myalloc(sizeof(comnode));
-			(*commandlistend)->thecommand = 1;
-			(*commandlistend)->rangelo = firstch;
-			(*commandlistend)->rangehi = lastch;
-			(*commandlistend)->offset = offset;
-			commandlistend = &(*commandlistend)->next;
-			(*commandlistend) = NULL;
-			break;
-		  case '0': case '1': case '2': case '3': case '4':
-		  case '5': case '6': case '7': case '8': case '9':
-		  case '-':
-					/* Mapping table entry */
-			Zungetc(command,controlfile);
-			readnum(controlfile,&firstch);
-			skipws(controlfile);
-		readnum(controlfile,&lastch);
-		offset=lastch-firstch;
-			lastch=firstch;
-			skiptoeol(controlfile);
-			(*commandlistend) = (comnode*)myalloc(sizeof(comnode));
-			(*commandlistend)->thecommand = 1;
-			(*commandlistend)->rangelo = firstch;
-			(*commandlistend)->rangehi = lastch;
-			(*commandlistend)->offset = offset;
-			commandlistend = &(*commandlistend)->next;
-			(*commandlistend) = NULL;
-			break;
-		  case 'f': /* freeze */
-			skiptoeol(controlfile);
-			(*commandlistend) = (comnode*)myalloc(sizeof(comnode));
-			(*commandlistend)->thecommand = 0;
-			commandlistend = &(*commandlistend)->next;
-			(*commandlistend) = NULL;
-			break;
-		  case 'b': /* DBCS input mode */
-			multibyte = 1;
-			break;
-		  case 'u': /* UTF-8 input mode */
-			multibyte = 2;
-			break;
-		  case 'h': /* HZ input mode */
-			multibyte = 3;
-			break;
-		  case 'j': /* Shift-JIS input mode */
-			multibyte = 4;
-			break;
-		  case 'g': /* ISO 2022 character set choices */
-			multibyte = 0;
-			skipws(controlfile);
-			command=Zgetc(controlfile);
-			switch (command) {
-			  case '0': /* define G0 charset */
-				charset(0, controlfile);
-				break;
-			  case '1': /* set G1 charset */
-				charset(1, controlfile);
-				break;
-			  case '2': /* set G2 charset */
-				charset(2, controlfile);
-				break;
-			  case '3': /* set G3 charset */
-				charset(3, controlfile);
-				break;
-			  case 'l': case 'L': /* define left half */
-				skipws(controlfile);
-				gl = Zgetc(controlfile) - '0';
-				skiptoeol(controlfile);
-				break;
-			  case 'r': case 'R': /* define right half */
-				skipws(controlfile);
-				gr = Zgetc(controlfile) - '0';
-				skiptoeol(controlfile);
-				break;
-			  default: /* meaningless "g" command */
-				skiptoeol(controlfile);
-			  }
-		  case '\r': case '\n': /* blank line */
-			break;
-		  default: /* Includes '#' */
-			skiptoeol(controlfile);
-		  }
-		}
-	  Zclose(controlfile);
-	}
-
-
-	/****************************************************************************
-
-	  readcontrolfiles
-
-	  Reads in the controlfiles names in cfilelist.  Uses readcontrol.
-	  Called in main().
-
-	****************************************************************************/
-
-	void readcontrolfiles()
-	{
-	  cfnamenode *cfnptr;
-
-	  for (cfnptr=cfilelist;cfnptr!=NULL;cfnptr=cfnptr->next) {
-		readcontrol(cfnptr->thename);
-		}
-	}
-
-
-	/****************************************************************************
-
-	  clearcfilelist
-
-	  Clears the control file list.  Assumes thename does not need freeing.
-
-	****************************************************************************/
-
-	void clearcfilelist()
-	{
-	  cfnamenode *cfnptr1,*cfnptr2;
-
-	  cfnptr1 = cfilelist;
-	  while (cfnptr1 != NULL) {
-		cfnptr2 = cfnptr1->next;
-		free(cfnptr1);
-		cfnptr1 = cfnptr2;
-		}
-	  cfilelist = NULL;
-	  cfilelistend = &cfilelist;
-	}
-
-
-	/****************************************************************************
-
-	  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);
-		}
-	}
-
-
-	/****************************************************************************
-
-	  clearline
-
-	  Clears both the input (inchrline) and output (outputline) storage.
-
-	****************************************************************************/
-
-	void clearline()
-	{
-	  int i;
-
-	  for (i=0;i<charheight;i++) {
-		outputline[i][0] = '\0';
-		}
-	  outlinelen = 0;
-	  inchrlinelen = 0;
-	}
-
-
-	/****************************************************************************
-
-	  readfontchar
-
-	  Reads a font character from the font file, and places it in a
-	  newly-allocated entry in the list.
-
-	****************************************************************************/
-
-	void readfontchar(file,theord)
-	ZFILE *file;
-	inchr theord;
-	{
-	  int row,k;
-	  char templine[MAXLEN+1];
-	  outchr endchar, outline[MAXLEN+1];
-	  fcharnode *fclsave;
-
-	  fclsave = fcharlist;
-	  fcharlist = (fcharnode*)myalloc(sizeof(fcharnode));
-	  fcharlist->ord = theord;
-	  fcharlist->thechar = (outchr**)myalloc(sizeof(outchr*)*charheight);
-	  fcharlist->next = fclsave;
-
-	  outline[0] = 0;
-
-	  for (row=0;row<charheight;row++) {
-		if (myfgets(templine,MAXLEN,file)==NULL) {
-		  templine[0] = '\0';
-		  }
-	#ifdef TLF_FONTS
-		utf8_to_wchar(templine,MAXLEN,outline,MAXLEN,0);
-	#else
-		strcpy(outline,templine);
-	#endif
-		k = STRLEN(outline)-1;
-		while (k>=0 && ISSPACE(outline[k])) {  /* remove trailing spaces */
-		  k--;
-		  }
-		if (k>=0) {
-		  endchar = outline[k];  /* remove endmarks */
-		  while (k>=0 && outline[k]==endchar) {
-			k--;
-			}
-		  }
-		outline[k+1] = '\0';
-		fcharlist->thechar[row] = (outchr*)myalloc(sizeof(outchr)*(STRLEN(outline)+1));
-		STRCPY(fcharlist->thechar[row],outline);
-		}
-	}
-
-
-	/****************************************************************************
-
-	  readfont
-
-	  Allocates memory, initializes variables, and reads in the font.
-	  Called near beginning of main().
-
-	****************************************************************************/
-
-	void readfont()
-	{
-	  int i,row,numsread;
-	  inchr theord;
-	  int maxlen,cmtlines,ffright2left;
-	  int smush,smush2;
-	  char fileline[MAXLEN+1],magicnum[5];
-	  ZFILE *fontfile;
-
-	  fontfile = FIGopen(fontname,FONTFILESUFFIX);
-	#ifdef TLF_FONTS
-	  if (fontfile==NULL) {
-		fontfile = FIGopen(fontname,TOILETFILESUFFIX);
-		if(fontfile) toiletfont = 1;
-		}
-	#endif
-
-	  if (fontfile==NULL) {
-		fprintf(stderr,"%s: %s: Unable to open font file\n",myname,fontname);
-		exit(1);
-		}
-
-	  readmagic(fontfile,magicnum);
-	  if (myfgets(fileline,MAXLEN,fontfile)==NULL) {
-		fileline[0] = '\0';
-		}
-	  if (MYSTRLEN(fileline)>0 ? fileline[MYSTRLEN(fileline)-1]!='\n' : 0) {
-		skiptoeol(fontfile);
-		}
-	  numsread = sscanf(fileline,"%*c%c %d %*d %d %d %d %d %d",
-		&hardblank,&charheight,&maxlen,&smush,&cmtlines,
-		&ffright2left,&smush2);
-
-	  if (maxlen > MAXLEN) {
-		fprintf(stderr,"%s: %s: character is too wide\n",myname,fontname);
-		exit(1);
-		}
-	#ifdef TLF_FONTS
-	  if ((!toiletfont && strcmp(magicnum,FONTFILEMAGICNUMBER)) ||
-		  (toiletfont && strcmp(magicnum,TOILETFILEMAGICNUMBER)) || numsread<5) {
-	#else
-	  if (strcmp(magicnum,FONTFILEMAGICNUMBER) || numsread<5) {
-	#endif
-		fprintf(stderr,"%s: %s: Not a FIGlet 2 font file\n",myname,fontname);
-		exit(1);
-		}
-	  for (i=1;i<=cmtlines;i++) {
-		skiptoeol(fontfile);
-		}
-
-	  if (numsread<6) {
-		ffright2left = 0;
-		}
-
-	  if (numsread<7) { /* if no smush2, decode smush into smush2 */
-		if (smush == 0) smush2 = SM_KERN;
-		else if (smush < 0) smush2 = 0;
-		else smush2 = (smush & 31) | SM_SMUSH;
-		}
-
-	  if (charheight<1) {
-		charheight = 1;
-		}
-
-	  if (maxlen<1) {
-		maxlen = 1;
-		}
-
-	  maxlen += 100; /* Give ourselves some extra room */
-
-	  if (smushoverride == SMO_NO)
-		 smushmode = smush2;
-	  else if (smushoverride == SMO_FORCE)
-		 smushmode |= smush2;
-
-	  if (right2left<0) {
-		right2left = ffright2left;
-		}
-
-	  if (justification<0) {
-		justification = 2*right2left;
-		}
-
-	  /* Allocate "missing" character */
-	  fcharlist = (fcharnode*)myalloc(sizeof(fcharnode));
-	  fcharlist->ord = 0;
-	  fcharlist->thechar = (outchr**)myalloc(sizeof(outchr*)*charheight);
-	  fcharlist->next = NULL;
-	  for (row=0;row<charheight;row++) {
-		fcharlist->thechar[row] = (outchr*)myalloc(sizeof(outchr));
-		fcharlist->thechar[row][0] = '\0';
-		}
-	  for (theord=' ';theord<='~';theord++) {
-		readfontchar(fontfile,theord);
-		}
-	  for (theord=0;theord<=6;theord++) {
-		readfontchar(fontfile,deutsch[theord]);
-		}
-	  while (myfgets(fileline,maxlen+1,fontfile)==NULL?0:
-		sscanf(fileline,"%li",&theord)==1) {
-		readfontchar(fontfile,theord);
-		}
-	  Zclose(fontfile);
-	}
-
-
-	/****************************************************************************
-
-	  linealloc
-
-	  Allocates & clears outputline, inchrline. Sets inchrlinelenlimit.
-	  Called near beginning of main().
-
-	****************************************************************************/
-
-	void linealloc()
-	{
-	  int row; 
-
-	  outputline = (outchr**)myalloc(sizeof(outchr*)*charheight);
-	  for (row=0;row<charheight;row++) {
-		outputline[row] = (outchr*)myalloc(sizeof(outchr)*(outlinelenlimit+1));
-		}
-	  inchrlinelenlimit = outputwidth*4+100;
-	  inchrline = (inchr*)myalloc(sizeof(inchr)*(inchrlinelenlimit+1));
-	  clearline();
-	}
-
-
-	/****************************************************************************
-
-	  getletter
-
-	  Sets currchar to point to the font entry for the given character.
-	  Sets currcharwidth to the width of this character.
-
-	****************************************************************************/
-
-	void getletter(c)
-	inchr c;
-	{
-	  fcharnode *charptr;
-
-	  for (charptr=fcharlist;charptr==NULL?0:charptr->ord!=c;
-		charptr=charptr->next) ;
-	  if (charptr!=NULL) {
-		currchar = charptr->thechar;
-		}
-	  else {
-		for (charptr=fcharlist;charptr==NULL?0:charptr->ord!=0;
-		  charptr=charptr->next) ;
-		currchar = charptr->thechar;
-		}
-	  previouscharwidth = currcharwidth;
-	  currcharwidth = STRLEN(currchar[0]);
-	}
-
-
-	/****************************************************************************
-
-	  smushem
-
-	  Given 2 characters, attempts to smush them into 1, according to
-	  smushmode.  Returns smushed character or '\0' if no smushing can be
-	  done.
-
-	  smushmode values are sum of following (all values smush blanks):
-		1: Smush equal chars (not hardblanks)
-		2: Smush '_' with any char in hierarchy below
-		4: hierarchy: "|", "/\", "[]", "{}", "()", "<>"
-		   Each class in hier. can be replaced by later class.
-		8: [ + ] -> |, { + } -> |, ( + ) -> |
-	   16: / + \ -> X, > + < -> X (only in that order)
-	   32: hardblank + hardblank -> hardblank
-
-	****************************************************************************/
-
-	outchr smushem(lch,rch)
-	outchr lch,rch;
-	{
-	  if (lch==' ') return rch;
-	  if (rch==' ') return lch;
-
-	  if (previouscharwidth<2 || currcharwidth<2) return '\0';
-		/* Disallows overlapping if the previous character */
-		/* or the current character has a width of 1 or zero. */
-
-	  if ((smushmode & SM_SMUSH) == 0) return '\0';  /* kerning */
-
-	  if ((smushmode & 63) == 0) {
-		/* This is smushing by universal overlapping. */
-		/* Unreachable code: lch==' ' or rch==' ' already handled!
-		if (lch==' ') return rch;
-		if (rch==' ') return lch;
-		*/
-
-		if (lch==hardblank) return rch;
-		if (rch==hardblank) return lch;
-		  /* Above four lines ensure overlapping preference to */
-		  /* visible characters. */
-		if (right2left==1) return lch;
-		  /* Above line ensures that the dominant (foreground) */
-		  /* fig-character for overlapping is the latter in the */
-		  /* user's text, not necessarily the rightmost character. */
-		return rch;
-		  /* Occurs in the absence of above exceptions. */
-		}
-	  
-	  if (smushmode & SM_HARDBLANK) {
-		if (lch==hardblank && rch==hardblank) return lch;
-		}
-
-	  if (lch==hardblank || rch==hardblank) return '\0';
-
-	  if (smushmode & SM_EQUAL) {
-		if (lch==rch) return lch;
-		}
-
-	  if (smushmode & SM_LOWLINE) {
-		if (lch=='_' && strchr("|/\\[]{}()<>",rch)) return rch;
-		if (rch=='_' && strchr("|/\\[]{}()<>",lch)) return lch;
-		}
-
-	  if (smushmode & SM_HIERARCHY) {
-		if (lch=='|' && strchr("/\\[]{}()<>",rch)) return rch;
-		if (rch=='|' && strchr("/\\[]{}()<>",lch)) return lch;
-		if (strchr("/\\",lch) && strchr("[]{}()<>",rch)) return rch;
-		if (strchr("/\\",rch) && strchr("[]{}()<>",lch)) return lch;
-		if (strchr("[]",lch) && strchr("{}()<>",rch)) return rch;
-		if (strchr("[]",rch) && strchr("{}()<>",lch)) return lch;
-		if (strchr("{}",lch) && strchr("()<>",rch)) return rch;
-		if (strchr("{}",rch) && strchr("()<>",lch)) return lch;
-		if (strchr("()",lch) && strchr("<>",rch)) return rch;
-		if (strchr("()",rch) && strchr("<>",lch)) return lch;
-		}
-
-	  if (smushmode & SM_PAIR) {
-		if (lch=='[' && rch==']') return '|';
-		if (rch=='[' && lch==']') return '|';
-		if (lch=='{' && rch=='}') return '|';
-		if (rch=='{' && lch=='}') return '|';
-		if (lch=='(' && rch==')') return '|';
-		if (rch=='(' && lch==')') return '|';
-		}
-
-	  if (smushmode & SM_BIGX) {
-		if (lch=='/' && rch=='\\') return '|';
-		if (rch=='/' && lch=='\\') return 'Y';
-		if (lch=='>' && rch=='<') return 'X';
-		  /* Don't want the reverse of above to give 'X'. */
-		}
-
-	  return '\0';
-	}
-
-
-	/****************************************************************************
-
-	  smushamt
-
-	  Returns the maximum amount that the current character can be smushed
-	  into the current line.
-
-	****************************************************************************/
-
-	int smushamt()
-	{
-	  int maxsmush,amt;
-	  int row,linebd,charbd;
-	  outchr ch1,ch2;
-
-	  if ((smushmode & (SM_SMUSH | SM_KERN)) == 0) {
-		return 0;
-		}
-	  maxsmush = currcharwidth;
-	  for (row=0;row<charheight;row++) {
-		if (right2left) {
-		  if (maxsmush>STRLEN(outputline[row])) {
-			maxsmush=STRLEN(outputline[row]);
-			}
-		  for (charbd=STRLEN(currchar[row]);
-			ch1=currchar[row][charbd],(charbd>0&&(!ch1||ch1==' '));charbd--) ;
-		  for (linebd=0;ch2=outputline[row][linebd],ch2==' ';linebd++) ;
-		  amt = linebd+currcharwidth-1-charbd;
-		  }
-		else {
-		  for (linebd=STRLEN(outputline[row]);
-			ch1 = outputline[row][linebd],(linebd>0&&(!ch1||ch1==' '));linebd--) ;
-		  for (charbd=0;ch2=currchar[row][charbd],ch2==' ';charbd++) ;
-		  amt = charbd+outlinelen-1-linebd;
-		  }
-		if (!ch1||ch1==' ') {
-		  amt++;
-		  }
-		else if (ch2) {
-		  if (smushem(ch1,ch2)!='\0') {
-			amt++;
-			}
-		  }
-		if (amt<maxsmush) {
-		  maxsmush = amt;
-		  }
-		}
-	  return maxsmush;
-	}
-
-
-	/****************************************************************************
-
-	  addchar
-
-	  Attempts to add the given character onto the end of the current line.
-	  Returns 1 if this can be done, 0 otherwise.
-
-	****************************************************************************/
-
-	int addchar(c)
-	inchr c;
-	{
-	  int smushamount,row,k,column;
-	  outchr *templine;
-
-	  getletter(c);
-	  smushamount = smushamt();
-	  if (outlinelen+currcharwidth-smushamount>outlinelenlimit
-		  ||inchrlinelen+1>inchrlinelenlimit) {
-		return 0;
-		}
-
-	  templine = (outchr*)myalloc(sizeof(outchr)*(outlinelenlimit+1));
-	  for (row=0;row<charheight;row++) {
-		if (right2left) {
-		  STRCPY(templine,currchar[row]);
-		  for (k=0;k<smushamount;k++) {
-			templine[currcharwidth-smushamount+k] =
-			  smushem(templine[currcharwidth-smushamount+k],outputline[row][k]);
-			}
-		  STRCAT(templine,outputline[row]+smushamount);
-		  STRCPY(outputline[row],templine);
-		  }
-		else {
-		  for (k=0;k<smushamount;k++) {
-		column = outlinelen-smushamount+k;
-		if (column < 0) {
-		  column = 0;
-		  }
-			outputline[row][column] =
-			  smushem(outputline[row][column],currchar[row][k]);
-			}
-		  STRCAT(outputline[row],currchar[row]+smushamount);
-		  }
-		}
-	  free(templine);
-	  outlinelen = STRLEN(outputline[0]);
-	  inchrline[inchrlinelen++] = c;
-	  return 1;
-	}
-
-
-	/****************************************************************************
-
-	  putstring
-
-	  Prints out the given null-terminated string, substituting blanks
-	  for hardblanks.  If outputwidth is 1, prints the entire string;
-	  otherwise prints at most outputwidth-1 characters.  Prints a newline
-	  at the end of the string.  The string is left-justified, centered or
-	  right-justified (taking outputwidth as the screen width) if
-	  justification is 0, 1 or 2, respectively.
-
-	****************************************************************************/
-
-	void putstring(string)
-	outchr *string;
-	{
-	  int i,len;
-	  char c[10];
-	#ifdef TLF_FONTS
-	  size_t size;
-	  wchar_t wc[2];
-	#endif
-
-	  len = STRLEN(string);
-	  if (outputwidth>1) {
-		if (len>outputwidth-1) {
-		  len = outputwidth-1;
-		  }
-		if (justification>0) {
-		  for (i=1;(3-justification)*i+len+justification-2<outputwidth;i++) {
-			putchar(' ');
-			}
-		  }
-		}
-	  for (i=0;i<len;i++) {
-	#ifdef TLF_FONTS
-		wc[0] = string[i];
-		wc[1] = 0;
-		size = wchar_to_utf8(wc,1,c,10,0);
-		if(size==1) {
-		  if(c[0]==hardblank) {
-			c[0] = ' ';
-			}
-		  }
-		c[size] = 0;
-		printf("%s",c);
-	#else
-		putchar(string[i]==hardblank?' ':string[i]);
-	#endif
-		}
-	  putchar('\n');
-	}
-
-
-	/****************************************************************************
-
-	  printline
-
-	  Prints outputline using putstring, then clears the current line.
-
-	****************************************************************************/
-
-	void printline()
-	{
-	  int i;
-
-	  for (i=0;i<charheight;i++) {
-		putstring(outputline[i]);
-		}
-	  clearline();
-	}
-
-
-	/****************************************************************************
-
-	  splitline
-
-	  Splits inchrline at the last word break (bunch of consecutive blanks).
-	  Makes a new line out of the first part and prints it using
-	  printline.  Makes a new line out of the second part and returns.
-
-	****************************************************************************/
-
-	void splitline()
-	{
-	  int i,gotspace,lastspace,len1,len2;
-	  inchr *part1,*part2;
-
-	  part1 = (inchr*)myalloc(sizeof(inchr)*(inchrlinelen+1));
-	  part2 = (inchr*)myalloc(sizeof(inchr)*(inchrlinelen+1));
-	  gotspace = 0;
-	  lastspace = inchrlinelen-1;
-	  for (i=inchrlinelen-1;i>=0;i--) {
-		if (!gotspace && inchrline[i]==' ') {
-		  gotspace = 1;
-		  lastspace = i;
-		  }
-		if (gotspace && inchrline[i]!=' ') {
-		  break;
-		  }
-		}
-	  len1 = i+1;
-	  len2 = inchrlinelen-lastspace-1;
-	  for (i=0;i<len1;i++) {
-		part1[i] = inchrline[i];
-		}
-	  for (i=0;i<len2;i++) {
-		part2[i] = inchrline[lastspace+1+i];
-		}
-	  clearline();
-	  for (i=0;i<len1;i++) {
-		addchar(part1[i]);
-		}
-	  printline();
-	  for (i=0;i<len2;i++) {
-		addchar(part2[i]);
-		}
-	  free(part1);
-	  free(part2);
-	}
-
-
-	/****************************************************************************
-
-	  handlemapping
-
-	  Given an input character (type inchr), executes re-mapping commands
-	  read from control files.  Returns re-mapped character (inchr).
-
-	****************************************************************************/
-
-	inchr handlemapping(c)
-	inchr c;
-	{
-	  comnode *cmptr;
-
-	  cmptr=commandlist;
-	  while (cmptr!=NULL) {
-		if (cmptr->thecommand ?
-		  (c >= cmptr->rangelo && c <= cmptr->rangehi) : 0) {
-		  c += cmptr->offset;
-		  while(cmptr!=NULL ? cmptr->thecommand : 0) {
-			cmptr=cmptr->next;
-			}
-		  }
-		else {
-		  cmptr=cmptr->next;
-		  }
-		}
-	  return c;
-	}
-
-	/****************************************************************************
-
-	  Agetchar
-
-	  Replacement to getchar().
-	  Acts exactly like getchar if -A is NOT specified,
-	  else obtains input from All remaining command line words.
-
-	****************************************************************************/
-
-	int Agetchar()
-	{
-		extern int optind;		/* current argv[] element under study */
-		static int AgetMode = 0;	/* >= 0 for displacement into argv[n], <0 EOF */
-		char   *arg;		/* pointer to active character */
-		int    c;			/* current character */
-
-		if ( ! cmdinput )		/* is -A active? */
-		return( getchar() );	/* no: return stdin character */
-
-		if ( AgetMode < 0 || optind >= Myargc )		/* EOF is sticky: */
-		return( EOF );		/* **ensure it now and forever more */
-
-		/* find next character */
-		arg = Myargv[optind];		/* pointer to active arg */
-		c = arg[AgetMode++]&0xFF;	/* get appropriate char of arg */
-
-		if ( ! c )			/* at '\0' that terminates word? */
-		{   /* at end of word: return ' ' if normal word, '\n' if empty */
-		c = ' ';		/* suppose normal word and return blank */
-		if ( AgetMode == 1 )	/* if ran out in very 1st char, force \n */
-			c = '\n';		/* (allows "hello '' world" to do \n at '') */
-		AgetMode = 0;		/* return to char 0 in NEXT word */
-		if ( ++optind >= Myargc )	/* run up word count and check if at "EOF" */
-		{   /* just ran out of arguments */
-			c = EOF;		/* return EOF */
-			AgetMode = -1;	/* ensure all future returns return EOF */
-		}
-		}
-
-		return( c );		/* return appropriate character */
-
-	}	/* end: Agetchar() */
-
-
-	/****************************************************************************
-
-	  iso2022
-
-	  Called by getinchr.  Interprets ISO 2022 sequences
-
-	******************************************************************************/
-
-	inchr iso2022()
-	{
-	  inchr ch;
-	  inchr ch2;
-	  int save_gl;
-	  int save_gr;
-
-	  ch = Agetchar();
-	  if (ch == EOF) return ch;
-	  if (ch == 27) ch = Agetchar() + 0x100; /* ESC x */
-	  if (ch == 0x100 + '$') ch = Agetchar() + 0x200; /* ESC $ x */
-	  switch (ch) {
-		case 14: /* invoke G1 into GL */
-		  gl = 1;
-		  return iso2022();
-		case 15: /* invoke G0 into GL */
-		  gl = 0;
-		  return iso2022();
-		case 142: case 'N' + 0x100: /* invoke G2 into GL for next char */
-		  save_gl = gl; save_gr = gr;
-		  gl = gr = 2;
-		  ch = iso2022();
-		  gl = save_gl; gr = save_gr;
-		  return ch;
-		case 143: case 'O' + 0x100: /* invoke G3 into GL for next char */
-		  save_gl = gl; save_gr = gr;
-		  gl = gr = 3;
-		  ch = iso2022();
-		  gl = save_gl; gr = save_gr;
-		  return ch;
-		case 'n' + 0x100: /* invoke G2 into GL */
-		  gl = 2;
-		  return iso2022();
-		case 'o' + 0x100: /* invoke G3 into GL */
-		  gl = 3;
-		  return iso2022();
-		case '~' + 0x100: /* invoke G1 into GR */
-		  gr = 1;
-		  return iso2022();
-		case '}' + 0x100: /* invoke G2 into GR */
-		  gr = 2;
-		  return iso2022();
-		case '|' + 0x100: /* invoke G3 into GR */
-		  gr = 3;
-		  return iso2022();
-		case '(' + 0x100: /* set G0 to 94-char set */
-		  ch = Agetchar();
-		  if (ch == 'B') ch = 0; /* ASCII */
-		  gn[0] = ch << 16;
-		  gndbl[0] = 0;
-		  return iso2022();
-		case ')' + 0x100: /* set G1 to 94-char set */
-		  ch = Agetchar();
-		  if (ch == 'B') ch = 0;
-		  gn[1] = ch << 16;
-		  gndbl[1] = 0;
-		  return iso2022();
-		case '*' + 0x100: /* set G2 to 94-char set */
-		  ch = Agetchar();
-		  if (ch == 'B') ch = 0;
-		  gn[2] = ch << 16;
-		  gndbl[2] = 0;
-		  return iso2022();
-		case '+' + 0x100: /* set G3 to 94-char set */
-		  ch = Agetchar();
-		  if (ch == 'B') ch = 0;
-		  gn[3] = ch << 16;
-		  gndbl[3] = 0;
-		  return iso2022();
-		case '-' + 0x100: /* set G1 to 96-char set */
-		  ch = Agetchar();
-		  if (ch == 'A') ch = 0; /* Latin-1 top half */
-		  gn[1] = (ch << 16) | 0x80;
-		  gndbl[1] = 0;
-		  return iso2022();
-		case '.' + 0x100: /* set G2 to 96-char set */
-		  ch = Agetchar();
-		  if (ch == 'A') ch = 0;
-		  gn[2] = (ch << 16) | 0x80;
-		  gndbl[2] = 0;
-		  return iso2022();
-		case '/' + 0x100: /* set G3 to 96-char set */
-		  ch = Agetchar();
-		  if (ch == 'A') ch = 0;
-		  gn[3] = (ch << 16) | 0x80;
-		  gndbl[3] = 0;
-		  return iso2022();
-		case '(' + 0x200: /* set G0 to 94 x 94 char set */
-		  ch = Agetchar();
-		  gn[0] = ch << 16;
-		  gndbl[0] = 1;
-		  return iso2022();
-		case ')' + 0x200: /* set G1 to 94 x 94 char set */
-		  ch = Agetchar();
-		  gn[1] = ch << 16;
-		  gndbl[1] = 1;
-		  return iso2022();
-		case '*' + 0x200: /* set G2 to 94 x 94 char set */
-		  ch = Agetchar();
-		  gn[2] = ch << 16;
-		  gndbl[2] = 1;
-		  return iso2022();
-		case '+' + 0x200: /* set G3 to 94 x 94 char set */
-		  ch = Agetchar();
-		  gn[3] = ch << 16;
-		  gndbl[3] = 1;
-		  return iso2022();
-		default:
-		  if (ch & 0x200) { /* set G0 to 94 x 94 char set (deprecated) */
-			gn[0] = (ch & ~0x200) << 16;
-			gndbl[0] = 1;
-			return iso2022();
-			}
-		  }
-
-	  if (ch >= 0x21 && ch <= 0x7E) { /* process GL */
-		if (gndbl[gl]) {
-		  ch2 = Agetchar();
-		  return gn[gl] | (ch << 8) | ch2;
-		  }
-		else return gn[gl] | ch;
-		}
-	  else if (ch >= 0xA0 && ch <= 0xFF) { /* process GR */
-		if (gndbl[gr]) {
-		  ch2 = Agetchar();
-		  return gn[gr] | (ch << 8) | ch2;
-		  }
-		else return gn[gr] | (ch & ~0x80);
-		}
-	  else return ch;
-	  }
-
-	/****************************************************************************
-
-	  ungetinchr
-
-	  Called by main.  Pushes back an "inchr" to be read by getinchr
-	  on the next call.
-
-	******************************************************************************/
-	inchr getinchr_buffer;
-	int getinchr_flag;
-
-	inchr ungetinchr(c)
-	inchr c;
-	{
-	  getinchr_buffer = c;
-	  getinchr_flag = 1;
-	  return c;
-	}
-
-	/*****************************************************************************
-
-	  getinchr
-
-	  Called by main.  Processes multibyte characters.  Invokes Agetchar.
-	  If multibyte = 0, ISO 2022 mode (see iso2022 routine).
-	  If multibyte = 1,  double-byte mode (0x00-0x7f bytes are characters,
-		0x80-0xFF bytes are first byte of a double-byte character).
-	  If multibyte = 2, Unicode UTF-8 mode (0x00-0x7F bytes are characters,
-		0x80-0xBF bytes are nonfirst byte of a multibyte character,
-		0xC0-0xFD bytes are first byte of a multibyte character,
-		0xFE-0xFF bytes are errors (all errors return code 0x0080)).
-	  If multibyte = 3, HZ mode ("~{" starts double-byte mode, "}~" ends it,
-		"~~" is a tilde, "~x" for all other x is ignored).
-	  If multibyte = 4, Shift-JIS mode (0x80-0x9F and 0xE0-0xEF are first byte
-		of a double-byte character, all other bytes are characters).
-	 
-
-	*****************************************************************************/
-
-	inchr getinchr()
-	{
-	  int ch, ch2, ch3, ch4, ch5, ch6;
-
-	  if (getinchr_flag) {
-		getinchr_flag = 0;
-		return getinchr_buffer;
-		}
-
-	  switch(multibyte) {
-	   case 0: /* single-byte */
-		  return iso2022();
-	   case 1: /* DBCS */
-		 ch = Agetchar();
-		 if ((ch >= 0x80 && ch <= 0x9F) ||
-			 (ch >= 0xE0 && ch <= 0xEF)) {
-		   ch = (ch << 8) + Agetchar();
-		   }
-		 return ch;
-	   case 2: /* UTF-8 */
-		  ch = Agetchar();
-		  if (ch < 0x80) return ch;  /* handles EOF, too */
-		  if (ch < 0xC0 || ch > 0xFD)
-			return 0x0080;  /* illegal first character */
-		  ch2 = Agetchar() & 0x3F;
-		  if (ch < 0xE0) return ((ch & 0x1F) << 6) + ch2;
-		  ch3 = Agetchar() & 0x3F;
-		  if (ch < 0xF0)
-			return ((ch & 0x0F) << 12) + (ch2 << 6) + ch3;
-		  ch4 = Agetchar() & 0x3F;
-		  if (ch < 0xF8)
-			return ((ch & 0x07) << 18) + (ch2 << 12) + (ch3 << 6) + ch4;
-		  ch5 = Agetchar() & 0x3F;
-		  if (ch < 0xFC)
-			return ((ch & 0x03) << 24) + (ch2 << 18) + (ch3 << 12) +
-			  (ch4 << 6) + ch5;
-		  ch6 = Agetchar() & 0x3F;
-		  return ((ch & 0x01) << 30) + (ch2 << 24) + (ch3 << 18) +
-			(ch4 << 12) + (ch5 << 6) + ch6;
-	   case 3: /* HZ */
-		 ch = Agetchar();
-		 if (ch == EOF) return ch;
-		 if (hzmode) {
-		   ch = (ch << 8) + Agetchar();
-		   if (ch == ('}' << 8) + '~') {
-			 hzmode = 0;
-			 return getinchr();
-			 }
-		   return ch;
-		   }
-		 else if (ch == '~') {
-		   ch = Agetchar();
-		   if (ch == '{') {
-			  hzmode = 1;
-			  return getinchr();
-			  }
-		  else if (ch == '~') {
-			return ch;
-			}
-		  else {
-			return getinchr();
-			}
-		  }
-		 else return ch;
-	   case 4: /* Shift-JIS */
-		 ch = Agetchar();
-		 if ((ch >= 0x80 && ch <= 0x9F) ||
-			 (ch >= 0xE0 && ch <= 0xEF)) {
-		   ch = (ch << 8) + Agetchar();
-		   }
-		 return ch;
-	   default:
-		 return 0x80;
-		}
-	  }
-
-	void fig_init(argc, argv)
-	int argc;
-	char** argv;
-	{
-	  Myargc = argc;
-	  Myargv = argv;
-
-	  if ((myname = strrchr(Myargv[0],DIRSEP))!=NULL) {
-		myname++;
-		}
-	  else {
-		myname = Myargv[0];
-		}
-	  fontdirname = DEFAULTFONTDIR;
-	  fontname = DEFAULTFONTFILE;
-	  cfilelist = NULL;
-	  cfilelistend = &cfilelist;
-	  commandlist = NULL;
-	  commandlistend = &commandlist;
-	  smushoverride = SMO_NO;
-	  deutschflag = 0;
-	  justification = -1;
-	  right2left = -1;
-	  paragraphflag = 0;
-	  cmdinput = 0;
-	  outputwidth = DEFAULTCOLUMNS;
-	  gn[1] = 0x80;
-	  gr = 1;
-	  outlinelenlimit = outputwidth-1;
-	}
-
-	void f(c)
-	const inchr c;
-	{
-	  int i;
-	  int char_not_added;
-	  static int wordbreakmode = 0;
-
-		do {
-		  char_not_added = 0;
-
-		  if (wordbreakmode== -1) {
-			if (c==' ') {
-			  break;
-			  }
-			else if (c=='\n') {
-			  wordbreakmode = 0;
-			  break;
-			  }
-			wordbreakmode = 0;
-			}
-
-		  if (c=='\n') {
-			printline();
-			wordbreakmode = 0;
-			}
-
-		  else if (addchar(c)) {
-			if (c!=' ') {
-			  wordbreakmode = (wordbreakmode>=2)?3:1;
-			  }
-			else {
-			  wordbreakmode = (wordbreakmode>0)?2:0;
-			  }
-			}
-
-		  else if (outlinelen==0) {
-        for (i=0;i<charheight;i++) {
-          if (right2left && outputwidth>1) {
-            putstring(currchar[i]+STRLEN(currchar[i])-outlinelenlimit);
-            }
-          else {
-            putstring(currchar[i]);
-            }
-          }
-        wordbreakmode = -1;
-        }
-
-      else if (c==' ') {
-        if (wordbreakmode==2) {
-          splitline();
-          }
-        else {
-          printline();
-          }
-        wordbreakmode = -1;
-        }
-
-      else {
-        if (wordbreakmode>=2) {
-          splitline();
-          }
-        else {
-          printline();
-          }
-        wordbreakmode = (wordbreakmode==3)?1:0;
-        char_not_added = 1;
-        }
-
-      } while (char_not_added);
 }
 
-void fs(string)
+
+/****************************************************************************
+
+  hasdirsep
+
+  Returns true if s1 contains a DIRSEP or DIRSEP2 character.
+
+****************************************************************************/
+
+int hasdirsep(s1)
+char *s1;
+{
+  if (strchr(s1, DIRSEP)) return 1;
+  else if (strchr(s1, DIRSEP2)) return 1;
+  else return 0;
+}
+
+/****************************************************************************
+
+  suffixcmp
+
+  Returns true if s2 is a suffix of s1; uses case-blind comparison.
+
+****************************************************************************/
+
+int suffixcmp(s1, s2)
+char *s1;
+char *s2;
+{
+  int len1, len2;
+
+  len1 = MYSTRLEN(s1);
+  len2 = MYSTRLEN(s2);
+  if (len2 > len1) return 0;
+  s1 += len1 - len2;
+  while (*s1) {
+	if (tolower(*s1) != tolower(*s2)) return 0;
+	s1++;
+	s2++;
+	}
+  return 1;
+}
+   
+/****************************************************************************
+
+  skiptoeol
+
+  Skips to the end of a line, given a stream.  Handles \r, \n, or \r\n.
+
+****************************************************************************/
+
+void skiptoeol(fp)
+ZFILE *fp;
+{
+  int dummy;
+
+  while (dummy=Zgetc(fp),dummy!=EOF) {
+	if (dummy == '\n') return;
+	if (dummy == '\r') {
+	  dummy = Zgetc(fp);
+	  if (dummy != EOF && dummy != '\n') Zungetc(dummy,fp);
+	  return;
+	  }
+  }
+}
+
+
+/****************************************************************************
+
+  myfgets
+
+  Local version of fgets.  Handles \r, \n, and \r\n terminators.
+
+****************************************************************************/
+
+char *myfgets(line,maxlen,fp)
+char *line;
+int maxlen;
+ZFILE *fp;
+{
+  int c = 0;
+  char *p;
+
+  p = line;
+  while((c=Zgetc(fp))!=EOF&&maxlen) {
+	*p++ = c;
+	maxlen--;
+	if (c=='\n') break;
+	if (c=='\r') {
+	  c = Zgetc(fp);
+	  if (c != EOF && c != '\n') Zungetc(c,fp);
+	  *(p-1) = '\n';
+	  break;
+	  }
+	}
+  *p = 0;
+  return (c==EOF) ? NULL : line;
+}
+
+
+/****************************************************************************
+
+  usageerr
+
+  Prints "Usage: ...." line to the given stream.
+
+****************************************************************************/
+
+void printusage(out)
+FILE *out;
+{
+  fprintf(out,
+	"Usage: %s [ -cklnoprstvxDELNRSWX ] [ -d fontdirectory ]\n",
+	"              [ -f fontfile ] [ -m smushmode ] [ -w outputwidth ]\n"
+	"              [ -C controlfile ] [ -I infocode ] [ message ]\n",
+	myname);
+}
+
+
+/****************************************************************************
+
+  printinfo
+
+  Prints version and copyright message, or utility information.
+
+****************************************************************************/
+
+void printinfo(infonum)
+int infonum;
+{
+  switch (infonum) {
+	case 0: /* Copyright message */
+	  printf("FIGlet Copyright (C) 1991-2012 Glenn Chappell, Ian Chai, "
+			 "John Cowan,\nChristiaan Keet and Claudio Matsuoka\n"
+			 "Internet: <info@figlet.org> "
+			 "Version: %s, date: %s\n\n"
+			 "FIGlet, along with the various FIGlet fonts"
+			 " and documentation, may be\n"
+			 "freely copied and distributed.\n\n"
+			 "If you use FIGlet, please send an"
+			 " e-mail message to <info@figlet.org>.\n\n"
+			 "The latest version of FIGlet is available from the"
+			 " web site,\n\thttp://www.figlet.org/\n\n",
+	   VERSION,DATE);
+	  printusage(stdout);
+	  break;
+	case 1: /* Version (integer) */
+	  printf("%d\n",VERSION_INT);
+	  break;
+	case 2: /* Font directory */
+	  printf("%s\n",fontdirname);
+	  break;
+	case 3: /* Font */
+	  printf("%s\n",fontname);
+	  break;
+	case 4: /* Outputwidth */
+	  printf("%d\n",outputwidth);
+	  break;
+	case 5: /* Font formats */
+	  printf("%s", FONTFILEMAGICNUMBER);
+#ifdef TLF_FONTS
+	  printf(" %s", TOILETFILEMAGICNUMBER);
+#endif
+	  printf("\n");
+	}
+}
+
+
+/****************************************************************************
+
+  readmagic
+
+  Reads a four-character magic string from a stream.
+
+****************************************************************************/
+void readmagic(fp,magic)
+ZFILE *fp;
+char *magic;
+{
+  int i;
+
+  for (i=0;i<4;i++) {
+	magic[i] = Zgetc(fp);
+	}
+  magic[4] = 0;
+  }
+  
+/****************************************************************************
+
+  skipws
+
+  Skips whitespace characters from a stream.
+
+****************************************************************************/
+void skipws(fp)
+ZFILE *fp;
+{
+  int c;
+  while (c=Zgetc(fp),isascii(c)&&isspace(c)) ;
+  Zungetc(c,fp);
+  }
+
+/****************************************************************************
+
+  readnum
+
+  Reads a number from a stream.  Accepts "0" prefix for octal and
+  "0x" or "0X" for hexadecimal.  Ignores leading whitespace.
+
+****************************************************************************/
+void readnum(fp,nump)
+ZFILE *fp;
+inchr *nump;
+{
+  int acc = 0;
+  char *p;
+  int c;
+  int base;
+  int sign = 1;
+  char digits[] = "0123456789ABCDEF";
+
+  skipws(fp);
+  c = Zgetc(fp);
+  if (c=='-') {
+	sign = -1;
+	}
+  else {
+	Zungetc(c,fp);
+	}
+  c = Zgetc(fp);
+  if (c=='0') {
+	 c = Zgetc(fp);
+	 if (c=='x'||c=='X') {
+	   base = 16;
+	   }
+	 else {
+	   base = 8;
+	   Zungetc(c,fp);
+	   }
+	}
+  else {
+	base = 10;
+	Zungetc(c,fp);
+	}
+
+  while((c=Zgetc(fp))!=EOF) {
+	c=toupper(c);
+	p=strchr(digits,c);
+	if (!p) {
+	  Zungetc(c,fp);
+	  *nump = acc * sign;
+	  return;
+	  }
+	acc = acc*base+(p-digits);
+	}
+  *nump = acc * sign;
+  }  
+
+/****************************************************************************
+
+  readTchar
+
+  Reads a control file "T" command character specification.
+
+  Character is a single byte, an escape sequence, or
+  an escaped numeric.
+
+****************************************************************************/
+
+inchr readTchar(fp)
+ZFILE *fp;
+{
+  inchr thechar;
+  char next;
+
+  thechar=Zgetc(fp);
+  if (thechar=='\n' || thechar=='\r') { /* Handle badly-formatted file */
+	Zungetc(thechar,fp);
+	return '\0';
+	}
+  if (thechar!='\\') return thechar;
+  next=Zgetc(fp);
+  switch(next) {
+	case 'a':
+	  return 7;
+	case 'b':
+	  return 8;
+	case 'e':
+	  return 27;
+	case 'f':
+	  return 12;
+	case 'n':
+	  return 10;
+	case 'r':
+	  return 13;
+	case 't':
+	  return 9;
+	case 'v':
+	  return 11;
+	default:
+	  if (next=='-' || next=='x' || (next>='0' && next<='9')) {
+		Zungetc(next,fp);
+		readnum(fp,&thechar);
+		return thechar;
+		}
+	  return next;
+	}
+}
+
+/****************************************************************************
+
+  charsetname
+
+  Get a Tchar representing a charset name, or 0 if none available.
+  Called in getcharset().
+
+****************************************************************************/
+
+inchr charsetname(fp)
+ZFILE *fp;
+{
+  inchr result;
+
+  result = readTchar(fp);
+  if (result == '\n' || result == '\r') {
+	result = 0;
+	Zungetc(result,fp);
+	}
+  return result;
+  }
+
+/****************************************************************************
+
+  charset
+
+  Processes "g[0123]" character set specifier
+  Called in readcontrol().
+
+****************************************************************************/
+
+void charset(n, controlfile)
+int n;
+ZFILE *controlfile;
+{
+  int ch;
+
+  skipws(controlfile);
+  if (Zgetc(controlfile) != '9') {
+	skiptoeol(controlfile);
+	return;
+	}
+  ch = Zgetc(controlfile);
+  if (ch == '6') {
+	 gn[n] = 65536L * charsetname(controlfile) + 0x80;
+	 gndbl[n] = 0;
+	 skiptoeol(controlfile);
+	 return;
+	 }
+  if (ch != '4') {
+	skiptoeol(controlfile);
+	return;
+	}
+  ch = Zgetc(controlfile);
+  if (ch == 'x') {
+	 if (Zgetc(controlfile) != '9') {
+	   skiptoeol(controlfile);
+	   return;
+	   }
+	 if (Zgetc(controlfile) != '4') {
+	   skiptoeol(controlfile);
+	   return;
+	   }
+	 skipws(controlfile);
+	 gn[n] = 65536L * charsetname(controlfile);
+	 gndbl[n] = 1;
+	 skiptoeol(controlfile);
+	 return;
+	 }
+  Zungetc(ch, controlfile);
+  skipws(controlfile);
+  gn[n] = 65536L * charsetname(controlfile);
+  gndbl[n] = 0;
+  return;
+  }
+
+/****************************************************************************
+
+  FIGopen
+
+  Given a FIGlet font or control file name and suffix, return the file
+  or NULL if not found
+
+****************************************************************************/
+
+ZFILE *FIGopen(name,suffix)
+char *name;
+char *suffix;
+{
+  char *fontpath;
+  ZFILE *fontfile;
+  struct stat st;
+  int namelen;
+
+  namelen = MYSTRLEN(fontdirname);
+  fontpath = (char*)alloca(sizeof(char)*
+	(namelen+MYSTRLEN(name)+MYSTRLEN(suffix)+2));
+  fontfile = NULL;
+  if (!hasdirsep(name)) {  /* not a full path name */
+	strcpy(fontpath,fontdirname);
+	fontpath[namelen] = DIRSEP;
+	fontpath[namelen+1] = '\0';
+	strcat(fontpath,name);
+	strcat(fontpath,suffix);
+	if(stat(fontpath,&st)==0) goto ok;
+	}
+  /* just append suffix */
+  strcpy(fontpath,name);
+  strcat(fontpath,suffix);
+  if(stat(fontpath,&st)==0) goto ok;
+
+  return NULL;
+
+ok:
+  fontfile = Zopen(fontpath,"rb");
+  return fontfile;
+}
+
+/****************************************************************************
+
+  readcontrol
+
+  Allocates memory and reads in the given control file.
+  Called in readcontrolfiles().
+
+****************************************************************************/
+
+void readcontrol(controlname)
+char *controlname;
+{
+  inchr firstch,lastch;
+  char dashcheck;
+  inchr offset;
+  int command;
+  ZFILE *controlfile;
+
+  controlfile = FIGopen(controlname,CONTROLFILESUFFIX);
+
+  if (controlfile==NULL) {
+	fprintf(stderr,"%s: %s: Unable to open control file\n",myname,
+	  controlname);
+	exit(1);
+	}
+
+  (*commandlistend) = (comnode*)myalloc(sizeof(comnode));
+  (*commandlistend)->thecommand = 0; /* Begin with a freeze command */
+  commandlistend = &(*commandlistend)->next;
+  (*commandlistend) = NULL;
+
+  while(command=Zgetc(controlfile),command!=EOF) {
+	switch (command) {
+	  case 't': /* Translate */
+		skipws(controlfile);
+		firstch=readTchar(controlfile);
+		if ((dashcheck=Zgetc(controlfile))=='-') {
+		  lastch=readTchar(controlfile);
+		  }
+		else {
+		  Zungetc(dashcheck,controlfile);
+		  lastch=firstch;
+		  }
+		skipws(controlfile);
+		offset=readTchar(controlfile)-firstch;
+		skiptoeol(controlfile);
+		(*commandlistend) = (comnode*)myalloc(sizeof(comnode));
+		(*commandlistend)->thecommand = 1;
+		(*commandlistend)->rangelo = firstch;
+		(*commandlistend)->rangehi = lastch;
+		(*commandlistend)->offset = offset;
+		commandlistend = &(*commandlistend)->next;
+		(*commandlistend) = NULL;
+		break;
+	  case '0': case '1': case '2': case '3': case '4':
+	  case '5': case '6': case '7': case '8': case '9':
+	  case '-':
+				/* Mapping table entry */
+		Zungetc(command,controlfile);
+		readnum(controlfile,&firstch);
+		skipws(controlfile);
+	readnum(controlfile,&lastch);
+	offset=lastch-firstch;
+		lastch=firstch;
+		skiptoeol(controlfile);
+		(*commandlistend) = (comnode*)myalloc(sizeof(comnode));
+		(*commandlistend)->thecommand = 1;
+		(*commandlistend)->rangelo = firstch;
+		(*commandlistend)->rangehi = lastch;
+		(*commandlistend)->offset = offset;
+		commandlistend = &(*commandlistend)->next;
+		(*commandlistend) = NULL;
+		break;
+	  case 'f': /* freeze */
+		skiptoeol(controlfile);
+		(*commandlistend) = (comnode*)myalloc(sizeof(comnode));
+		(*commandlistend)->thecommand = 0;
+		commandlistend = &(*commandlistend)->next;
+		(*commandlistend) = NULL;
+		break;
+	  case 'b': /* DBCS input mode */
+		multibyte = 1;
+		break;
+	  case 'u': /* UTF-8 input mode */
+		multibyte = 2;
+		break;
+	  case 'h': /* HZ input mode */
+		multibyte = 3;
+		break;
+	  case 'j': /* Shift-JIS input mode */
+		multibyte = 4;
+		break;
+	  case 'g': /* ISO 2022 character set choices */
+		multibyte = 0;
+		skipws(controlfile);
+		command=Zgetc(controlfile);
+		switch (command) {
+		  case '0': /* define G0 charset */
+			charset(0, controlfile);
+			break;
+		  case '1': /* set G1 charset */
+			charset(1, controlfile);
+			break;
+		  case '2': /* set G2 charset */
+			charset(2, controlfile);
+			break;
+		  case '3': /* set G3 charset */
+			charset(3, controlfile);
+			break;
+		  case 'l': case 'L': /* define left half */
+			skipws(controlfile);
+			gl = Zgetc(controlfile) - '0';
+			skiptoeol(controlfile);
+			break;
+		  case 'r': case 'R': /* define right half */
+			skipws(controlfile);
+			gr = Zgetc(controlfile) - '0';
+			skiptoeol(controlfile);
+			break;
+		  default: /* meaningless "g" command */
+			skiptoeol(controlfile);
+		  }
+	  case '\r': case '\n': /* blank line */
+		break;
+	  default: /* Includes '#' */
+		skiptoeol(controlfile);
+	  }
+	}
+  Zclose(controlfile);
+}
+
+
+/****************************************************************************
+
+  readcontrolfiles
+
+  Reads in the controlfiles names in cfilelist.  Uses readcontrol.
+  Called in main().
+
+****************************************************************************/
+
+void readcontrolfiles()
+{
+  cfnamenode *cfnptr;
+
+  for (cfnptr=cfilelist;cfnptr!=NULL;cfnptr=cfnptr->next) {
+	readcontrol(cfnptr->thename);
+	}
+}
+
+
+/****************************************************************************
+
+  clearcfilelist
+
+  Clears the control file list.  Assumes thename does not need freeing.
+
+****************************************************************************/
+
+void clearcfilelist()
+{
+  cfnamenode *cfnptr1,*cfnptr2;
+
+  cfnptr1 = cfilelist;
+  while (cfnptr1 != NULL) {
+	cfnptr2 = cfnptr1->next;
+	free(cfnptr1);
+	cfnptr1 = cfnptr2;
+	}
+  cfilelist = NULL;
+  cfilelistend = &cfilelist;
+}
+
+
+/****************************************************************************
+
+  clearline
+
+  Clears both the input (inchrline) and output (outputline) storage.
+
+****************************************************************************/
+
+void clearline()
+{
+  int i;
+
+  for (i=0;i<charheight;i++) {
+	outputline[i][0] = '\0';
+	}
+  outlinelen = 0;
+  inchrlinelen = 0;
+}
+
+
+/****************************************************************************
+
+  readfontchar
+
+  Reads a font character from the font file, and places it in a
+  newly-allocated entry in the list.
+
+****************************************************************************/
+
+void readfontchar(file,theord)
+ZFILE *file;
+inchr theord;
+{
+  int row,k;
+  char templine[MAXLEN+1];
+  outchr endchar, outline[MAXLEN+1];
+  fcharnode *fclsave;
+
+  fclsave = fcharlist;
+  fcharlist = (fcharnode*)myalloc(sizeof(fcharnode));
+  fcharlist->ord = theord;
+  fcharlist->thechar = (outchr**)myalloc(sizeof(outchr*)*charheight);
+  fcharlist->next = fclsave;
+
+  outline[0] = 0;
+
+  for (row=0;row<charheight;row++) {
+	if (myfgets(templine,MAXLEN,file)==NULL) {
+	  templine[0] = '\0';
+	  }
+#ifdef TLF_FONTS
+	utf8_to_wchar(templine,MAXLEN,outline,MAXLEN,0);
+#else
+	strcpy(outline,templine);
+#endif
+	k = STRLEN(outline)-1;
+	while (k>=0 && ISSPACE(outline[k])) {  /* remove trailing spaces */
+	  k--;
+	  }
+	if (k>=0) {
+	  endchar = outline[k];  /* remove endmarks */
+	  while (k>=0 && outline[k]==endchar) {
+		k--;
+		}
+	  }
+	outline[k+1] = '\0';
+	fcharlist->thechar[row] = (outchr*)myalloc(sizeof(outchr)*(STRLEN(outline)+1));
+	STRCPY(fcharlist->thechar[row],outline);
+	}
+}
+
+
+/****************************************************************************
+
+  readfont
+
+  Allocates memory, initializes variables, and reads in the font.
+  Called near beginning of main().
+
+****************************************************************************/
+
+void readfont()
+{
+  int i,row,numsread;
+  inchr theord;
+  int maxlen,cmtlines,ffright2left;
+  int smush,smush2;
+  char fileline[MAXLEN+1],magicnum[5];
+  ZFILE *fontfile;
+
+  fontfile = FIGopen(fontname,FONTFILESUFFIX);
+#ifdef TLF_FONTS
+  if (fontfile==NULL) {
+	fontfile = FIGopen(fontname,TOILETFILESUFFIX);
+	if(fontfile) toiletfont = 1;
+	}
+#endif
+
+  if (fontfile==NULL) {
+	fprintf(stderr,"%s: %s: Unable to open font file\n",myname,fontname);
+	exit(1);
+	}
+
+  readmagic(fontfile,magicnum);
+  if (myfgets(fileline,MAXLEN,fontfile)==NULL) {
+	fileline[0] = '\0';
+	}
+  if (MYSTRLEN(fileline)>0 ? fileline[MYSTRLEN(fileline)-1]!='\n' : 0) {
+	skiptoeol(fontfile);
+	}
+  numsread = sscanf(fileline,"%*c%c %d %*d %d %d %d %d %d",
+	&hardblank,&charheight,&maxlen,&smush,&cmtlines,
+	&ffright2left,&smush2);
+
+  if (maxlen > MAXLEN) {
+	fprintf(stderr,"%s: %s: character is too wide\n",myname,fontname);
+	exit(1);
+	}
+#ifdef TLF_FONTS
+  if ((!toiletfont && strcmp(magicnum,FONTFILEMAGICNUMBER)) ||
+	  (toiletfont && strcmp(magicnum,TOILETFILEMAGICNUMBER)) || numsread<5) {
+#else
+  if (strcmp(magicnum,FONTFILEMAGICNUMBER) || numsread<5) {
+#endif
+	fprintf(stderr,"%s: %s: Not a FIGlet 2 font file\n",myname,fontname);
+	exit(1);
+	}
+  for (i=1;i<=cmtlines;i++) {
+	skiptoeol(fontfile);
+	}
+
+  if (numsread<6) {
+	ffright2left = 0;
+	}
+
+  if (numsread<7) { /* if no smush2, decode smush into smush2 */
+	if (smush == 0) smush2 = SM_KERN;
+	else if (smush < 0) smush2 = 0;
+	else smush2 = (smush & 31) | SM_SMUSH;
+	}
+
+  if (charheight<1) {
+	charheight = 1;
+	}
+
+  if (maxlen<1) {
+	maxlen = 1;
+	}
+
+  maxlen += 100; /* Give ourselves some extra room */
+
+  if (smushoverride == SMO_NO)
+	 smushmode = smush2;
+  else if (smushoverride == SMO_FORCE)
+	 smushmode |= smush2;
+
+  if (right2left<0) {
+	right2left = ffright2left;
+	}
+
+  if (justification<0) {
+	justification = 2*right2left;
+	}
+
+  /* Allocate "missing" character */
+  fcharlist = (fcharnode*)myalloc(sizeof(fcharnode));
+  fcharlist->ord = 0;
+  fcharlist->thechar = (outchr**)myalloc(sizeof(outchr*)*charheight);
+  fcharlist->next = NULL;
+  for (row=0;row<charheight;row++) {
+	fcharlist->thechar[row] = (outchr*)myalloc(sizeof(outchr));
+	fcharlist->thechar[row][0] = '\0';
+	}
+  for (theord=' ';theord<='~';theord++) {
+	readfontchar(fontfile,theord);
+	}
+  for (theord=0;theord<=6;theord++) {
+	readfontchar(fontfile,deutsch[theord]);
+	}
+  while (myfgets(fileline,maxlen+1,fontfile)==NULL?0:
+	sscanf(fileline,"%li",&theord)==1) {
+	readfontchar(fontfile,theord);
+	}
+  Zclose(fontfile);
+}
+
+
+/****************************************************************************
+
+  linealloc
+
+  Allocates & clears outputline, inchrline. Sets inchrlinelenlimit.
+  Called near beginning of main().
+
+****************************************************************************/
+
+void linealloc()
+{
+  int row; 
+
+  outputline = (outchr**)myalloc(sizeof(outchr*)*charheight);
+  for (row=0;row<charheight;row++) {
+	outputline[row] = (outchr*)myalloc(sizeof(outchr)*(outlinelenlimit+1));
+	}
+  inchrlinelenlimit = outputwidth*4+100;
+  inchrline = (inchr*)myalloc(sizeof(inchr)*(inchrlinelenlimit+1));
+  clearline();
+}
+
+
+/****************************************************************************
+
+  getletter
+
+  Sets currchar to point to the font entry for the given character.
+  Sets currcharwidth to the width of this character.
+
+****************************************************************************/
+
+void getletter(c)
+inchr c;
+{
+  fcharnode *charptr;
+
+  for (charptr=fcharlist;charptr==NULL?0:charptr->ord!=c;
+	charptr=charptr->next) ;
+  if (charptr!=NULL) {
+	currchar = charptr->thechar;
+	}
+  else {
+	for (charptr=fcharlist;charptr==NULL?0:charptr->ord!=0;
+	  charptr=charptr->next) ;
+	currchar = charptr->thechar;
+	}
+  previouscharwidth = currcharwidth;
+  currcharwidth = STRLEN(currchar[0]);
+}
+
+
+/****************************************************************************
+
+  smushem
+
+  Given 2 characters, attempts to smush them into 1, according to
+  smushmode.  Returns smushed character or '\0' if no smushing can be
+  done.
+
+  smushmode values are sum of following (all values smush blanks):
+	1: Smush equal chars (not hardblanks)
+	2: Smush '_' with any char in hierarchy below
+	4: hierarchy: "|", "/\", "[]", "{}", "()", "<>"
+	   Each class in hier. can be replaced by later class.
+	8: [ + ] -> |, { + } -> |, ( + ) -> |
+   16: / + \ -> X, > + < -> X (only in that order)
+   32: hardblank + hardblank -> hardblank
+
+****************************************************************************/
+
+outchr smushem(lch,rch)
+outchr lch,rch;
+{
+  if (lch==' ') return rch;
+  if (rch==' ') return lch;
+
+  if (previouscharwidth<2 || currcharwidth<2) return '\0';
+	/* Disallows overlapping if the previous character */
+	/* or the current character has a width of 1 or zero. */
+
+  if ((smushmode & SM_SMUSH) == 0) return '\0';  /* kerning */
+
+  if ((smushmode & 63) == 0) {
+	/* This is smushing by universal overlapping. */
+	/* Unreachable code: lch==' ' or rch==' ' already handled!
+	if (lch==' ') return rch;
+	if (rch==' ') return lch;
+	*/
+
+	if (lch==hardblank) return rch;
+	if (rch==hardblank) return lch;
+	  /* Above four lines ensure overlapping preference to */
+	  /* visible characters. */
+	if (right2left==1) return lch;
+	  /* Above line ensures that the dominant (foreground) */
+	  /* fig-character for overlapping is the latter in the */
+	  /* user's text, not necessarily the rightmost character. */
+	return rch;
+	  /* Occurs in the absence of above exceptions. */
+	}
+  
+  if (smushmode & SM_HARDBLANK) {
+	if (lch==hardblank && rch==hardblank) return lch;
+	}
+
+  if (lch==hardblank || rch==hardblank) return '\0';
+
+  if (smushmode & SM_EQUAL) {
+	if (lch==rch) return lch;
+	}
+
+  if (smushmode & SM_LOWLINE) {
+	if (lch=='_' && strchr("|/\\[]{}()<>",rch)) return rch;
+	if (rch=='_' && strchr("|/\\[]{}()<>",lch)) return lch;
+	}
+
+  if (smushmode & SM_HIERARCHY) {
+	if (lch=='|' && strchr("/\\[]{}()<>",rch)) return rch;
+	if (rch=='|' && strchr("/\\[]{}()<>",lch)) return lch;
+	if (strchr("/\\",lch) && strchr("[]{}()<>",rch)) return rch;
+	if (strchr("/\\",rch) && strchr("[]{}()<>",lch)) return lch;
+	if (strchr("[]",lch) && strchr("{}()<>",rch)) return rch;
+	if (strchr("[]",rch) && strchr("{}()<>",lch)) return lch;
+	if (strchr("{}",lch) && strchr("()<>",rch)) return rch;
+	if (strchr("{}",rch) && strchr("()<>",lch)) return lch;
+	if (strchr("()",lch) && strchr("<>",rch)) return rch;
+	if (strchr("()",rch) && strchr("<>",lch)) return lch;
+	}
+
+  if (smushmode & SM_PAIR) {
+	if (lch=='[' && rch==']') return '|';
+	if (rch=='[' && lch==']') return '|';
+	if (lch=='{' && rch=='}') return '|';
+	if (rch=='{' && lch=='}') return '|';
+	if (lch=='(' && rch==')') return '|';
+	if (rch=='(' && lch==')') return '|';
+	}
+
+  if (smushmode & SM_BIGX) {
+	if (lch=='/' && rch=='\\') return '|';
+	if (rch=='/' && lch=='\\') return 'Y';
+	if (lch=='>' && rch=='<') return 'X';
+	  /* Don't want the reverse of above to give 'X'. */
+	}
+
+  return '\0';
+}
+
+
+/****************************************************************************
+
+  smushamt
+
+  Returns the maximum amount that the current character can be smushed
+  into the current line.
+
+****************************************************************************/
+
+int smushamt()
+{
+  int maxsmush,amt;
+  int row,linebd,charbd;
+  outchr ch1,ch2;
+
+  if ((smushmode & (SM_SMUSH | SM_KERN)) == 0) {
+	return 0;
+	}
+  maxsmush = currcharwidth;
+  for (row=0;row<charheight;row++) {
+	if (right2left) {
+	  if (maxsmush>STRLEN(outputline[row])) {
+		maxsmush=STRLEN(outputline[row]);
+		}
+	  for (charbd=STRLEN(currchar[row]);
+		ch1=currchar[row][charbd],(charbd>0&&(!ch1||ch1==' '));charbd--) ;
+	  for (linebd=0;ch2=outputline[row][linebd],ch2==' ';linebd++) ;
+	  amt = linebd+currcharwidth-1-charbd;
+	  }
+	else {
+	  for (linebd=STRLEN(outputline[row]);
+		ch1 = outputline[row][linebd],(linebd>0&&(!ch1||ch1==' '));linebd--) ;
+	  for (charbd=0;ch2=currchar[row][charbd],ch2==' ';charbd++) ;
+	  amt = charbd+outlinelen-1-linebd;
+	  }
+	if (!ch1||ch1==' ') {
+	  amt++;
+	  }
+	else if (ch2) {
+	  if (smushem(ch1,ch2)!='\0') {
+		amt++;
+		}
+	  }
+	if (amt<maxsmush) {
+	  maxsmush = amt;
+	  }
+	}
+  return maxsmush;
+}
+
+
+/****************************************************************************
+
+  addchar
+
+  Attempts to add the given character onto the end of the current line.
+  Returns 1 if this can be done, 0 otherwise.
+
+****************************************************************************/
+
+int addchar(c)
+inchr c;
+{
+  int smushamount,row,k,column;
+  outchr *templine;
+
+  getletter(c);
+  smushamount = smushamt();
+  if (outlinelen+currcharwidth-smushamount>outlinelenlimit
+	  ||inchrlinelen+1>inchrlinelenlimit) {
+	return 0;
+	}
+
+  templine = (outchr*)myalloc(sizeof(outchr)*(outlinelenlimit+1));
+  for (row=0;row<charheight;row++) {
+	if (right2left) {
+	  STRCPY(templine,currchar[row]);
+	  for (k=0;k<smushamount;k++) {
+		templine[currcharwidth-smushamount+k] =
+		  smushem(templine[currcharwidth-smushamount+k],outputline[row][k]);
+		}
+	  STRCAT(templine,outputline[row]+smushamount);
+	  STRCPY(outputline[row],templine);
+	  }
+	else {
+	  for (k=0;k<smushamount;k++) {
+	column = outlinelen-smushamount+k;
+	if (column < 0) {
+	  column = 0;
+	  }
+		outputline[row][column] =
+		  smushem(outputline[row][column],currchar[row][k]);
+		}
+	  STRCAT(outputline[row],currchar[row]+smushamount);
+	  }
+	}
+  free(templine);
+  outlinelen = STRLEN(outputline[0]);
+  inchrline[inchrlinelen++] = c;
+  return 1;
+}
+
+
+/****************************************************************************
+
+  putstring
+
+  Prints out the given null-terminated string, substituting blanks
+  for hardblanks.  If outputwidth is 1, prints the entire string;
+  otherwise prints at most outputwidth-1 characters.  Prints a newline
+  at the end of the string.  The string is left-justified, centered or
+  right-justified (taking outputwidth as the screen width) if
+  justification is 0, 1 or 2, respectively.
+
+****************************************************************************/
+
+void putstring(string)
+outchr *string;
+{
+  int i,len;
+  char c[10];
+#ifdef TLF_FONTS
+  size_t size;
+  wchar_t wc[2];
+#endif
+
+  len = STRLEN(string);
+  if (outputwidth>1) {
+	if (len>outputwidth-1) {
+	  len = outputwidth-1;
+	  }
+	if (justification>0) {
+	  for (i=1;(3-justification)*i+len+justification-2<outputwidth;i++) {
+		putchar(' ');
+		}
+	  }
+	}
+  for (i=0;i<len;i++) {
+#ifdef TLF_FONTS
+	wc[0] = string[i];
+	wc[1] = 0;
+	size = wchar_to_utf8(wc,1,c,10,0);
+	if(size==1) {
+	  if(c[0]==hardblank) {
+		c[0] = ' ';
+		}
+	  }
+	c[size] = 0;
+	printf("%s",c);
+#else
+	putchar(string[i]==hardblank?' ':string[i]);
+#endif
+	}
+  putchar('\n');
+}
+
+
+/****************************************************************************
+
+  fig_flush
+
+  Prints outputline using putstring, then clears the current line.
+
+****************************************************************************/
+
+void fig_flush()
+{
+  int i;
+
+  for (i=0;i<charheight;i++) {
+	putstring(outputline[i]);
+	}
+  clearline();
+}
+
+
+/****************************************************************************
+
+  splitline
+
+  Splits inchrline at the last word break (bunch of consecutive blanks).
+  Makes a new line out of the first part and prints it using
+  fig_flush.  Makes a new line out of the second part and returns.
+
+****************************************************************************/
+
+void splitline()
+{
+  int i,gotspace,lastspace,len1,len2;
+  inchr *part1,*part2;
+
+  part1 = (inchr*)myalloc(sizeof(inchr)*(inchrlinelen+1));
+  part2 = (inchr*)myalloc(sizeof(inchr)*(inchrlinelen+1));
+  gotspace = 0;
+  lastspace = inchrlinelen-1;
+  for (i=inchrlinelen-1;i>=0;i--) {
+	if (!gotspace && inchrline[i]==' ') {
+	  gotspace = 1;
+	  lastspace = i;
+	  }
+	if (gotspace && inchrline[i]!=' ') {
+	  break;
+	  }
+	}
+  len1 = i+1;
+  len2 = inchrlinelen-lastspace-1;
+  for (i=0;i<len1;i++) {
+	part1[i] = inchrline[i];
+	}
+  for (i=0;i<len2;i++) {
+	part2[i] = inchrline[lastspace+1+i];
+	}
+  clearline();
+  for (i=0;i<len1;i++) {
+	addchar(part1[i]);
+	}
+  fig_flush();
+  for (i=0;i<len2;i++) {
+	addchar(part2[i]);
+	}
+  free(part1);
+  free(part2);
+}
+
+
+/****************************************************************************
+
+  handlemapping
+
+  Given an input character (type inchr), executes re-mapping commands
+  read from control files.  Returns re-mapped character (inchr).
+
+****************************************************************************/
+
+inchr handlemapping(c)
+inchr c;
+{
+  comnode *cmptr;
+
+  cmptr=commandlist;
+  while (cmptr!=NULL) {
+	if (cmptr->thecommand ?
+	  (c >= cmptr->rangelo && c <= cmptr->rangehi) : 0) {
+	  c += cmptr->offset;
+	  while(cmptr!=NULL ? cmptr->thecommand : 0) {
+		cmptr=cmptr->next;
+		}
+	  }
+	else {
+	  cmptr=cmptr->next;
+	  }
+	}
+  return c;
+}
+
+/****************************************************************************
+
+  Agetchar
+
+  Replacement to getchar().
+  Acts exactly like getchar if -A is NOT specified,
+  else obtains input from All remaining command line words.
+
+****************************************************************************/
+
+int Agetchar()
+{
+	extern int optind;		/* current argv[] element under study */
+	static int AgetMode = 0;	/* >= 0 for displacement into argv[n], <0 EOF */
+	char   *arg;		/* pointer to active character */
+	int    c;			/* current character */
+
+	if ( ! cmdinput )		/* is -A active? */
+	return( getchar() );	/* no: return stdin character */
+
+	if ( AgetMode < 0 || optind >= Myargc )		/* EOF is sticky: */
+	return( EOF );		/* **ensure it now and forever more */
+
+	/* find next character */
+	arg = Myargv[optind];		/* pointer to active arg */
+	c = arg[AgetMode++]&0xFF;	/* get appropriate char of arg */
+
+	if ( ! c )			/* at '\0' that terminates word? */
+	{   /* at end of word: return ' ' if normal word, '\n' if empty */
+	c = ' ';		/* suppose normal word and return blank */
+	if ( AgetMode == 1 )	/* if ran out in very 1st char, force \n */
+		c = '\n';		/* (allows "hello '' world" to do \n at '') */
+	AgetMode = 0;		/* return to char 0 in NEXT word */
+	if ( ++optind >= Myargc )	/* run up word count and check if at "EOF" */
+	{   /* just ran out of arguments */
+		c = EOF;		/* return EOF */
+		AgetMode = -1;	/* ensure all future returns return EOF */
+	}
+	}
+
+	return( c );		/* return appropriate character */
+
+}	/* end: Agetchar() */
+
+
+/****************************************************************************
+
+  iso2022
+
+  Called by getinchr.  Interprets ISO 2022 sequences
+
+******************************************************************************/
+
+inchr iso2022()
+{
+  inchr ch;
+  inchr ch2;
+  int save_gl;
+  int save_gr;
+
+  ch = Agetchar();
+  if (ch == EOF) return ch;
+  if (ch == 27) ch = Agetchar() + 0x100; /* ESC x */
+  if (ch == 0x100 + '$') ch = Agetchar() + 0x200; /* ESC $ x */
+  switch (ch) {
+	case 14: /* invoke G1 into GL */
+	  gl = 1;
+	  return iso2022();
+	case 15: /* invoke G0 into GL */
+	  gl = 0;
+	  return iso2022();
+	case 142: case 'N' + 0x100: /* invoke G2 into GL for next char */
+	  save_gl = gl; save_gr = gr;
+	  gl = gr = 2;
+	  ch = iso2022();
+	  gl = save_gl; gr = save_gr;
+	  return ch;
+	case 143: case 'O' + 0x100: /* invoke G3 into GL for next char */
+	  save_gl = gl; save_gr = gr;
+	  gl = gr = 3;
+	  ch = iso2022();
+	  gl = save_gl; gr = save_gr;
+	  return ch;
+	case 'n' + 0x100: /* invoke G2 into GL */
+	  gl = 2;
+	  return iso2022();
+	case 'o' + 0x100: /* invoke G3 into GL */
+	  gl = 3;
+	  return iso2022();
+	case '~' + 0x100: /* invoke G1 into GR */
+	  gr = 1;
+	  return iso2022();
+	case '}' + 0x100: /* invoke G2 into GR */
+	  gr = 2;
+	  return iso2022();
+	case '|' + 0x100: /* invoke G3 into GR */
+	  gr = 3;
+	  return iso2022();
+	case '(' + 0x100: /* set G0 to 94-char set */
+	  ch = Agetchar();
+	  if (ch == 'B') ch = 0; /* ASCII */
+	  gn[0] = ch << 16;
+	  gndbl[0] = 0;
+	  return iso2022();
+	case ')' + 0x100: /* set G1 to 94-char set */
+	  ch = Agetchar();
+	  if (ch == 'B') ch = 0;
+	  gn[1] = ch << 16;
+	  gndbl[1] = 0;
+	  return iso2022();
+	case '*' + 0x100: /* set G2 to 94-char set */
+	  ch = Agetchar();
+	  if (ch == 'B') ch = 0;
+	  gn[2] = ch << 16;
+	  gndbl[2] = 0;
+	  return iso2022();
+	case '+' + 0x100: /* set G3 to 94-char set */
+	  ch = Agetchar();
+	  if (ch == 'B') ch = 0;
+	  gn[3] = ch << 16;
+	  gndbl[3] = 0;
+	  return iso2022();
+	case '-' + 0x100: /* set G1 to 96-char set */
+	  ch = Agetchar();
+	  if (ch == 'A') ch = 0; /* Latin-1 top half */
+	  gn[1] = (ch << 16) | 0x80;
+	  gndbl[1] = 0;
+	  return iso2022();
+	case '.' + 0x100: /* set G2 to 96-char set */
+	  ch = Agetchar();
+	  if (ch == 'A') ch = 0;
+	  gn[2] = (ch << 16) | 0x80;
+	  gndbl[2] = 0;
+	  return iso2022();
+	case '/' + 0x100: /* set G3 to 96-char set */
+	  ch = Agetchar();
+	  if (ch == 'A') ch = 0;
+	  gn[3] = (ch << 16) | 0x80;
+	  gndbl[3] = 0;
+	  return iso2022();
+	case '(' + 0x200: /* set G0 to 94 x 94 char set */
+	  ch = Agetchar();
+	  gn[0] = ch << 16;
+	  gndbl[0] = 1;
+	  return iso2022();
+	case ')' + 0x200: /* set G1 to 94 x 94 char set */
+	  ch = Agetchar();
+	  gn[1] = ch << 16;
+	  gndbl[1] = 1;
+	  return iso2022();
+	case '*' + 0x200: /* set G2 to 94 x 94 char set */
+	  ch = Agetchar();
+	  gn[2] = ch << 16;
+	  gndbl[2] = 1;
+	  return iso2022();
+	case '+' + 0x200: /* set G3 to 94 x 94 char set */
+	  ch = Agetchar();
+	  gn[3] = ch << 16;
+	  gndbl[3] = 1;
+	  return iso2022();
+	default:
+	  if (ch & 0x200) { /* set G0 to 94 x 94 char set (deprecated) */
+		gn[0] = (ch & ~0x200) << 16;
+		gndbl[0] = 1;
+		return iso2022();
+		}
+	  }
+
+  if (ch >= 0x21 && ch <= 0x7E) { /* process GL */
+	if (gndbl[gl]) {
+	  ch2 = Agetchar();
+	  return gn[gl] | (ch << 8) | ch2;
+	  }
+	else return gn[gl] | ch;
+	}
+  else if (ch >= 0xA0 && ch <= 0xFF) { /* process GR */
+	if (gndbl[gr]) {
+	  ch2 = Agetchar();
+	  return gn[gr] | (ch << 8) | ch2;
+	  }
+	else return gn[gr] | (ch & ~0x80);
+	}
+  else return ch;
+  }
+
+/****************************************************************************
+
+  ungetinchr
+
+  Called by main.  Pushes back an "inchr" to be read by getinchr
+  on the next call.
+
+******************************************************************************/
+inchr getinchr_buffer;
+int getinchr_flag;
+
+inchr ungetinchr(c)
+inchr c;
+{
+  getinchr_buffer = c;
+  getinchr_flag = 1;
+  return c;
+}
+
+/*****************************************************************************
+
+  getinchr
+
+  Called by main.  Processes multibyte characters.  Invokes Agetchar.
+  If multibyte = 0, ISO 2022 mode (see iso2022 routine).
+  If multibyte = 1,  double-byte mode (0x00-0x7f bytes are characters,
+	0x80-0xFF bytes are first byte of a double-byte character).
+  If multibyte = 2, Unicode UTF-8 mode (0x00-0x7F bytes are characters,
+	0x80-0xBF bytes are nonfirst byte of a multibyte character,
+	0xC0-0xFD bytes are first byte of a multibyte character,
+	0xFE-0xFF bytes are errors (all errors return code 0x0080)).
+  If multibyte = 3, HZ mode ("~{" starts double-byte mode, "}~" ends it,
+	"~~" is a tilde, "~x" for all other x is ignored).
+  If multibyte = 4, Shift-JIS mode (0x80-0x9F and 0xE0-0xEF are first byte
+	of a double-byte character, all other bytes are characters).
+ 
+
+*****************************************************************************/
+
+inchr getinchr()
+{
+  int ch, ch2, ch3, ch4, ch5, ch6;
+
+  if (getinchr_flag) {
+	getinchr_flag = 0;
+	return getinchr_buffer;
+	}
+
+  switch(multibyte) {
+   case 0: /* single-byte */
+	  return iso2022();
+   case 1: /* DBCS */
+	 ch = Agetchar();
+	 if ((ch >= 0x80 && ch <= 0x9F) ||
+		 (ch >= 0xE0 && ch <= 0xEF)) {
+	   ch = (ch << 8) + Agetchar();
+	   }
+	 return ch;
+   case 2: /* UTF-8 */
+	  ch = Agetchar();
+	  if (ch < 0x80) return ch;  /* handles EOF, too */
+	  if (ch < 0xC0 || ch > 0xFD)
+		return 0x0080;  /* illegal first character */
+	  ch2 = Agetchar() & 0x3F;
+	  if (ch < 0xE0) return ((ch & 0x1F) << 6) + ch2;
+	  ch3 = Agetchar() & 0x3F;
+	  if (ch < 0xF0)
+		return ((ch & 0x0F) << 12) + (ch2 << 6) + ch3;
+	  ch4 = Agetchar() & 0x3F;
+	  if (ch < 0xF8)
+		return ((ch & 0x07) << 18) + (ch2 << 12) + (ch3 << 6) + ch4;
+	  ch5 = Agetchar() & 0x3F;
+	  if (ch < 0xFC)
+		return ((ch & 0x03) << 24) + (ch2 << 18) + (ch3 << 12) +
+		  (ch4 << 6) + ch5;
+	  ch6 = Agetchar() & 0x3F;
+	  return ((ch & 0x01) << 30) + (ch2 << 24) + (ch3 << 18) +
+		(ch4 << 12) + (ch5 << 6) + ch6;
+   case 3: /* HZ */
+	 ch = Agetchar();
+	 if (ch == EOF) return ch;
+	 if (hzmode) {
+	   ch = (ch << 8) + Agetchar();
+	   if (ch == ('}' << 8) + '~') {
+		 hzmode = 0;
+		 return getinchr();
+		 }
+	   return ch;
+	   }
+	 else if (ch == '~') {
+	   ch = Agetchar();
+	   if (ch == '{') {
+		  hzmode = 1;
+		  return getinchr();
+		  }
+	  else if (ch == '~') {
+		return ch;
+		}
+	  else {
+		return getinchr();
+		}
+	  }
+	 else return ch;
+   case 4: /* Shift-JIS */
+	 ch = Agetchar();
+	 if ((ch >= 0x80 && ch <= 0x9F) ||
+		 (ch >= 0xE0 && ch <= 0xEF)) {
+	   ch = (ch << 8) + Agetchar();
+	   }
+	 return ch;
+   default:
+	 return 0x80;
+	}
+  }
+
+void fig_init(argc, argv)
+int argc;
+char** argv;
+{
+  Myargc = argc;
+  Myargv = argv;
+
+  if ((myname = strrchr(Myargv[0],DIRSEP))!=NULL) {
+	myname++;
+	}
+  else {
+	myname = Myargv[0];
+	}
+  fontdirname = DEFAULTFONTDIR;
+  fontname = DEFAULTFONTFILE;
+  cfilelist = NULL;
+  cfilelistend = &cfilelist;
+  commandlist = NULL;
+  commandlistend = &commandlist;
+  smushoverride = SMO_NO;
+  deutschflag = 0;
+  justification = -1;
+  right2left = -1;
+  paragraphflag = 0;
+  cmdinput = 0;
+  outputwidth = DEFAULTCOLUMNS;
+  gn[1] = 0x80;
+  gr = 1;
+  outlinelenlimit = outputwidth-1;
+}
+
+void fig_putchar(c)
+const inchr c;
+{
+  int i;
+  int char_not_added;
+  static int wordbreakmode = 0;
+
+	do {
+	  char_not_added = 0;
+
+	  if (wordbreakmode== -1) {
+		if (c==' ') {
+		  break;
+		  }
+		else if (c=='\n') {
+		  wordbreakmode = 0;
+		  break;
+		  }
+		wordbreakmode = 0;
+		}
+
+	  if (c=='\n') {
+		fig_flush();
+		wordbreakmode = 0;
+		}
+
+	  else if (addchar(c)) {
+		if (c!=' ') {
+		  wordbreakmode = (wordbreakmode>=2)?3:1;
+		  }
+		else {
+		  wordbreakmode = (wordbreakmode>0)?2:0;
+		  }
+		}
+
+	  else if (outlinelen==0) {
+    for (i=0;i<charheight;i++) {
+      if (right2left && outputwidth>1) {
+        putstring(currchar[i]+STRLEN(currchar[i])-outlinelenlimit);
+        }
+      else {
+        putstring(currchar[i]);
+        }
+      }
+    wordbreakmode = -1;
+    }
+
+  else if (c==' ') {
+    if (wordbreakmode==2) {
+      splitline();
+      }
+    else {
+      fig_flush();
+      }
+    wordbreakmode = -1;
+    }
+
+  else {
+    if (wordbreakmode>=2) {
+      splitline();
+      }
+    else {
+      fig_flush();
+      }
+    wordbreakmode = (wordbreakmode==3)?1:0;
+    char_not_added = 1;
+    }
+
+  } while (char_not_added);
+}
+
+void fig_puts(string)
 char* string;
 {
 	char* str_ptr = string;
 	while(*str_ptr!=0){
-		f(*str_ptr);
+		fig_putchar(handlemapping(*str_ptr));
 		++str_ptr;
 	}
 }
diff --git a/figlet.c b/figlet.c
index e26c207..c44c461 100644
--- a/figlet.c
+++ b/figlet.c
@@ -1,5 +1,206 @@
 #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
@@ -55,11 +256,11 @@ char *argv[];
 
     if ((c>'\0' && c<' ' && c!='\n') || c==127) continue;
 
-	f(c);
+	fig_puts(c);
   }
 
   if (outlinelen!=0) {
-    printline();
+    fig_flush();
     }
 
   return 0;
diff --git a/tests/FIGlib.c b/tests/FIGlib.c
index 7fc6471..612b507 100644
--- a/tests/FIGlib.c
+++ b/tests/FIGlib.c
@@ -5,16 +5,16 @@ int main(argc,argv)
 int argc;
 char *argv[];
 {
-  //fontinfo fi;
-  //readfont(&fi);
   fig_init();
   fontdirname = "fonts/";
+  fontname = "small";
   readcontrolfiles();
   readfont();
   linealloc();
-	fs("Hello ");
-	fs("World!");
-    printline();
+  fig_puts("Hello ");
+  linealloc();
+  fig_puts("World!");
+  fig_flush();
 
   return 0;
 }