/*
The code is available only to persons
currently affiliated with any of the following,
      o Universities and schools
      o Non-commercial research organizations
      o Registered not-for-profit organizations
      o Registered charities
For these people, the license is of the form of
the GNU Public License version 2.  The restrictions
must remain attached to this and any subsequently derived code.
All other people have no implicit right to use, read, or copy
this software unless granted by Mr. Deck
THIS SOFTWARE IS PROVIDED "AS IS" AND MR. DECK
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, HE
MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANT-
ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE
OF THE LICENSED SOFTWARE AND DOCUMENTATION WILL NOT
INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR
*/

import java.util.*;
import java.awt.*;

public class textArea extends Canvas {
icontext it;
Graphics g=null;
boolean east  = true;
boolean south = false;
boolean north = false;
boolean west  = false;
int curX=0, curY=0;
int ox=-20, oy=-20;
int okey=0;
int startX, startY;  // start point of key typing
Character[][] text = new Character[50][50];
byte[] buf = new byte[7];

  public textArea(icontext i){
	super();
	it = i;
	setBackground(Color.white);
	setForeground(Color.black);
        if(it.curChar !=null){
           for(int j=0;j<50;j++)
              for(int k=0;k<50;k++)
                     text[j][k] = i.curChar;
        } 
        else 
         System.out.println("null curChar");
	buf[0] = 0; //len_a
        buf[1] = 5; //len_b
	buf[2] = 0; //type
	buf[3] = 0; //id
  }

  public void setStartPoint(){
	startX = curX;
	startY = curY;
  }

  private void backReturn(){
        if (east && (!south) && (!north) && curY > 0) { // east
          if (curX == 0) {
            curX = 490;
            curY -= 10;
          }
        }
        else if (west && (!south) && (!north) && curY < 490) { // wes
          if (curX == 490) {
              curX = 0;
              curY += 10;
          }
        }
        else if (south && (!west) && (!east) && curX < 490) { // sout
          if (curY == 0) {
            curY = 490;
            curX += 10;
          }
        }
        else if (north && (!east) && (!west) && curX > 0){ // north
          if (curY == 490) {
            curY = 0;
            curX -= 10;
          }
        }
        else if (east && south) { // south-east
          if ((curX==490) && (curY==0)) {}
          else {
            if (curY == 0) {
                  curY = 490 - curX - 10;
                  curX = 490;
                }
                else if (curX == 0) {
                  curX = 490 - curY + 10;
                  curY = 490;
                }
          }
        }
        else if (east && north){ // north-east
          if ((curX==0) && (curY==0)) {}
          else {
                if (curX == 0) {
                  curX = curY - 10;
                  curY = 0;
                }
                else if (curY == 490) {
                  curY = curX - 10;
                  curX = 490;
                }
          }
        }
       else if (west && south) { // south-west
          if ((curX == 490) && (curY == 490)) {}
          else {
             if (curX == 490) {
                  curX = curY + 10;
                  curY = 490;
             }
             else if (curY == 0) {
                  curY = curX + 10;
                  curX = 0;
             }
          }
        }
        else if (west && north) { // north-west
          if ((curX == 0) && (curY == 490)) {}
          else {
              if (curY == 490) {
                  curY = 490 - curX + 10;
                  curX = 0;
              }
              else if (curX == 490) {
                  curX = 490 - curY - 10;
                  curY = 0;
              }
          }
       }
   }

