HashMap map = new HashMap();

void   setup(){
  size(400, 400); 

  //  map.put
  map.put("a",new letter(se,fb,nw,fb));
  map.put("b",new letter(fb,sw,fb,fb));
  map.put("c",new letter(se,nw,ne,sw));
  map.put("d",new letter(ne,sw,se,nw));
  map.put("e",new letter(se,fb,ne,fb));
  map.put("f",new letter(se,fb,fb,eb));
  map.put("g",new letter(se,nw,ne,fb));
  map.put("h",new letter(sw,se,nw,ne));
  map.put("i",new letter(sw,eb,ne,sw));
  map.put("j",new letter(eb,fb,ne,nw));
  map.put("k",new letter(fb,nw,fb,sw));
  map.put("l",new letter(fb,eb,fb,fb));
  map.put("m",new letter(sw,se,fb,fb));
  map.put("n",new letter(sw,fb,fb,ne));
  map.put("o",new letter(se,sw,ne,nw));
  map.put("p",new letter(fb,sw,fb,eb));
  map.put("q",new letter(se,sw,ne,fb));
  map.put("r",new letter(fb,sw,fb,sw));
  map.put("s",new letter(se,nw,se,nw));
  map.put("t",new letter(fb,fb,se,sw));
  map.put("u",new letter(fb,fb,fb,nw));
  map.put("v",new letter(fb,fb,ne,nw));
  map.put("w",new letter(fb,fb,nw,ne));
  map.put("x",new letter(ne,nw,se,sw));
  map.put("y",new letter(ne,fb,eb,fb));
  map.put("z",new letter(fb,nw,se,fb));
  map.put(":",new symbol(nw,nw));
  map.put("!",new symbol(fb,ne));
  map.put(".",new symbol(eb,fb));
  map.put("/",new letter(eb,se,se,nw));
  map.put(" ",new symbol(eb,eb));
  map.put(",",new symbol(eb,se));
  map.put("?",new letter(se,sw,eb,sw));
  map.put(";",new symbol(fb,se));



}

float resetleft = 10;
float maxleft = 380;
String buffer = "abcdefghijklm\nnopqrstuvwxyz\n,.?!\n\nthe quick brown\nfox jumps over\nthe lazy dog\n\nclick here\n       and type";
boolean virgin = true;

String se = "se";
String ne = "ne";
String sw = "sw";
String nw = "nw";
String fb = "fb";
String eb = "eb";


void keyPressed(){
  if(virgin) {
    buffer = "";
    virgin = false; 
  }
  if(key ==8 ){
    if(buffer.length() > 0){
      buffer = buffer.substring(0,buffer.length()-1); 
    }
  } 
  else {

    String hit = String.valueOf(key).toLowerCase();
    buffer += hit;
  }
  loop();
}


interface alphasymbol{
  void pos(float pleft,float ptop,float psize);
  float width();
  void draw();
}


class letter  implements alphasymbol{
  chunk c0,c1,c2,c3;
  float size, top, left;
  letter(String p0,String p1,String p2,String p3){
    c0 = factory(p0);
    c1 = factory(p1);
    c2 = factory(p2);
    c3 = factory(p3);       

    //twixt 0 and 1  
    if(c1.touchside(3)) c0.skip(1);
    if(c0.touchside(1)) c1.skip(3);
    //twixt 0 and 2
    if(c2.touchside(0)) c0.skip(2);
    if(c0.touchside(2)) c2.skip(0);
    //twixt 1 and 3
    if(c3.touchside(0)) c1.skip(2);
    if(c1.touchside(2)) c3.skip(0);
    //twixt 2 and 3
    if(c3.touchside(3)) c2.skip(1);
    if(c2.touchside(1)) c3.skip(3);


  }
  void pos(float pleft,float ptop,float psize){
    size = psize;
    left = pleft;
    top = ptop;
    c0.pos(left,top,size);
    c1.pos(left+size,top,size);
    c2.pos(left,top+size,size);
    c3.pos(left+size,top+size,size);
  }

  void draw(){

    noStroke();

    c0.drawSpace();
    c1.drawSpace();
    c2.drawSpace();
    c3.drawSpace();

    stroke(0);
    strokeWeight(3);
    c0.drawLines();
    c1.drawLines();
    c2.drawLines();
    c3.drawLines();

  }
  float width(){
    return size * 2;
  }

}





