import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.zip.*;

public  class glyphEdit extends Canvas implements Runnable{
 String  baseURL = null;
 glyphiti gl = null;
 Image       img = null;
 Thread        t = null;
 boolean    down;
 byte[][]  icon  = null;
 int          x1;
 int          y1;
 int         num;
 int WHITE;
 int BLACK;
 int    curColor;
 boolean macNets;

  public glyphEdit(int imgNum, glyphiti gl){ 
        this.num = imgNum;
	this.gl = gl;
 	down = false;
 	icon  = new byte[32][32];
 	x1 = -1;
 	y1 = -1;
 	WHITE = 64;
 	BLACK = 65;
 	curColor = WHITE;
	macNets = false;
        baseURL = "http://artcontext.org/act/01/glyphiti/";
	setBackground(Color.white);
	reshape(512,0,512,512); 
	for(int y=0;y<32;y++){
	  for(int x=0;x<32;x++){
		icon[y][x] = (byte)WHITE;
	  }
	}

	if(System.getProperty("java.vendor.url").indexOf("netscape")>=0 &&
	   System.getProperty("os.name").indexOf("Mac")>=0) macNets = true; 

	start();
  }

  public void start(){
     t = new Thread(this);
     //t.setPriority(Thread.MIN_PRIORITY);
     t.start();
  }
  public void stop(){
      if(t!=null) t.stop();
      t = null;
  }

  public void run(){
    if(macNets){
        // Grrrrr. 
        // No alternative because PixelGrabber doesn't work in Netscape 4.7 under MacOS
	String str = new String();
        DataInputStream din = null;
	int X=0,Y=0,y=0,curImg=0;
	try{
	   din = new DataInputStream(new GZIPInputStream((new URL(baseURL+"docs/kludge.php?num="+Integer.toString(num))).openStream()));
	   while((str = din.readLine())!=null){
                    if(str.charAt(0)=='#'){
                            curImg = Integer.parseInt(str.substring(2).trim());
                    }
                    else if(str.charAt(0)=='@'){
                           // just ignore the last modified date 
                    }else if(str.length()>0){
                           String pix = Long.toString(Long.parseLong(str.substring(0,str.length()-1),36),2)+
                                           (String)(str.substring(str.length()-1).equals("W")?"0":"1");
                           while(pix.length()<32){
                                  pix = "0"+pix;
                           }
                           for(int x=0;x<32;x++){
                                    if(pix.charAt(x) == '0') icon[y][x] = (byte)WHITE;
                                    else                     icon[y][x] = (byte)BLACK;
                           }
                           y++;
                    }
           }  
	}catch(Exception ee){
		ee.printStackTrace();
	}

    }else{
        java.awt.image.PixelGrabber pg;
        int [] iconBuf = new int[1024];
        int i = 0;
	int offx = (num%16)<<5;
        int offy = (num/16)<<5; 
        pg = new java.awt.image.PixelGrabber(gl.img,offx,offy,32,32,iconBuf,0,32);
        try{ 
		pg.grabPixels();
	}
        catch(InterruptedException e) 
	{ 
	     System.out.println(e+"ldScr"); 
	     iconBuf=null; 
	     return ; 
	}
        if((pg.status() & java.awt.image.ImageObserver.ABORT)!=0){
	     System.out.println("fail");
             iconBuf=null; 
             return ;
        }
        for(int y = 0; y<32; y++){
            for(int x = 0; x<32; x++)
            {
                    if(iconBuf[i++]==-1) icon[y][x]=(byte)WHITE;
                    else                 icon[y][x]=(byte)BLACK;
            }
        }      
     }
     repaint();
   }


   public boolean mouseMove(Event e, int X, int Y){
	gl.getAppletContext().showStatus("Changes are saved automatically");
	return true;
   }