   private void carraigeReturn(){
	if (east && (!south) && (!north) && curY < 490) { // east
	      curX = startX;
	      curY += 10;
	      startY = curY;
	}
	else if (west && (!south) && (!north) && curY > 0) { // west
	      curX = startX;
	      curY -= 10;
	      startY = curY;
	}
	else if (south && (!west) && (!east) && curX > 0) { // south
	    curY = startY;
	    curX -= 10;
	    startX = curX;
	}
	else if (north && (!east) && (!west) && curX < 490){// north
	    curY = startY;
	    curX += 10;
	    startX = curX;
	}
	else if (east && south) { // south-east
	  curX = startX;
	  if (startY <= 490) 
	    startY += 10;
	  curY = startY;
	}
	else if (east && north){ // north-east
	  if (startY <= 490) 
	    startY += 10;
	  else if (startY >= 500) { // corner situation
	    startY = 500;
	    startX += 10;
	  }
	  curX = startX;
	  curY = startY;
	}
	else if (west && south) { // south-west
	  if (startY > 0) 
	    startY -= 10;
	  else if (startY <= 0) { // corner
	    startY = 0;
	    startX -= 10;
	  }
	  curX = startX;
	  curY = startY;
	}
	else if (west && north) { // north-west
	  if (startY > 0) 
	    startY -= 10;
	  curX = startX;
	  curY = startY;
	}
   }
   
   private 
    void next(boolean n,boolean s,boolean e,boolean w,boolean back){
     if (e && (!s) && (!n)) { // east
         if (curX < 490) 
           curX += 10;
	 else{ 
           if(back) backReturn();
           else carraigeReturn();
	 }
     }
     else if (w && (!s) && (!n)) { // west
         if(curX > 0) 
           curX -= 10;
	else{         
           if(back) backReturn();
           else carraigeReturn();
	}
     }
     else if (s && (!e) && (!w)) { // south
         if(curY < 490)  
           curY += 10;
   	 else{          
           if(back) backReturn();
           else carraigeReturn();
	 }
     }
     else if (n && (!e) && (!w)) { // north
         if(curY > 0)    
           curY -= 10;
   	 else{
           if(back) backReturn();
           else carraigeReturn();
	 }
     }
     else if (n && e) { // north-east
   	 if ((curX >= 490) || (curY <= 0)) {
           if(back) backReturn();
           else carraigeReturn();
	 }
	 else{
           curX += 10;
	   curY -= 10;
	 }
     }
     else if (s && e) { // south-east
         if ((curX >= 490) || (curY >= 490)) {
           if(back) backReturn();
           else carraigeReturn();
	 }
	 else {
           curX += 10;
	   curY += 10;
	 }
     }
     else if (n && w) { // north-west
        if ((curX <= 0) || (curY <= 0)){
           if(back) backReturn();
           else carraigeReturn();
	}
	else {
           curX -= 10;
	   curY -= 10;
	}
     }
     else if (s && w) { // south-west
         if ((curX <= 0) || (curY >= 490)) {
           if(back) backReturn();
           else carraigeReturn();
	 }
	 else {
	   curX -= 10;
	   curY += 10;
	 }
     }
   }

   public void setElement(int x,int y,int col,
				int row,Character c){
	 if(g!=null) g.setPaintMode();
	 if(g!=null) g.clearRect(x,y,10,10);
	 if(g!=null) g.setColor(Color.white);
	 if(g!=null) g.drawString(text[col][row].toString(),x,y+9);
	 if(g!=null) g.setColor(Color.black);
	 if(g!=null) g.drawString(c.toString(),x,y+9);
	 if(row>0){
	  if(g!=null) 
		g.drawString(text[col][row-1].toString(),x,y-1);
	 }
	 if(row<49){
	  if(g!=null) 
		g.drawString(text[col][row+1].toString(),x,y+19);
	 }
      text[Math.max(0,Math.min(49,col))]
          [Math.max(0,Math.min(49,row))] = (Character)c;
      if(it.da.img_g!=null){
        it.da.img_g.setColor((Color)(it.ctab.get(text[col][row])));
        // would stretch small image, but Mac Netscape VM won't allow it
      	//it.da.img_g.drawLine(col,row,col,row);
      	it.da.img_g.fillRect(x>>1,y>>1,5,5);
      }else{
	it.da.img_g = it.da.img.getGraphics();
      }
   }