class symbol implements alphasymbol{
  chunk c0,c1;
  float size, top, left;
  symbol(String p0,String p1){
    c0 = factory(p0);
    c1 = factory(p1);
    //twixt 0 and 1  
    if(c1.touchside(0)) c0.skip(2);
    if(c0.touchside(2)) c1.skip(0);
  }
  void pos(float pleft,float ptop,float psize){
    size = psize;
    left = pleft;
    top = ptop;
    c0.pos(left,top,size);
    c1.pos(left,top+size,size);
  }

  void draw(){
    noStroke();

    c0.drawSpace();
    c1.drawSpace();

    stroke(0);
    strokeWeight(3);
    c0.drawLines();
    c1.drawLines();

  }
  float width(){
    return size;
  }

}

void draw() { 
  background(204);
  noStroke();

  float left = resetleft;
  float size = 10;
  float top = 10;



  // String alpha = "http://kisrael.com\nthe quick brown fox jumps over the lazy dog";
  //  String alpha = "not the most readable font";
  String alpha = buffer;

  char arr[] = new char[1];
  for(int i = 0; i < alpha.length();i++){

    String key = alpha.substring(i,i+1);

    if(key.equals("\n")){
      left = resetleft;
      top += size*3; 

    } 
    else {

      alphasymbol duh = (alphasymbol) map.get(key);
      if(duh != null){
        duh.pos(left,top,size);
        duh.draw();

        left += duh.width()+(size*.75);
        /*        if(left > maxleft){
         left = resetleft;
         top += size*3; 
         }*/
      }
    }
  }

  noLoop();  
}


chunk factory(String s){
  chunk c = null;
  if(s.equals(nw)){
    c = new northwest();
  }
  if(s.equals(ne)){
    c = new northeast();
  }
  if(s.equals(se)){
    c = new southeast();
  }
  if(s.equals(sw)){
    c = new southwest();
  }
  if(s.equals(fb)){
    c = new fillblock();
  }
  if(s.equals(eb)){
    c = new emptyblock();
  }


  return c;
}

void mouseReleased(){
   buffer="";
   loop();
  
}


public abstract class chunk {
  float size, top, left;
  boolean skip[] = new boolean[4];

  void skip(int side){
    skip[side] = true;
  }

  void pos(float pleft,float ptop, float psize){
    size = psize;
    top = ptop;
    left = pleft;
  }
  abstract void drawLines();
  abstract void drawSpace();

  abstract boolean touchside(int side); 
}


public class northwest extends chunk {
  void drawSpace(){
    triangle(left,top,left+size,top,left,top+size);
  }
  void drawLines(){
    line(left+size,top,left,top+size);
    if(! skip[0]) line(left,top,left+size,top);
    if(! skip[3]) line(left,top,left,top+size);
  }
  boolean touchside(int side){
    if(side ==0 || side == 3) return true;
    return false;
  }
}


public class northeast extends chunk {
  void drawSpace(){
    triangle(left,top,left+size,top,left+size,top+size);
  }
  void drawLines(){
    line(left,top,left+size,top+size);
    if(! skip[0]) line(left,top,left+size,top);
    if(! skip[1]) line(left+size,top,left+size,top+size);
  }
  boolean touchside(int side){
    if(side ==0 || side == 1) return true;
    return false;
  }
}



public class southwest extends chunk {
  void drawSpace(){
    triangle(left,top,left,top+size,left+size,top+size);
  }
  void drawLines(){
    line(left,top,left+size,top+size);
    if(! skip[2]) line(left,top+size,left+size,top+size);
    if(! skip[3]) line(left,top,left,top+size);
  }
  boolean touchside(int side){
    if(side ==2 || side == 3) return true;
    return false;
  }
}


public class southeast extends chunk {
  void drawSpace(){
    triangle(left,top+size,left+size,top,left+size,top+size);
  }
  void drawLines(){
    line(left,top+size,left+size,top);

    if(! skip[1]) line(left+size,top,left+size,top+size);

    if(! skip[2]) line(left,top+size,left+size,top+size);

  }
  boolean touchside(int side){
    if(side ==1 || side == 2) return true;
    return false;
  }
}


public class fillblock extends chunk {
  void drawSpace(){
    rect(left,top,size,size);
  }
  void drawLines(){
    if(! skip[0]) line(left,top,left+size,top);
    if(! skip[1]) line(left+size,top,left+size,top+size);
    if(! skip[2]) line(left,top+size,left+size,top+size);
    if(! skip[3]) line(left,top,left,top+size);
  }
  boolean touchside(int side){

    return true;
  }
}


public class emptyblock extends chunk {
  void drawSpace(){
  }
  void drawLines(){

  }
  boolean touchside(int side){
    return false;
  }
}