Program: 187969
Project: 187969
Buggy source:
/** 
 * Import the pony from file
 * @return  The pony
 */
public Pony importPony(){
  if (this.version == VERSION_COWSAY)   return this.importCow();
  boolean[] plain=new boolean[9];
  Color[] colours=new Color[256];
  boolean[] format=plain;
  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);
  InputStream in=System.in;
  if (this.file != null)   in=new BufferedInputStream(new FileInputStream(this.file));
  boolean dollar=false;
  boolean escape=false;
  boolean csi=false;
  boolean osi=false;
  int[] buf=new int[256];
  int ptr=0;
  int dollareql=-1;
  int width=0;
  int curwidth=0;
  int height=1;
  LinkedList<Object> items=new LinkedList<Object>();
  String comment=null;
  String[][] tags=null;
  int tagptr=0;
  int[] unmetabuf=new int[4];
  int unmetaptr=0;
  unmetabuf[unmetaptr++]=in.read();
  unmetabuf[unmetaptr++]=in.read();
  unmetabuf[unmetaptr++]=in.read();
  unmetabuf[unmetaptr++]=in.read();
  if ((unmetabuf[0] == '$') && (unmetabuf[1] == '$') && (unmetabuf[2] == '$')&& (unmetabuf[3] == '\n')) {
    unmetaptr=0;
    byte[] data=new byte[256];
    int d=0;
    while ((d=in.read()) != -1) {
      if (ptr == data.length)       System.arraycopy(data,0,data=new byte[ptr << 1],0,ptr);
      data[ptr++]=(byte)d;
      if ((ptr >= 5) && (data[ptr - 1] == '\n') && (data[ptr - 2] == '$')&& (data[ptr - 3] == '$')&& (data[ptr - 4] == '$')&& (data[ptr - 5] == '\n')) {
        ptr-=5;
        break;
      }
      if ((ptr == 4) && (data[ptr - 1] == '\n') && (data[ptr - 2] == '$')&& (data[ptr - 3] == '$')&& (data[ptr - 4] == '$')) {
        ptr-=4;
        break;
      }
    }
    if (d == -1)     throw new RuntimeException("String_Node_Str");
    String[] code=(new String(data,0,ptr,"String_Node_Str")).split("String_Node_Str");
    StringBuilder commentbuf=new StringBuilder();
    for (    String line : code) {
      int colon=line.indexOf(':');
      boolean istag=colon > 0;
      String name=null, value=null;
      block: {
        if (istag) {
          istag=false;
          name=line.substring(0,colon);
          value=line.substring(colon + 1);
          char c;
          for (int i=0, n=name.length(); i < n; i++)           if ((c=name.charAt(i)) != ' ')           if (('A' > c) || (c > 'Z'))           break block;
          istag=true;
        }
      }
      if (istag) {
        if (tags == null)         tags=new String[32][];
 else         if (tagptr == tags.length)         System.arraycopy(tags,0,tags=new String[tagptr << 1],0,tagptr);
        tags[tagptr++]=new String[]{name.trim(),value.trim()};
      }
 else {
        commentbuf.append(line);
        commentbuf.append('\n');
      }
    }
    ptr=0;
    comment=commentbuf.toString();
    while ((ptr < comment.length()) && (comment.charAt(ptr) == '\n'))     ptr++;
    if (ptr > 0) {
      comment=comment.substring(ptr);
      ptr=0;
    }
    if (comment.isEmpty())     comment=null;
    if ((tags != null) && (tagptr < tags.length))     System.arraycopy(tags,0,tags=new String[tagptr],0,tagptr);
  }
  for (int d=0, stored=-1, c; ; ) {
    if (unmetaptr > 0) {
      d=unmetabuf[3 - --unmetaptr];
      if (d == -1)       break;
    }
 else     if ((d=stored) != -1)     stored=-1;
 else     if ((d=in.read()) == -1)     break;
    if (((c=d) & 0x80) == 0x80) {
      int n=0;
      while ((c & 0x80) == 0x80) {
        c<<=1;
        n++;
      }
      c=(c & 255) >> n;
      while (((d=in.read()) & 0xC0) == 0x80)       c=(c << 6) | (d & 0x3F);
      stored=d;
    }
    if (dollar)     if ((d == '\033') && !escape)     escape=true;
 else     if ((d == '$') && !escape) {
      dollar=false;
      if (dollareql == -1) {
        int[] _name=new int[ptr];
        System.arraycopy(buf,0,_name,0,_name.length);
        String name=utf32to16(_name);
        if (name.equals("String_Node_Str")) {
          curwidth++;
          items.add(new Pony.Cell(this.ignorelink ? ' ' : Pony.Cell.NNE_SSW,null,null,plain));
        }
 else         if (name.equals("String_Node_Str")) {
          curwidth++;
          items.add(new Pony.Cell(this.ignorelink ? ' ' : Pony.Cell.NNW_SSE,null,null,plain));
        }
 else         if (name.startsWith("String_Node_Str") == false)         items.add(new Pony.Recall(name,foreground,background,format));
 else         if (this.ignoreballoon == false) {
          String[] parts=(name.substring("String_Node_Str".length()) + "String_Node_Str").split("String_Node_Str");
          Integer h=parts[1].isEmpty() ? null : new Integer(parts[1]);
          int justify=Pony.Balloon.NONE;
          if (parts[0].contains("String_Node_Str"))           justify=Pony.Balloon.LEFT;
 else           if (parts[0].contains("String_Node_Str"))           justify=Pony.Balloon.RIGHT;
 else           if (parts[0].contains("String_Node_Str"))           justify=Pony.Balloon.CENTRE;
 else           items.add(new Pony.Balloon(null,null,parts[0].isEmpty() ? null : new Integer(parts[0]),h,null,null,Pony.Balloon.NONE));
          if (justify != Pony.Balloon.NONE) {
            parts=parts[0].replace('l',',').replace('r',',').replace('c',',').split("String_Node_Str");
            int part0=Integer.parseInt(parts[0]), part1=Integer.parseInt(parts[1]);
            items.add(new Pony.Balloon(new Integer(part0),null,new Integer(part1 - part0 + 1),h,null,null,justify));
          }
        }
      }
 else {
        int[] name=new int[dollareql];
        System.arraycopy(buf,0,name,0,name.length);
        int[] value=new int[ptr - dollareql - 1];
        System.arraycopy(buf,dollareql + 1,value,0,value.length);
        items.add(new Pony.Recall(utf32to16(name),utf32to16(value)));
      }
      ptr=0;
      dollareql=-1;
    }
 else {
      escape=false;
      if (ptr == buf.length)       System.arraycopy(buf,0,buf=new int[ptr << 1],0,ptr);
      if ((dollareql == -1) && (d == '='))       dollareql=ptr;
      buf[ptr++]=d;
    }
 else     if (escape)     if (osi)     if (ptr > 0) {
      buf[ptr++ - 1]=d;
      if (ptr == 8) {
        ptr=0;
        osi=escape=false;
        int index=(buf[0] < 'A') ? (buf[0] & 15) : ((buf[0] ^ '@') + 9);
        int red=(buf[1] < 'A') ? (buf[1] & 15) : ((buf[1] ^ '@') + 9);
        red=(red << 4) | ((buf[2] < 'A') ? (buf[2] & 15) : ((buf[2] ^ '@') + 9));
        int green=(buf[3] < 'A') ? (buf[3] & 15) : ((buf[3] ^ '@') + 9);
        green=(green << 4) | ((buf[4] < 'A') ? (buf[4] & 15) : ((buf[4] ^ '@') + 9));
        int blue=(buf[5] < 'A') ? (buf[5] & 15) : ((buf[5] ^ '@') + 9);
        blue=(blue << 4) | ((buf[6] < 'A') ? (buf[6] & 15) : ((buf[6] ^ '@') + 9));
        colours[index]=new Color(red,green,blue);
      }
    }
 else     if (ptr < 0) {
      if (~ptr == buf.length)       System.arraycopy(buf,0,buf=new int[~ptr << 1],0,~ptr);
      if (d == '\\') {
        ptr=~ptr;
        ptr--;
        if ((ptr > 8) && (buf[ptr] == '\033') && (buf[0] == ';')) {
          int[] _code=new int[ptr - 1];
          System.arraycopy(buf,1,_code,0,ptr - 1);
          String[] code=utf32to16(_code).split("String_Node_Str");
          if (code.length == 2) {
            int index=Integer.parseInt(code[0]);
            code=code[1].split("String_Node_Str");
            if ((code.length == 3) && (code[0].startsWith("String_Node_Str"))) {
              code[0]=code[0].substring(4);
              int red=Integer.parseInt(code[0],16);
              int green=Integer.parseInt(code[1],16);
              int blue=Integer.parseInt(code[2],16);
              colours[index]=new Color(red,green,blue);
            }
          }
        }
        ptr=0;
        osi=escape=false;
      }
 else {
        buf[~ptr]=d;
        ptr--;
      }
    }
 else     if (d == 'P')     ptr=1;
 else     if (d == '4')     ptr=~0;
 else {
      osi=escape=false;
      items.add(new Pony.Cell('\033',foreground,background,format));
      items.add(new Pony.Cell(']',foreground,background,format));
      items.add(new Pony.Cell(d,foreground,background,format));
    }
 else     if (csi) {
      if (ptr == buf.length)       System.arraycopy(buf,0,buf=new int[ptr << 1],0,ptr);
      buf[ptr++]=d;
      if ((('a' <= d) && (d <= 'z')) || (('A' <= d) && (d <= 'Z')) || (d == '~')) {
        csi=escape=false;
        ptr--;
        if (d == 'm') {
          int[] _code=new int[ptr];
          System.arraycopy(buf,0,_code,0,ptr);
          String[] code=utf32to16(_code).split("String_Node_Str");
          int xterm256=0;
          boolean back=false;
          for (          String seg : code) {
            int value=Integer.parseInt(seg);
            if (xterm256 == 2) {
              xterm256=0;
              if (back)               background=colours[value];
 else               foreground=colours[value];
            }
 else             if (value == 0) {
              for (int i=0; i < 9; i++)               format[i]=false;
              background=foreground=null;
            }
 else             if (xterm256 == 1)             xterm256=value == 5 ? 2 : 0;
 else             if (value < 10)             format[value - 1]=true;
 else             if ((20 < value) && (value < 30))             format[value - 21]=false;
 else             if (value == 39)             foreground=null;
 else             if (value == 49)             background=null;
 else             if (value < 38)             foreground=colours[value - 30];
 else             if (value < 48)             background=colours[value - 40];
 else             if (value == 38)             xterm256=1;
 else             if (value == 48)             xterm256=1;
            if (xterm256 == 1)             back=value == 48;
          }
        }
        ptr=0;
      }
    }
 else     if (d == '[') {
      csi=true;
      ptr=0;
    }
 else     if (d == ']')     osi=true;
 else {
      escape=false;
      items.add(new Pony.Cell('\033',foreground,background,format));
      items.add(new Pony.Cell(d,foreground,background,format));
      curwidth+=2;
    }
 else     if (d == '\033')     escape=true;
 else     if (d == '$')     dollar=true;
 else     if (d == '\n') {
      if (width < curwidth)       width=curwidth;
      curwidth=0;
      height=0;
      items.add(null);
    }
 else {
      boolean combining=false;
      if ((0x0300 <= c) && (c <= 0x036F))       combining=true;
      if ((0x20D0 <= c) && (c <= 0x20FF))       combining=true;
      if ((0x1DC0 <= c) && (c <= 0x1DFF))       combining=true;
      if ((0xFE20 <= c) && (c <= 0xFE2F))       combining=true;
      if (combining)       items.add(new Pony.Combining(c,foreground,background,format));
 else {
        curwidth++;
        Color fore=foreground == null ? colours[7] : foreground;
        if (c == '▀')         items.add(new Pony.Cell(Pony.Cell.PIXELS,fore,background,format));
 else         if (c == '▄')         items.add(new Pony.Cell(Pony.Cell.PIXELS,background,fore,format));
 else         if (c == '█')         items.add(new Pony.Cell(Pony.Cell.PIXELS,fore,fore,format));
 else         if (c == ' ')         items.add(new Pony.Cell(Pony.Cell.PIXELS,background,background,format));
 else         items.add(new Pony.Cell(c,foreground,background,format));
      }
    }
  }
  if (in != System.in)   in.close();
  Pony pony=new Pony(height,width,comment,tags);
  int y=0, x=0;
  Pony.Meta[] metabuf=new Pony.Meta[256];
  int metaptr=0;
  for (  Object obj : items)   if (obj == null) {
    if (metaptr != 0) {
      Pony.Meta[] metacell=new Pony.Meta[metaptr];
      System.arraycopy(metabuf,0,metacell,0,metaptr);
      pony.matrix[y][x]=metacell;
      metaptr=0;
    }
    y++;
    x=0;
  }
 else   if (obj instanceof Pony.Cell) {
    if (metaptr != 0) {
      Pony.Meta[] metacell=new Pony.Meta[metaptr];
      System.arraycopy(metabuf,0,metacell,0,metaptr);
      pony.matrix[y][x]=metacell;
      metaptr=0;
    }
    Pony.Cell cell=(Pony.Cell)obj;
    pony.matrix[y][x++]=cell;
  }
 else {
    Pony.Meta meta=(Pony.Meta)obj;
    if (metaptr == metabuf.length)     System.arraycopy(metabuf,0,metabuf=new Pony.Meta[metaptr << 1],0,metaptr);
    metabuf[metaptr++]=meta;
  }
  if (metaptr != 0) {
    Pony.Meta[] metacell=new Pony.Meta[metaptr];
    System.arraycopy(metabuf,0,metacell,0,metaptr);
    pony.matrix[y][x]=metacell;
    metaptr=0;
  }
  return pony;
}