   public boolean mouseUp(Event e, int X, int Y){
	// Convert icon to base36 to minimize data before sending
        // Use B or W for 32nd bit (+/- conflict in type long)
	byte[] linebuf = new byte[31];
        StringBuffer strBuf = new StringBuffer();
	for(int y=0;y<32;y++){
	     for(int x=0;x<31;x++){
	         if(icon[y][x]==BLACK){
		        linebuf[x] = (byte)'1';
		 }else{
			linebuf[x] = (byte)'0';
		 }
	     }
	     strBuf.append(Long.toString(Long.valueOf( new String(linebuf),2).longValue(),36)+
			                                       (String)(icon[y][31]==BLACK?"B":"W"));
        }
	new saver(baseURL+"docs/save.php?n="+Integer.toString(num)+"&m="+strBuf.toString());
        return true;
   }

  public boolean mouseDown(Event e, int X, int Y){
	int x = (X>>4);
	int y = (Y>>4);
	if(x<0 || x>31 || y<0 || y>31) return true;
	if(icon[y][x] == BLACK) icon[y][x] = (byte)WHITE;
	else                    icon[y][x] = (byte)BLACK;
	curColor = icon[y][x];
	x1 = x;
	y1 = y;
	repaint(x<<4,y<<4,16,16);
	return true;
  }

  public boolean mouseDrag(Event e, int x, int y){
     int xinc1,xinc2,yinc1,yinc2,num,numadd,numpixels,den;
     int x2 = (x>>4);
     int y2 = (y>>4);
     if(x2<0 || x2>31 || y2<0 || y2>31) return true;
     int deltax = Math.abs(x2 - x1);        // The difference between the x's
     int deltay = Math.abs(y2 - y1);        // The difference between the y's
     x = x1;                       // Start x off at the first pixel
     y = y1;                       // Start y off at the first pixel

     if (x2 >= x1)                 // The x-values are increasing
     {
       xinc1 = 1;
       xinc2 = 1;
     }
     else                          // The x-values are decreasing
     {
       xinc1 = -1;
       xinc2 = -1;
     }

     if (y2 >= y1)                 // The y-values are increasing
     {
       yinc1 = 1;
       yinc2 = 1;
     }
     else                          // The y-values are decreasing
     {
       yinc1 = -1;
       yinc2 = -1;
     }


     if (deltax >= deltay)         // There is at least one x-value for every y-value
     {
       xinc1 = 0;                  // Don't change the x when numerator >= denominator
       yinc2 = 0;                  // Don't change the y for every iteration
       den = deltax;
       num = deltax / 2;
       numadd = deltay;
       numpixels = deltax;         // There are more x-values than y-values
     }
     else                          // There is at least one y-value for every x-value
     {
       xinc2 = 0;                  // Don't change the x for every iteration
       yinc1 = 0;                  // Don't change the y when numerator >= denominator
       den = deltay;
       num = deltay / 2;
       numadd = deltax;
       numpixels = deltay;         // There are more y-values than x-values
     }

     for (int curpixel = 0; curpixel <= numpixels; curpixel++)
     {
       if(icon[y][x] != curColor){
           icon[y][x] = (byte)curColor;
           repaint(x<<4,y<<4,16,16);
       }    
       num += numadd;              // Increase the numerator by the top of the fraction
       if (num >= den)             // Check if numerator >= denominator
       {
         num -= den;               // Calculate the new numerator value
         x += xinc1;               // Change the x as appropriate
         y += yinc1;               // Change the y as appropriate
       }
       x += xinc2;                 // Change the x as appropriate
       y += yinc2;                 // Change the y as appropriate
     }
	x1 = x2;
	y1 = y2;
	return true;
   }

   public void paint(Graphics g){
	int X=0;
	int Y=0;
	for(int y=0;y<32;y++){
	  Y = y<<4;
	  for(int x=0;x<32;x++){
	        X = x<<4;
		if(icon[y][x] == BLACK) g.fillRect(X,Y,16,16);
		else                    g.clearRect(X,Y,16,16);
		
	  }
	}
   }
}

