    public void exportPony(Pony pony) throws IOException
    {
	Color[] colours = new Color[256];
	boolean[] format = new boolean[9];
	Color background = null, foreground = null;
	for (int i = 0; i < 256; i++)
	{   Colour colour = new Colour(i);
	    colours[i] = new Color(colour.red, colour.green, colour.blue);
	}
	if (this.palette != null)
	    System.arraycopy(this.palette, 0, colours, 0, 16);
	StringBuilder resetpalette = null;
	if (this.tty)
	    if (this.colourful)
	    {   resetpalette = new StringBuilder();
		for (int i = 0; i < 16; i++)
		{   Colour colour = new Colour(i);
		    resetpalette.append("\033]P");
		    resetpalette.append("0123456789ABCDEF".charAt(i));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue & 15));
	    }   }
	    else
	    {   resetpalette = new StringBuilder();
		for (int i : new int[] { 7, 15 })
		{   Colour colour = new Colour(i);
		    resetpalette.append("\033]P");
		    resetpalette.append("0123456789ABCDEF".charAt(i));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue & 15));
	    }   }
	else if (this.fullcolour)
	{   resetpalette = new StringBuilder();
	    for (int i = 0; i < 16; i++)
	    {   Colour colour = new Colour(i);
		resetpalette.append("\033]4;");
		resetpalette.append(i);
		resetpalette.append(";rgb:");
		resetpalette.append("0123456789ABCDEF".charAt(colour.red >>> 4));
		resetpalette.append("0123456789ABCDEF".charAt(colour.red & 15));
		resetpalette.append('/');
		resetpalette.append("0123456789ABCDEF".charAt(colour.green >>> 4));
		resetpalette.append("0123456789ABCDEF".charAt(colour.green & 15));
		resetpalette.append('/');
		resetpalette.append("0123456789ABCDEF".charAt(colour.blue >>> 4));
		resetpalette.append("0123456789ABCDEF".charAt(colour.blue & 15));
		resetpalette.append("\033\\");
	}   }
	StringBuilder databuf = new StringBuilder();
	int curleft = 0, curright = 0, curtop = 0, curbottom = 0;
	Pony.Cell[][] matrix = pony.matrix;
	Pony.Meta[][][] metamatrix = pony.metamatrix;
	boolean[] PLAIN = new boolean[9];
	if ((pony.tags != null) || (pony.comment != null))
	    databuf.append("$$$\n");
	if (pony.tags != null)
	    for (String[] tag : pony.tags)
	    {
		databuf.append(tag[0].toUpperCase());
		databuf.append(": ");
		databuf.append(tag[1]);
		databuf.append("\n");
	    }
	if (pony.comment != null)
	{
	    if ((pony.tags != null) && (pony.tags.length != 0))
		databuf.append('\n');
	    String comment = '\n' + pony.comment.trim() + '\n';
	    while (comment.contains("\n$$$\n"))
		comment = comment.replace("\n$$$\n", "\n$$$(!)\n");
	    comment = comment.substring(1, comment.length() - 1);
	    databuf.append(comment);
	}
	if ((pony.tags != null) || (pony.comment != null))
	    databuf.append("\n$$$\n");
	if (this.ignoreballoon)
	    for (Pony.Meta[][] row : metamatrix)
		for (Pony.Meta[] cell : row)
		    if (cell != null)
			for (int i = 0, n = cell.length; i < n; i++)
			    if ((cell[i] != null) && (cell[i] instanceof Pony.Balloon))
				row[i] = null;
	if (this.ignorelink)
	    for (Pony.Cell[] row : matrix)
		for (int i = 0, n = row.length; i < n; i++)
		{   Pony.Cell cell;
		    if ((cell = row[i]) != null)
			if (this.ignorelink && ((cell.character == Pony.Cell.NNE_SSW) || (cell.character == Pony.Cell.NNW_SSE)))
			    row[i] = new Pony.Cell(' ', null, null, PLAIN);
			else
			{   Color back = ((cell.lowerColour == null) || (cell.lowerColour.getAlpha() < 112)) ? null : cell.lowerColour;
			    Color fore = ((cell.upperColour == null) || (cell.upperColour.getAlpha() < 112)) ? null : cell.upperColour;
			    row[i] = new Pony.Cell(cell.character, back, fore, cell.format); 
			}
	        }
	if (this.left >= 0)
	{
	    int cur = 0;
	    outer:
	        for (int n = matrix[0].length; cur < n; cur++)
		    for (int j = 0, m = matrix.length; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = matrix[j][cur];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metamatrix[j][cur];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		    }
	    this.left -= cur;
	    if (this.left < 0)
		{
		    int w = matrix[0].length;
		    for (int j = 0, n = matrix.length; j < n; j++)
		    {	System.arraycopy(matrix[j], 0, matrix[j] = new Pony.Cell[w - this.left], -this.left, w);
			System.arraycopy(metamatrix[j], 0, metamatrix[j] = new Pony.Meta[w + 1 - this.left][], -this.left, w + 1);
		    }
		    this.left = 0;
		}
	}
	else
	    this.left = 0;
	if (this.right >= 0)
	{
	    int cur = 0;
	    outer:
	        for (int n = matrix[0].length - 1; cur <= n; cur++)
		    for (int j = 0, m = matrix.length; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = matrix[j][n - cur];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metamatrix[j][n - cur];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		    }
	    this.right -= cur;
	    if (this.right < 0)
		{
		    int w = matrix[0].length;
		    for (int j = 0, n = matrix.length; j < n; j++)
		    {	System.arraycopy(matrix[j], 0, matrix[j] = new Pony.Cell[w - this.right], 0, w);
			System.arraycopy(metamatrix[j], 0, metamatrix[j] = new Pony.Meta[w + 1 - this.right][], 0, w + 1);
		    }
		    this.right = 0;
		}
	}
	else
	    this.right = 0;
	if (this.top >= 0)
	{
	    int cur = 0, m = matrix[0].length - this.right;
	    outer:
	        for (int n = matrix.length; cur < n; cur++)
		{   Pony.Cell[] row = matrix[cur];
		    Pony.Meta[][] metarow = metamatrix[cur];
		    for (int j = this.left; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = row[j];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metarow[j];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		}   }
	    this.top -= cur;
	    if (this.top < 0)
		{
		    int w = matrix[0].length;
		    System.arraycopy(matrix, 0, matrix = new Pony.Cell[matrix.length - this.top][], -this.top, matrix.length);
		    System.arraycopy(new Pony.Cell[-this.top][w], 0, matrix, 0, -this.top);
		    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[metamatrix.length - this.top][][], -this.top, metamatrix.length);
		    System.arraycopy(new Pony.Meta[-this.top][w + 1][], 0, metamatrix, 0, -this.top);
		    this.top = 0;
		}
	}
	else
	    this.top = 0;
	if (this.bottom >= 0)
	{
	    int cur = 0, m = matrix[0].length - this.right;
	    outer:
	        for (int n = matrix.length - 1 - this.top; cur <= n; cur++)
		{   Pony.Cell[] row = matrix[n - cur];
		    Pony.Meta[][] metarow = metamatrix[n - cur];
		    for (int j = this.left; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = row[j];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metarow[j];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		}   }
	    this.bottom -= cur;
	    if (this.bottom < 0)
		{
		    int h = matrix.length;
		    System.arraycopy(matrix, 0, matrix = new Pony.Cell[matrix.length - this.bottom][], 0, matrix.length);
		    System.arraycopy(new Pony.Cell[-this.bottom][matrix[0].length], 0, matrix, h, -this.bottom);
		    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[metamatrix.length - this.bottom][][], 0, metamatrix.length);
		    System.arraycopy(new Pony.Meta[-this.bottom][metamatrix[0].length][], 0, metamatrix, h, -this.bottom);
		    this.bottom = 0;
		}
	}
	else
	    this.bottom = 0;
	if (this.left > 0)
	{   int w = matrix[0].length;
	    for (int y = 0, h = matrix.length; y < h; y++)
	    {
		System.arraycopy(matrix[y], 0, matrix[y] = new Pony.Cell[w + this.left], this.left, w);
		System.arraycopy(metamatrix[y], 0, metamatrix[y] = new Pony.Meta[w + 1 + this.left][], this.left, w + 1);
	    }
	    this.left = 0;
	}
	else
	    this.left = -this.left;
	if (this.right > 0)
	{   int w = matrix[0].length;
	    for (int y = 0, h = matrix.length; y < h; y++)
	    {
		System.arraycopy(matrix[y], 0, matrix[y] = new Pony.Cell[w + this.right], 0, w);
		System.arraycopy(metamatrix[y], 0, metamatrix[y] = new Pony.Meta[w + 1 + this.right][], 0, w + 1);
	    }
	    this.right = 0;
	}
	else
	    this.right = -this.right;
	if (this.top > 0)
	{
	    int h = matrix.length, w = matrix[0].length;
	    Pony.Cell[][] appendix = new Pony.Cell[this.top][w];
	    System.arraycopy(matrix, 0, matrix = new Pony.Cell[h + this.top][], this.top, h);
	    System.arraycopy(appendix, 0, matrix, 0, this.top);
	    Pony.Meta[][][] metaappendix = new Pony.Meta[this.top][w + 1][];
	    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[h + this.top][w + 1][], this.top, h);
	    System.arraycopy(metaappendix, 0, metamatrix, 0, this.top);
	    this.top = 0;
	}
	else
	    this.top = -this.top;
	if (this.bottom > 0)
	{
	    int h = matrix.length, w = matrix[0].length;
	    Pony.Cell[][] appendix = new Pony.Cell[this.bottom][w];
	    System.arraycopy(matrix, 0, matrix = new Pony.Cell[h + this.bottom][], 0, h);
	    System.arraycopy(appendix, 0, matrix, h, this.bottom);
	    Pony.Meta[][][] metaappendix = new Pony.Meta[this.bottom][w + 1][];
	    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[h + this.bottom][][], 0, h);
	    System.arraycopy(metaappendix, 0, metamatrix, h, this.bottom);
	    this.bottom = 0;
	}
	else
	    this.bottom = -this.bottom;
	for (int y = 0; y < this.top; y++)
	{   Pony.Meta[][] metarow = metamatrix[y];
	    for (int x = 0, w = metarow.length; x < w; x++)
	    {   Pony.Meta[] metacell = metarow[x];
		for (int z = 0, d = metacell.length; z < d; z++)
		{   Pony.Meta metaelem;
		    if (((metaelem = metacell[z]) != null) && (metaelem instanceof Pony.Store))
			databuf.append("$" + (((Pony.Store)(metaelem)).name + "=" + ((Pony.Store)(metaelem)).value).replace("$", "\033$") + "$");
	}   }   }
	if (this.right != 0)
	{   int w = matrix[0].length, r = metamatrix[0].length - this.right;
	    Pony.Meta[] leftovers = new Pony.Meta[32];
	    for (int y = this.top, h = matrix.length - this.bottom; y < h; y++)
	    {
		int ptr = 0;
		Pony.Meta[][] metarow = metamatrix[y];
		for (int x = r; x <= w; x++)
		    if (metarow[x] != null)
			for (Pony.Meta meta : metarow[x])
			    if ((meta != null) && (meta instanceof Pony.Store))
			    {   if (ptr == leftovers.length)
				    System.arraycopy(leftovers, 0, leftovers = new Pony.Meta[ptr << 1], 0, ptr);
				leftovers[ptr++] = meta;
			    }
		if (ptr != 0)
		{   Pony.Meta[] metacell = metarow[r];
		    System.arraycopy(metacell, 0, metarow[r] = metacell = new Pony.Meta[metacell.length + ptr], 0, metacell.length - ptr);
		    System.arraycopy(leftovers, 0, metacell, metacell.length - ptr, ptr);
		}
		System.arraycopy(matrix[y], 0, matrix[y] = new Pony.Cell[w - this.right], 0, w - this.right);
		System.arraycopy(metarow, 0, metamatrix[y] = new Pony.Meta[w - this.right + 1][], 0, w - this.right + 1);
	    }
	}
	int[] endings = null;
	if (this.even == false)
	{
	    int w = matrix[0].length;
	    endings = new int[matrix.length];
	    for (int y = 0, h = matrix.length; y < h; y++)
	    {
		Pony.Cell[] row = matrix[y];
		Pony.Meta[][] metarow = metamatrix[y];
		int cur = 0;
		mid:
		    for (int n = w - 1; cur <= n; cur++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = row[n - cur];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metarow[n - cur];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break mid;
			    }
			    else
				break mid;
			}
		    }
		endings[y] = w - cur;
	    }
	}
	Pony.Cell defaultcell = new Pony.Cell(' ', null, null, PLAIN);
	for (int y = this.top, h = matrix.length - this.bottom; y < h; y++)
	{
	    Pony.Cell[] row = matrix[y];
	    Pony.Meta[][] metarow = metamatrix[y];
	    int ending = endings == null ? row.length : endings[y];
	    for (int x = 0, w = row.length; x <= w; x++)
	    {   Pony.Meta[] metacell = metarow[x];
		if (metacell != null)
		    for (int z = 0, d = metacell.length; z < d; z++)
		    {   Pony.Meta meta = metacell[z];
			if ((meta != null) && ((x >= this.left) || (meta instanceof Pony.Store)))
			{   Class<?> metaclass = meta.getClass();
			    if (metaclass == Pony.Store.class)
				databuf.append("$" + (((Pony.Store)meta).name + "=" + ((Pony.Store)meta).value).replace("$", "\033$") + "$");
			    else if (metaclass == Pony.Recall.class)
			    {   Pony.Recall recall = (Pony.Recall)meta;
				Color back = ((recall.backgroundColour == null) || (recall.backgroundColour.getAlpha() < 112)) ? null : recall.backgroundColour;
				Color fore = ((recall.foregroundColour == null) || (recall.foregroundColour.getAlpha() < 112)) ? null : recall.foregroundColour;
				databuf.append(applyColour(colours, background, foreground, format, background = back, foreground = fore, recall.format));
				databuf.append("$" + recall.name.replace("$", "\033$") + "$");
			    }
			    else if (metaclass == Pony.Balloon.class)
			    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = null, format = PLAIN));
				Pony.Balloon balloon = (Pony.Balloon)meta;
				if (balloon.left != null)
				{   int justification = balloon.minWidth != null ? balloon.justification & (Pony.Balloon.LEFT | Pony.Balloon.RIGHT) : Pony.Balloon.NONE;
				    switch (justification)
				    {	case Pony.Balloon.NONE:
					    char[] spaces = new char[balloon.left.intValue()];
					    Arrays.fill(spaces, ' ');
					    databuf.append(new String(spaces));
					    databuf.append("$balloon" + balloon.left.intValue());
					    break;
					case Pony.Balloon.LEFT:
					    databuf.append("$balloon" + balloon.left.intValue() + "l");
					    databuf.append(balloon.left.intValue() + balloon.minWidth.intValue() - 1);
					    break;
					case Pony.Balloon.RIGHT:
					    databuf.append("$balloon" + balloon.left.intValue() + "r");
					    databuf.append(balloon.left.intValue() + balloon.minWidth.intValue() - 1);
					    break;
					default:
					    databuf.append("$balloon" + balloon.left.intValue() + "c");
					    databuf.append(balloon.left.intValue() + balloon.minWidth.intValue() - 1);
					    break;
				}   }
				else if (balloon.minWidth != null)
				    databuf.append("$balloon" + balloon.minWidth.toString());
				if (balloon.minHeight != null)
				    databuf.append("," + balloon.minHeight.toString());
				databuf.append("$\n");
		    }	}   }
		if ((x != w) && (x >= this.left) && (x < ending))
		{   Pony.Cell cell = row[x];
		    if (cell == null)
			cell = defaultcell;
		    if (cell.character >= 0)
		    {   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = cell.upperColour, format = cell.format));
			databuf.append(utf32to16(cell.character));
		    }
		    else if (cell.character == Pony.Cell.NNE_SSW)
		    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = null, format = PLAIN));
			databuf.append("$\\$");
		    }
		    else if (cell.character == Pony.Cell.NNW_SSE)
		    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = null, format = PLAIN));
			databuf.append("$/$");
		    }
		    else if (cell.character == Pony.Cell.PIXELS)
			if (cell.lowerColour == null)
			    if (cell.upperColour == null)
			    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = this.spacesave ? foreground : null, format = PLAIN));
				databuf.append(' ');
			    }
			    else
			    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = cell.upperColour, format = PLAIN));
				databuf.append('▀');
			    }
			else
			    if (cell.upperColour == null)
			    {   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = null, format = PLAIN));
				databuf.append('▀');
			    }
			    else if (cell.upperColour.equals(cell.lowerColour))
				if (this.zebra)
				{   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = cell.lowerColour, format = PLAIN));
				    databuf.append('▄');
				}
				else if (this.fullblocks )
				{   databuf.append(applyColour(colours, background, foreground, format, background = this.spacesave ? background : cell.lowerColour, foreground = cell.lowerColour, format = PLAIN));
				    databuf.append('█');
				}
				else
				{   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = this.spacesave ? foreground : cell.lowerColour, format = PLAIN));
				    databuf.append(' ');
				}
			    else  
			    {   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = cell.upperColour, format = PLAIN));
				databuf.append('▄');
			    }
		}
	    }
	    background = foreground = null;
	    format = PLAIN;
	    databuf.append("\033[0m\n");
	}
	String data = databuf.toString();
	if (this.version == VERSION_COWSAY)
	{
	    String metadata = null;
	    if (data.startsWith("$$$\n"))
	    {
		metadata = data.substring(4);
		if (metadata.startsWith("$$$\n"))
		    metadata = null;
		else
		{   metadata = metadata.substring(0, metadata.indexOf("\n$$$\n") + 5);
		    data = data.substring(data.indexOf("\n$$$\n") + 5);
		    metadata = '#' + metadata.replace("\n", "\n#");
		}
	    }
	    String eop = "\nEOP";
	    while (data.contains(eop + '\n'))
		eop += 'P';
	    data = data.replace("$/$", "/").replace("$\\$", "${thoughts}");
	    while (data.contains("$balloon"))
	    {
		int start = data.indexOf("$balloon");
		int end = data.indexOf("$", start + 8);
		data = data.substring(0, start) + data.substring(end + 1);
	    }
	    data = "$the_cow = <<" + eop + ";\n" + data;
	    data += eop + '\n';
	    if (metadata != null)
		data = metadata + data;
	    if (this.utf8 == false)
		data = data.replace("▀", "\\N{U+2580}").replace("▄", "\\N{U+2584}");
	}
	else
	{   if (this.version < VERSION_METADATA)
	    {
		if (data.startsWith("$$$\n"))
		    data = data.substring(data.indexOf("\n$$$\n") + 5);
	    }
	    if (this.version < VERSION_HORIZONTAL_JUSTIFICATION)
	    {
		databuf = new StringBuilder();
		int pos = data.indexOf("\n$$$\n");
		pos += pos < 0 ? 1 : 5;
		databuf.append(data.substring(0, pos));
		StringBuilder dollarbuf = null;
		boolean esc = false;
		for (int i = 0, n = data.length(); i < n;)
		{
		    char c = data.charAt(i++);
		    if (dollarbuf != null)
		    {
			dollarbuf.append(c);
			if (esc || (c == '\033'))
			    esc ^= true;
			else if (c == '$')
			{
			    String dollar = dollarbuf.toString();
			    dollarbuf = null;
			    if (dollar.startsWith("$balloon") == false)
				databuf.append(dollar);
			    else
			    {   databuf.append("$balloon");
				dollar = dollar.substring(8);
				if      (dollar.contains("l"))  dollar = dollar.substring(dollar.indexOf('l') + 1);
				else if (dollar.contains("r"))  dollar = dollar.substring(dollar.indexOf('r') + 1);
				else if (dollar.contains("c"))  dollar = dollar.substring(dollar.indexOf('c') + 1);
				databuf.append(dollar);
			}   }
		    }
		    else if (c == '$')
			dollarbuf = new StringBuilder("$");
		    else
			databuf.append(c);
		}
		data = databuf.toString();
	    }
	}
	if (resetpalette != null)
	    data += resetpalette.toString();
	if (this.escesc)
	    data = data.replace("\033", "\\e");
	OutputStream out = System.out;
	if (this.file != null)
	    out = new FileOutputStream(this.file); 
	out.write(data.getBytes("UTF-8"));
	out.flush();
	if (out != System.out)
	    out.close();
    }

    public void exportPony(Pony pony) throws IOException
    {
	Color[] colours = new Color[256];
	boolean[] format = new boolean[9];
	Color background = null, foreground = null;
	for (int i = 0; i < 256; i++)
	{   Colour colour = new Colour(i);
	    colours[i] = new Color(colour.red, colour.green, colour.blue);
	}
	if (this.palette != null)
	    System.arraycopy(this.palette, 0, colours, 0, 16);
	StringBuilder resetpalette = null;
	if (this.tty)
	    if (this.colourful)
	    {   resetpalette = new StringBuilder();
		for (int i = 0; i < 16; i++)
		{   Colour colour = new Colour(i);
		    resetpalette.append("\033]P");
		    resetpalette.append("0123456789ABCDEF".charAt(i));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue & 15));
	    }   }
	    else
	    {   resetpalette = new StringBuilder();
		for (int i : new int[] { 7, 15 })
		{   Colour colour = new Colour(i);
		    resetpalette.append("\033]P");
		    resetpalette.append("0123456789ABCDEF".charAt(i));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.red & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.green & 15));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue >>> 4));
		    resetpalette.append("0123456789ABCDEF".charAt(colour.blue & 15));
	    }   }
	else if (this.fullcolour)
	{   resetpalette = new StringBuilder();
	    for (int i = 0; i < 16; i++)
	    {   Colour colour = new Colour(i);
		resetpalette.append("\033]4;");
		resetpalette.append(i);
		resetpalette.append(";rgb:");
		resetpalette.append("0123456789ABCDEF".charAt(colour.red >>> 4));
		resetpalette.append("0123456789ABCDEF".charAt(colour.red & 15));
		resetpalette.append('/');
		resetpalette.append("0123456789ABCDEF".charAt(colour.green >>> 4));
		resetpalette.append("0123456789ABCDEF".charAt(colour.green & 15));
		resetpalette.append('/');
		resetpalette.append("0123456789ABCDEF".charAt(colour.blue >>> 4));
		resetpalette.append("0123456789ABCDEF".charAt(colour.blue & 15));
		resetpalette.append("\033\\");
	}   }
	StringBuilder databuf = new StringBuilder();
	int curleft = 0, curright = 0, curtop = 0, curbottom = 0;
	Pony.Cell[][] matrix = pony.matrix;
	Pony.Meta[][][] metamatrix = pony.metamatrix;
	boolean[] PLAIN = new boolean[9];
	if ((pony.tags != null) || (pony.comment != null))
	    databuf.append("$$$\n");
	if (pony.tags != null)
	    for (String[] tag : pony.tags)
	    {
		databuf.append(tag[0].toUpperCase());
		databuf.append(": ");
		databuf.append(tag[1]);
		databuf.append("\n");
	    }
	if (pony.comment != null)
	{
	    if ((pony.tags != null) && (pony.tags.length != 0))
		databuf.append('\n');
	    String comment = '\n' + pony.comment.trim() + '\n';
	    while (comment.contains("\n$$$\n"))
		comment = comment.replace("\n$$$\n", "\n$$$(!)\n");
	    comment = comment.substring(1, comment.length() - 1);
	    databuf.append(comment);
	}
	if ((pony.tags != null) || (pony.comment != null))
	    databuf.append("\n$$$\n");
	if (this.ignoreballoon)
	    for (Pony.Meta[][] row : metamatrix)
		for (Pony.Meta[] cell : row)
		    if (cell != null)
			for (int i = 0, n = cell.length; i < n; i++)
			    if ((cell[i] != null) && (cell[i] instanceof Pony.Balloon))
				row[i] = null;
	if (this.ignorelink)
	    for (Pony.Cell[] row : matrix)
		for (int i = 0, n = row.length; i < n; i++)
		{   Pony.Cell cell;
		    if ((cell = row[i]) != null)
			if (this.ignorelink && ((cell.character == Pony.Cell.NNE_SSW) || (cell.character == Pony.Cell.NNW_SSE)))
			    row[i] = new Pony.Cell(' ', null, null, PLAIN);
			else
			{   Color back = ((cell.lowerColour == null) || (cell.lowerColour.getAlpha() < 112)) ? null : cell.lowerColour;
			    Color fore = ((cell.upperColour == null) || (cell.upperColour.getAlpha() < 112)) ? null : cell.upperColour;
			    row[i] = new Pony.Cell(cell.character, back, fore, cell.format); 
			}
	        }
	if (this.left >= 0)
	{
	    int cur = 0;
	    outer:
	        for (int n = matrix[0].length; cur < n; cur++)
		    for (int j = 0, m = matrix.length; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = matrix[j][cur];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metamatrix[j][cur];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		    }
	    this.left -= cur;
	    if (this.left < 0)
		{
		    int w = matrix[0].length;
		    for (int j = 0, n = matrix.length; j < n; j++)
		    {	System.arraycopy(matrix[j], 0, matrix[j] = new Pony.Cell[w - this.left], -this.left, w);
			System.arraycopy(metamatrix[j], 0, metamatrix[j] = new Pony.Meta[w + 1 - this.left][], -this.left, w + 1);
		    }
		    this.left = 0;
		}
	}
	else
	    this.left = 0;
	if (this.right >= 0)
	{
	    int cur = 0;
	    outer:
	        for (int n = matrix[0].length - 1; cur <= n; cur++)
		    for (int j = 0, m = matrix.length; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = matrix[j][n - cur];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metamatrix[j][n - cur];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		    }
	    this.right -= cur;
	    if (this.right < 0)
		{
		    int w = matrix[0].length;
		    for (int j = 0, n = matrix.length; j < n; j++)
		    {	System.arraycopy(matrix[j], 0, matrix[j] = new Pony.Cell[w - this.right], 0, w);
			System.arraycopy(metamatrix[j], 0, metamatrix[j] = new Pony.Meta[w + 1 - this.right][], 0, w + 1);
		    }
		    this.right = 0;
		}
	}
	else
	    this.right = 0;
	if (this.top >= 0)
	{
	    int cur = 0, m = matrix[0].length - this.right;
	    outer:
	        for (int n = matrix.length; cur < n; cur++)
		{   Pony.Cell[] row = matrix[cur];
		    Pony.Meta[][] metarow = metamatrix[cur];
		    for (int j = this.left; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = row[j];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metarow[j];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		}   }
	    this.top -= cur;
	    if (this.top < 0)
		{
		    int w = matrix[0].length;
		    System.arraycopy(matrix, 0, matrix = new Pony.Cell[matrix.length - this.top][], -this.top, matrix.length);
		    System.arraycopy(new Pony.Cell[-this.top][w], 0, matrix, 0, -this.top);
		    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[metamatrix.length - this.top][][], -this.top, metamatrix.length);
		    System.arraycopy(new Pony.Meta[-this.top][w + 1][], 0, metamatrix, 0, -this.top);
		    this.top = 0;
		}
	}
	else
	    this.top = 0;
	if (this.bottom >= 0)
	{
	    int cur = 0, m = matrix[0].length - this.right;
	    outer:
	        for (int n = matrix.length - 1 - this.top; cur <= n; cur++)
		{   Pony.Cell[] row = matrix[n - cur];
		    Pony.Meta[][] metarow = metamatrix[n - cur];
		    for (int j = this.left; j < m; j++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = row[j];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metarow[j];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break outer;
			    }
			    else
				break outer;
			}
		}   }
	    this.bottom -= cur;
	    if (this.bottom < 0)
		{
		    int h = matrix.length;
		    System.arraycopy(matrix, 0, matrix = new Pony.Cell[matrix.length - this.bottom][], 0, matrix.length);
		    System.arraycopy(new Pony.Cell[-this.bottom][matrix[0].length], 0, matrix, h, -this.bottom);
		    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[metamatrix.length - this.bottom][][], 0, metamatrix.length);
		    System.arraycopy(new Pony.Meta[-this.bottom][metamatrix[0].length][], 0, metamatrix, h, -this.bottom);
		    this.bottom = 0;
		}
	}
	else
	    this.bottom = 0;
	if (this.left > 0)
	{   int w = matrix[0].length;
	    for (int y = 0, h = matrix.length; y < h; y++)
	    {
		System.arraycopy(matrix[y], 0, matrix[y] = new Pony.Cell[w + this.left], this.left, w);
		System.arraycopy(metamatrix[y], 0, metamatrix[y] = new Pony.Meta[w + 1 + this.left][], this.left, w + 1);
	    }
	    this.left = 0;
	}
	else
	    this.left = -this.left;
	if (this.right > 0)
	{   int w = matrix[0].length;
	    for (int y = 0, h = matrix.length; y < h; y++)
	    {
		System.arraycopy(matrix[y], 0, matrix[y] = new Pony.Cell[w + this.right], 0, w);
		System.arraycopy(metamatrix[y], 0, metamatrix[y] = new Pony.Meta[w + 1 + this.right][], 0, w + 1);
	    }
	    this.right = 0;
	}
	else
	    this.right = -this.right;
	if (this.top > 0)
	{
	    int h = matrix.length, w = matrix[0].length;
	    Pony.Cell[][] appendix = new Pony.Cell[this.top][w];
	    System.arraycopy(matrix, 0, matrix = new Pony.Cell[h + this.top][], this.top, h);
	    System.arraycopy(appendix, 0, matrix, 0, this.top);
	    Pony.Meta[][][] metaappendix = new Pony.Meta[this.top][w + 1][];
	    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[h + this.top][w + 1][], this.top, h);
	    System.arraycopy(metaappendix, 0, metamatrix, 0, this.top);
	    this.top = 0;
	}
	else
	    this.top = -this.top;
	if (this.bottom > 0)
	{
	    int h = matrix.length, w = matrix[0].length;
	    Pony.Cell[][] appendix = new Pony.Cell[this.bottom][w];
	    System.arraycopy(matrix, 0, matrix = new Pony.Cell[h + this.bottom][], 0, h);
	    System.arraycopy(appendix, 0, matrix, h, this.bottom);
	    Pony.Meta[][][] metaappendix = new Pony.Meta[this.bottom][w + 1][];
	    System.arraycopy(metamatrix, 0, metamatrix = new Pony.Meta[h + this.bottom][][], 0, h);
	    System.arraycopy(metaappendix, 0, metamatrix, h, this.bottom);
	    this.bottom = 0;
	}
	else
	    this.bottom = -this.bottom;
	for (int y = 0; y < this.top; y++)
	{   Pony.Meta[][] metarow = metamatrix[y];
	    for (int x = 0, w = metarow.length; x < w; x++)
	    {   Pony.Meta[] metacell = metarow[x];
		for (int z = 0, d = metacell.length; z < d; z++)
		{   Pony.Meta metaelem;
		    if (((metaelem = metacell[z]) != null) && (metaelem instanceof Pony.Store))
			databuf.append("$" + (((Pony.Store)(metaelem)).name + "=" + ((Pony.Store)(metaelem)).value).replace("$", "\033$") + "$");
	}   }   }
	if (this.right != 0)
	{   int w = matrix[0].length, r = metamatrix[0].length - this.right;
	    Pony.Meta[] leftovers = new Pony.Meta[32];
	    for (int y = this.top, h = matrix.length - this.bottom; y < h; y++)
	    {
		int ptr = 0;
		Pony.Meta[][] metarow = metamatrix[y];
		for (int x = r; x <= w; x++)
		    if (metarow[x] != null)
			for (Pony.Meta meta : metarow[x])
			    if ((meta != null) && (meta instanceof Pony.Store))
			    {   if (ptr == leftovers.length)
				    System.arraycopy(leftovers, 0, leftovers = new Pony.Meta[ptr << 1], 0, ptr);
				leftovers[ptr++] = meta;
			    }
		if (ptr != 0)
		{   Pony.Meta[] metacell = metarow[r];
		    System.arraycopy(metacell, 0, metarow[r] = metacell = new Pony.Meta[metacell.length + ptr], 0, metacell.length - ptr);
		    System.arraycopy(leftovers, 0, metacell, metacell.length - ptr, ptr);
		}
		System.arraycopy(matrix[y], 0, matrix[y] = new Pony.Cell[w - this.right], 0, w - this.right);
		System.arraycopy(metarow, 0, metamatrix[y] = new Pony.Meta[w - this.right + 1][], 0, w - this.right + 1);
	    }
	}
	int[] endings = null;
	if (this.even == false)
	{
	    int w = matrix[0].length;
	    endings = new int[matrix.length];
	    for (int y = 0, h = matrix.length; y < h; y++)
	    {
		Pony.Cell[] row = matrix[y];
		Pony.Meta[][] metarow = metamatrix[y];
		int cur = 0;
		mid:
		    for (int n = w - 1; cur <= n; cur++)
		    {
			boolean cellpass = true;
			Pony.Cell cell = row[n - cur];
			if (cell != null)
			    if ((cell.character != ' ') || (cell.lowerColour != null))
				if ((cell.character != Pony.Cell.PIXELS) || (cell.lowerColour != null) || (cell.upperColour != null))
				    cellpass = false;
			if (cellpass == false)
			{   Pony.Meta[] meta = metarow[n - cur];
			    if ((meta != null) && (meta.length != 0))
			    {	for (int k = 0, l = meta.length; k < l; k++)
				    if ((meta[k] != null) && ((meta[k] instanceof Pony.Store) == false))
					break mid;
			    }
			    else
				break mid;
			}
		    }
		endings[y] = w - cur;
	    }
	}
	Pony.Cell defaultcell = new Pony.Cell(' ', null, null, PLAIN);
	for (int y = this.top, h = matrix.length - this.bottom; y < h; y++)
	{
	    Pony.Cell[] row = matrix[y];
	    Pony.Meta[][] metarow = metamatrix[y];
	    int ending = endings == null ? row.length : endings[y];
	    for (int x = 0, w = row.length; x <= w; x++)
	    {   Pony.Meta[] metacell = metarow[x];
		if (metacell != null)
		    for (int z = 0, d = metacell.length; z < d; z++)
		    {   Pony.Meta meta = metacell[z];
			if ((meta != null) && ((x >= this.left) || (meta instanceof Pony.Store)))
			{   Class<?> metaclass = meta.getClass();
			    if (metaclass == Pony.Store.class)
				databuf.append("$" + (((Pony.Store)meta).name + "=" + ((Pony.Store)meta).value).replace("$", "\033$") + "$");
			    else if (metaclass == Pony.Recall.class)
			    {   Pony.Recall recall = (Pony.Recall)meta;
				Color back = ((recall.backgroundColour == null) || (recall.backgroundColour.getAlpha() < 112)) ? null : recall.backgroundColour;
				Color fore = ((recall.foregroundColour == null) || (recall.foregroundColour.getAlpha() < 112)) ? null : recall.foregroundColour;
				databuf.append(applyColour(colours, background, foreground, format, background = back, foreground = fore, recall.format));
				databuf.append("$" + recall.name.replace("$", "\033$") + "$");
			    }
			    else if (metaclass == Pony.Balloon.class)
			    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = null, format = PLAIN));
				Pony.Balloon balloon = (Pony.Balloon)meta;
				if (balloon.left != null)
				{   int justification = balloon.minWidth != null ? balloon.justification & (Pony.Balloon.LEFT | Pony.Balloon.RIGHT) : Pony.Balloon.NONE;
				    switch (justification)
				    {	case Pony.Balloon.NONE:
					    char[] spaces = new char[balloon.left.intValue()];
					    Arrays.fill(spaces, ' ');
					    databuf.append(new String(spaces));
					    databuf.append("$balloon" + balloon.left.intValue());
					    break;
					case Pony.Balloon.LEFT:
					    databuf.append("$balloon" + balloon.left.intValue() + "l");
					    databuf.append(balloon.left.intValue() + balloon.minWidth.intValue() - 1);
					    break;
					case Pony.Balloon.RIGHT:
					    databuf.append("$balloon" + balloon.left.intValue() + "r");
					    databuf.append(balloon.left.intValue() + balloon.minWidth.intValue() - 1);
					    break;
					default:
					    databuf.append("$balloon" + balloon.left.intValue() + "c");
					    databuf.append(balloon.left.intValue() + balloon.minWidth.intValue() - 1);
					    break;
				}   }
				else if (balloon.minWidth != null)
				    databuf.append("$balloon" + balloon.minWidth.toString());
				if (balloon.minHeight != null)
				    databuf.append("," + balloon.minHeight.toString());
				databuf.append("$");
		    }	}   }
		if ((x != w) && (x >= this.left) && (x < ending))
		{   Pony.Cell cell = row[x];
		    if (cell == null)
			cell = defaultcell;
		    if (cell.character >= 0)
		    {   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = cell.upperColour, format = cell.format));
			databuf.append(utf32to16(cell.character));
		    }
		    else if (cell.character == Pony.Cell.NNE_SSW)
		    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = null, format = PLAIN));
			databuf.append("$\\$");
		    }
		    else if (cell.character == Pony.Cell.NNW_SSE)
		    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = null, format = PLAIN));
			databuf.append("$/$");
		    }
		    else if (cell.character == Pony.Cell.PIXELS)
			if (cell.lowerColour == null)
			    if (cell.upperColour == null)
			    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = this.spacesave ? foreground : null, format = PLAIN));
				databuf.append(' ');
			    }
			    else
			    {   databuf.append(applyColour(colours, background, foreground, format, background = null, foreground = cell.upperColour, format = PLAIN));
				databuf.append('▀');
			    }
			else
			    if (cell.upperColour == null)
			    {   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = null, format = PLAIN));
				databuf.append('▀');
			    }
			    else if (cell.upperColour.equals(cell.lowerColour))
				if (this.zebra)
				{   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = cell.lowerColour, format = PLAIN));
				    databuf.append('▄');
				}
				else if (this.fullblocks )
				{   databuf.append(applyColour(colours, background, foreground, format, background = this.spacesave ? background : cell.lowerColour, foreground = cell.lowerColour, format = PLAIN));
				    databuf.append('█');
				}
				else
				{   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = this.spacesave ? foreground : cell.lowerColour, format = PLAIN));
				    databuf.append(' ');
				}
			    else  
			    {   databuf.append(applyColour(colours, background, foreground, format, background = cell.lowerColour, foreground = cell.upperColour, format = PLAIN));
				databuf.append('▄');
			    }
		}
	    }
	    background = foreground = null;
	    format = PLAIN;
	    databuf.append("\033[0m\n");
	}
	String data = databuf.toString();
	if (this.version == VERSION_COWSAY)
	{
	    String metadata = null;
	    if (data.startsWith("$$$\n"))
	    {
		metadata = data.substring(4);
		if (metadata.startsWith("$$$\n"))
		    metadata = null;
		else
		{   metadata = metadata.substring(0, metadata.indexOf("\n$$$\n") + 5);
		    data = data.substring(data.indexOf("\n$$$\n") + 5);
		    metadata = '#' + metadata.replace("\n", "\n#");
		}
	    }
	    String eop = "\nEOP";
	    while (data.contains(eop + '\n'))
		eop += 'P';
	    data = data.replace("$/$", "/").replace("$\\$", "${thoughts}");
	    while (data.contains("$balloon"))
	    {
		int start = data.indexOf("$balloon");
		int end = data.indexOf("$", start + 8);
		data = data.substring(0, start) + data.substring(end + 1);
	    }
	    data = "$the_cow = <<" + eop + ";\n" + data;
	    data += eop + '\n';
	    if (metadata != null)
		data = metadata + data;
	    if (this.utf8 == false)
		data = data.replace("▀", "\\N{U+2580}").replace("▄", "\\N{U+2584}");
	}
	else
	{   if (this.version < VERSION_METADATA)
	    {
		if (data.startsWith("$$$\n"))
		    data = data.substring(data.indexOf("\n$$$\n") + 5);
	    }
	    if (this.version < VERSION_HORIZONTAL_JUSTIFICATION)
	    {
		databuf = new StringBuilder();
		int pos = data.indexOf("\n$$$\n");
		pos += pos < 0 ? 1 : 5;
		databuf.append(data.substring(0, pos));
		StringBuilder dollarbuf = null;
		boolean esc = false;
		for (int i = 0, n = data.length(); i < n;)
		{
		    char c = data.charAt(i++);
		    if (dollarbuf != null)
		    {
			dollarbuf.append(c);
			if (esc || (c == '\033'))
			    esc ^= true;
			else if (c == '$')
			{
			    String dollar = dollarbuf.toString();
			    dollarbuf = null;
			    if (dollar.startsWith("$balloon") == false)
				databuf.append(dollar);
			    else
			    {   databuf.append("$balloon");
				dollar = dollar.substring(8);
				if      (dollar.contains("l"))  dollar = dollar.substring(dollar.indexOf('l') + 1);
				else if (dollar.contains("r"))  dollar = dollar.substring(dollar.indexOf('r') + 1);
				else if (dollar.contains("c"))  dollar = dollar.substring(dollar.indexOf('c') + 1);
				databuf.append(dollar);
			}   }
		    }
		    else if (c == '$')
			dollarbuf = new StringBuilder("$");
		    else
			databuf.append(c);
		}
		data = databuf.toString();
	    }
	}
	if (resetpalette != null)
	    data += resetpalette.toString();
	if (this.escesc)
	    data = data.replace("\033", "\\e");
	OutputStream out = System.out;
	if (this.file != null)
	    out = new FileOutputStream(this.file); 
	out.write(data.getBytes("UTF-8"));
	out.flush();
	if (out != System.out)
	    out.close();
    }