Fixed version (ground truth):
/** 
 * Import the pony from file
 * @return  The pony
 */
public Pony importPony(){
  if (this.version == VERSION_COWSAY)   return this.importCow();
  boolean[] plain=new boolean[9];
  Color[] colours=new Color[256];
  boolean[] format=plain;
  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);
  InputStream in=System.in;
  if (this.file != null)   in=new BufferedInputStream(new FileInputStream(this.file));
  boolean dollar=false;
  boolean escape=false;
  boolean csi=false;
  boolean osi=false;
  int[] buf=new int[256];
  int ptr=0;
  int dollareql=-1;
  int width=0;
  int curwidth=0;
  int height=1;
  LinkedList<Object> items=new LinkedList<Object>();
  String comment=null;
  String[][] tags=null;
  int tagptr=0;
  int[] unmetabuf=new int[4];
  int unmetaptr=0;
  unmetabuf[unmetaptr++]=in.read();
  unmetabuf[unmetaptr++]=in.read();
  unmetabuf[unmetaptr++]=in.read();
  unmetabuf[unmetaptr++]=in.read();
  if ((unmetabuf[0] == '$') && (unmetabuf[1] == '$') && (unmetabuf[2] == '$')&& (unmetabuf[3] == '\n')) {
    unmetaptr=0;
    byte[] data=new byte[256];
    int d=0;
    while ((d=in.read()) != -1) {
      if (ptr == data.length)       System.arraycopy(data,0,data=new byte[ptr << 1],0,ptr);
      data[ptr++]=(byte)d;
      if ((ptr >= 5) && (data[ptr - 1] == '\n') && (data[ptr - 2] == '$')&& (data[ptr - 3] == '$')&& (data[ptr - 4] == '$')&& (data[ptr - 5] == '\n')) {
        ptr-=5;
        break;
      }
      if ((ptr == 4) && (data[ptr - 1] == '\n') && (data[ptr - 2] == '$')&& (data[ptr - 3] == '$')&& (data[ptr - 4] == '$')) {
        ptr-=4;
        break;
      }
    }
    if (d == -1)     throw new RuntimeException("String_Node_Str");
    String[] code=(new String(data,0,ptr,"String_Node_Str")).split("String_Node_Str");
    StringBuilder commentbuf=new StringBuilder();
    for (    String line : code) {
      int colon=line.indexOf(':');
      boolean istag=colon > 0;
      String name=null, value=null;
      block: {
        if (istag) {
          istag=false;
          name=line.substring(0,colon);
          value=line.substring(colon + 1);
          char c;
          for (int i=0, n=name.length(); i < n; i++)           if ((c=name.charAt(i)) != ' ')           if (('A' > c) || (c > 'Z'))           break block;
          istag=true;
        }
      }
      if (istag) {
        if (tags == null)         tags=new String[32][];
 else         if (tagptr == tags.length)         System.arraycopy(tags,0,tags=new String[tagptr << 1][],0,tagptr);
        tags[tagptr++]=new String[]{name.trim(),value.trim()};
      }
 else {
        commentbuf.append(line);
        commentbuf.append('\n');
      }
    }
    ptr=0;
    comment=commentbuf.toString();
    while ((ptr < comment.length()) && (comment.charAt(ptr) == '\n'))     ptr++;
    if (ptr > 0) {
      comment=comment.substring(ptr);
      ptr=0;
    }
    if (comment.isEmpty())     comment=null;
    if ((tags != null) && (tagptr < tags.length))     System.arraycopy(tags,0,tags=new String[tagptr][],0,tagptr);
  }
  for (int d=0, stored=-1, c; ; ) {
    if (unmetaptr > 0) {
      d=unmetabuf[3 - --unmetaptr];
      if (d == -1)       break;
    }
 else     if ((d=stored) != -1)     stored=-1;
 else     if ((d=in.read()) == -1)     break;
    if (((c=d) & 0x80) == 0x80) {
      int n=0;
      while ((c & 0x80) == 0x80) {
        c<<=1;
        n++;
      }
      c=(c & 255) >> n;
      while (((d=in.read()) & 0xC0) == 0x80)       c=(c << 6) | (d & 0x3F);
      stored=d;
    }
    if (dollar)     if ((d == '\033') && !escape)     escape=true;
 else     if ((d == '$') && !escape) {
      dollar=false;
      if (dollareql == -1) {
        int[] _name=new int[ptr];
        System.arraycopy(buf,0,_name,0,_name.length);
        String name=utf32to16(_name);
        if (name.equals("String_Node_Str")) {
          curwidth++;
          items.add(new Pony.Cell(this.ignorelink ? ' ' : Pony.Cell.NNE_SSW,null,null,plain));
        }
 else         if (name.equals("String_Node_Str")) {
          curwidth++;
          items.add(new Pony.Cell(this.ignorelink ? ' ' : Pony.Cell.NNW_SSE,null,null,plain));
        }
 else         if (name.startsWith("String_Node_Str") == false)         items.add(new Pony.Recall(name,foreground,background,format));
 else         if (this.ignoreballoon == false) {
          String[] parts=(name.substring("String_Node_Str".length()) + "String_Node_Str").split("String_Node_Str");
          Integer h=parts[1].isEmpty() ? null : new Integer(parts[1]);
          int justify=Pony.Balloon.NONE;
          if (parts[0].contains("String_Node_Str"))           justify=Pony.Balloon.LEFT;
 else           if (parts[0].contains("String_Node_Str"))           justify=Pony.Balloon.RIGHT;
 else           if (parts[0].contains("String_Node_Str"))           justify=Pony.Balloon.CENTRE;
 else           items.add(new Pony.Balloon(null,null,parts[0].isEmpty() ? null : new Integer(parts[0]),h,null,null,Pony.Balloon.NONE));
          if (justify != Pony.Balloon.NONE) {
            parts=parts[0].replace('l',',').replace('r',',').replace('c',',').split("String_Node_Str");
            int part0=Integer.parseInt(parts[0]), part1=Integer.parseInt(parts[1]);
            items.add(new Pony.Balloon(new Integer(part0),null,new Integer(part1 - part0 + 1),h,null,null,justify));
          }
        }
      }
 else {
        int[] name=new int[dollareql];
        System.arraycopy(buf,0,name,0,name.length);
        int[] value=new int[ptr - dollareql - 1];
        System.arraycopy(buf,dollareql + 1,value,0,value.length);
        items.add(new Pony.Store(utf32to16(name),utf32to16(value)));
      }
      ptr=0;
      dollareql=-1;
    }
 else {
      escape=false;
      if (ptr == buf.length)       System.arraycopy(buf,0,buf=new int[ptr << 1],0,ptr);
      if ((dollareql == -1) && (d == '='))       dollareql=ptr;
      buf[ptr++]=d;
    }
 else     if (escape)     if (osi)     if (ptr > 0) {
      buf[ptr++ - 1]=d;
      if (ptr == 8) {
        ptr=0;
        osi=escape=false;
        int index=(buf[0] < 'A') ? (buf[0] & 15) : ((buf[0] ^ '@') + 9);
        int red=(buf[1] < 'A') ? (buf[1] & 15) : ((buf[1] ^ '@') + 9);
        red=(red << 4) | ((buf[2] < 'A') ? (buf[2] & 15) : ((buf[2] ^ '@') + 9));
        int green=(buf[3] < 'A') ? (buf[3] & 15) : ((buf[3] ^ '@') + 9);
        green=(green << 4) | ((buf[4] < 'A') ? (buf[4] & 15) : ((buf[4] ^ '@') + 9));
        int blue=(buf[5] < 'A') ? (buf[5] & 15) : ((buf[5] ^ '@') + 9);
        blue=(blue << 4) | ((buf[6] < 'A') ? (buf[6] & 15) : ((buf[6] ^ '@') + 9));
        colours[index]=new Color(red,green,blue);
      }
    }
 else     if (ptr < 0) {
      if (~ptr == buf.length)       System.arraycopy(buf,0,buf=new int[~ptr << 1],0,~ptr);
      if (d == '\\') {
        ptr=~ptr;
        ptr--;
        if ((ptr > 8) && (buf[ptr] == '\033') && (buf[0] == ';')) {
          int[] _code=new int[ptr - 1];
          System.arraycopy(buf,1,_code,0,ptr - 1);
          String[] code=utf32to16(_code).split("String_Node_Str");
          if (code.length == 2) {
            int index=Integer.parseInt(code[0]);
            code=code[1].split("String_Node_Str");
            if ((code.length == 3) && (code[0].startsWith("String_Node_Str"))) {
              code[0]=code[0].substring(4);
              int red=Integer.parseInt(code[0],16);
              int green=Integer.parseInt(code[1],16);
              int blue=Integer.parseInt(code[2],16);
              colours[index]=new Color(red,green,blue);
            }
          }
        }
        ptr=0;
        osi=escape=false;
      }
 else {
        buf[~ptr]=d;
        ptr--;
      }
    }
 else     if (d == 'P')     ptr=1;
 else     if (d == '4')     ptr=~0;
 else {
      osi=escape=false;
      items.add(new Pony.Cell('\033',foreground,background,format));
      items.add(new Pony.Cell(']',foreground,background,format));
      items.add(new Pony.Cell(d,foreground,background,format));
    }
 else     if (csi) {
      if (ptr == buf.length)       System.arraycopy(buf,0,buf=new int[ptr << 1],0,ptr);
      buf[ptr++]=d;
      if ((('a' <= d) && (d <= 'z')) || (('A' <= d) && (d <= 'Z')) || (d == '~')) {
        csi=escape=false;
        ptr--;
        if (d == 'm') {
          int[] _code=new int[ptr];
          System.arraycopy(buf,0,_code,0,ptr);
          String[] code=utf32to16(_code).split("String_Node_Str");
          int xterm256=0;
          boolean back=false;
          for (          String seg : code) {
            int value=Integer.parseInt(seg);
            if (xterm256 == 2) {
              xterm256=0;
              if (back)               background=colours[value];
 else               foreground=colours[value];
            }
 else             if (value == 0) {
              for (int i=0; i < 9; i++)               format[i]=false;
              background=foreground=null;
            }
 else             if (xterm256 == 1)             xterm256=value == 5 ? 2 : 0;
 else             if (value < 10)             format[value - 1]=true;
 else             if ((20 < value) && (value < 30))             format[value - 21]=false;
 else             if (value == 39)             foreground=null;
 else             if (value == 49)             background=null;
 else             if (value < 38)             foreground=colours[value - 30];
 else             if (value < 48)             background=colours[value - 40];
 else             if (value == 38)             xterm256=1;
 else             if (value == 48)             xterm256=1;
            if (xterm256 == 1)             back=value == 48;
          }
        }
        ptr=0;
      }
    }
 else     if (d == '[') {
      csi=true;
      ptr=0;
    }
 else     if (d == ']')     osi=true;
 else {
      escape=false;
      items.add(new Pony.Cell('\033',foreground,background,format));
      items.add(new Pony.Cell(d,foreground,background,format));
      curwidth+=2;
    }
 else     if (d == '\033')     escape=true;
 else     if (d == '$')     dollar=true;
 else     if (d == '\n') {
      if (width < curwidth)       width=curwidth;
      curwidth=0;
      height=0;
      items.add(null);
    }
 else {
      boolean combining=false;
      if ((0x0300 <= c) && (c <= 0x036F))       combining=true;
      if ((0x20D0 <= c) && (c <= 0x20FF))       combining=true;
      if ((0x1DC0 <= c) && (c <= 0x1DFF))       combining=true;
      if ((0xFE20 <= c) && (c <= 0xFE2F))       combining=true;
      if (combining)       items.add(new Pony.Combining(c,foreground,background,format));
 else {
        curwidth++;
        Color fore=foreground == null ? colours[7] : foreground;
        if (c == '▀')         items.add(new Pony.Cell(Pony.Cell.PIXELS,fore,background,format));
 else         if (c == '▄')         items.add(new Pony.Cell(Pony.Cell.PIXELS,background,fore,format));
 else         if (c == '█')         items.add(new Pony.Cell(Pony.Cell.PIXELS,fore,fore,format));
 else         if (c == ' ')         items.add(new Pony.Cell(Pony.Cell.PIXELS,background,background,format));
 else         items.add(new Pony.Cell(c,foreground,background,format));
      }
    }
  }
  if (in != System.in)   in.close();
  Pony pony=new Pony(height,width,comment,tags);
  int y=0, x=0;
  Pony.Meta[] metabuf=new Pony.Meta[256];
  int metaptr=0;
  for (  Object obj : items)   if (obj == null) {
    if (metaptr != 0) {
      Pony.Meta[] metacell=new Pony.Meta[metaptr];
      System.arraycopy(metabuf,0,metacell,0,metaptr);
      pony.metamatrix[y][x]=metacell;
      metaptr=0;
    }
    y++;
    x=0;
  }
 else   if (obj instanceof Pony.Cell) {
    if (metaptr != 0) {
      Pony.Meta[] metacell=new Pony.Meta[metaptr];
      System.arraycopy(metabuf,0,metacell,0,metaptr);
      pony.metamatrix[y][x]=metacell;
      metaptr=0;
    }
    Pony.Cell cell=(Pony.Cell)obj;
    pony.matrix[y][x++]=cell;
  }
 else {
    Pony.Meta meta=(Pony.Meta)obj;
    if (metaptr == metabuf.length)     System.arraycopy(metabuf,0,metabuf=new Pony.Meta[metaptr << 1],0,metaptr);
    metabuf[metaptr++]=meta;
  }
  if (metaptr != 0) {
    Pony.Meta[] metacell=new Pony.Meta[metaptr];
    System.arraycopy(metabuf,0,metacell,0,metaptr);
    pony.metamatrix[y][x]=metacell;
    metaptr=0;
  }
  return pony;
}