   public boolean handleEvent(Event e){
     if(e.id==Event.MOUSE_DOWN ||
	 e.id==Event.MOUSE_DRAG ){
	if(okey>=0) hiLite(ox,oy,true);
	startX = curX = (e.x/10)*10;
	startY = curY = (e.y/10)*10;
	hiLite(curX,curY,false);
	okey  = 8;
	requestFocus(); 
     }
     else if(e.id == Event.KEY_PRESS){
	if(e.key == 10){      /* Return */
	    hiLite(ox,oy,true);
	    carraigeReturn();
	    hiLite(curX,curY,false);
	    okey  = 0;
	    return true;
	}
	else if(e.key == 8){  /* Backspace */
            buf[4] = (byte)(curX/10);
            buf[5] = (byte)(curY/10);
	    buf[6] = ' ';
            it.con.send(buf,7);
	    if(okey==8){
                hiLite(ox,oy,true);
		setElement(curX,curY,(int)buf[4],
                      (int)buf[5],new Character(' '));
      	        it.da.repaint(curX>>1,curY>>1,5,5);
	    }
	    if (east && (!north) && (!south))    
                 next(north,south,!east,!west,true);
            else if(west && (!north) && (!south))
                 next(north,south,!east,!west,true);
            else if(north && (!east) && (!west)) 
                 next(!north,!south,east,west,true);
            else if (south && (!east) && (!west))
                 next(!north,!south,east,west,true);
            else if ((north && east) || (north && west) 
                    || (south && east) || (south && west)) 
                 next(!north,!south,!east,!west,true);
	    if(okey!=8){
              hiLite(ox,oy,true);
	      setElement(curX,curY,curX/10,
                     curY/10,new Character(' '));
      	      it.da.repaint(curX>>1,curY>>1,5,5);
            }
	    hiLite(curX,curY,false);
	    okey = 8;
	    return true;
	}
	else if(e.key < 32 ) return true;
	else if(e.key == '<') e.key = ' ';
	else if(e.key == '"') e.key = '\'';

        buf[4] = (byte)(curX/10);
        buf[5] = (byte)(curY/10);
        buf[6] = (byte)(e.key);
        it.con.send(buf,7);
        hiLite(ox,oy,true);
	setElement(curX,curY,(int)buf[4],
             (int)buf[5],new Character((char)e.key));
      	it.da.repaint(curX>>1,curY>>1,5,5);
	next(north,south,east,west,false);
	hiLite(curX,curY,false);
	okey  = 0;
     }//END KEY_PRESSED
     else if(e.id == Event.KEY_ACTION){
            hiLite(ox, oy,true);
            if(e.key == Event.UP && curY > 0)  //up
                  curY -= 10;
            else if(e.key == Event.DOWN && curY < 490) //down
                  curY += 10;
            else if(e.key == Event.LEFT && curX > 0) //left
                  curX -= 10;
            else if(e.key == Event.RIGHT && curX < 490) //right
                  curX += 10;
            hiLite(curX, curY,false);
     }
     else if(e.id == Event.LOST_FOCUS){  
		hiLite(ox,oy,true);
		okey=-1;
     }
    return false;
  }
	
  public void paint(Graphics g){
    if(this.g==null) this.g = getGraphics();
    if(it.da.img_g==null) return; //sloppy but faster
    int r=0, c=0;
    g.clearRect(0,0,500,500);
    for(int x=0;x<500;x+=10,c=0,r++){
        for(int y=9;y<500;y+=10,c++){
          g.drawString(text[r][c].toString(),x,y); 
        }
    }
  }

  private void hiLite(int x, int y,boolean on){
     Graphics g = getGraphics();
     if(g!=null) {
	if(on){
		g.setColor(Color.white);
		g.fillRect(x,y,10,10);
	}else{
		g.setColor(Color.yellow);
		g.fillRect(x,y,10,10);
	}
	g.setColor(Color.black);
	int col = Math.max(0,Math.min(49,x/10));
	int row = Math.max(0,Math.min(49,y/10));
     	g.drawString(text[col][row].toString(),x,y+9); 
        g.dispose();
     }
     ox=x;
     oy=y;
  }
}

