/*
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.awt.*;
import java.util.*;

public class Viewer extends java.applet.Applet implements Runnable
{

boolean      wasrunning = true,           buffered = true,
                   fill = false,             cycle = false,	           
		ready[] = null,		  noscript = true,
		   down = false;

static final char col[]={'r','g','B','L','G','D','C','m','y','p','o','w','b','P','O'};

static final int icon[] = {
	0x8f9f9c31,0xe79f9c71,0xf3fffee3,0xf3f03f87,0xfbc607c7,0x7f0f81ff,0x1f3ffcff,0x867ffcff,
	0xb6738eff,0xfcc18675,0xfcc10261,0xfcc1837d,0x4e3c73f,0x4ffff3f,0xfc7ffe3b,  0xfc387e61,
	0xfe301ef3,0xff300cff,0xff100dff,0xc71819cf,0x879c7185,0xf9fe3f1,0x3f9fc7f9, 0xfecf9f7f,
	0xf8c01f1f,0xf1e07f87,0xe7ffffe3,0xe3c7baf1,0xcfcf98f9,0xcf9f9c7f,


	0x1c000007,0x81fffff7,0x2bff0073,0x5d807f1b,0x413fffcb,0x7f1fffe9,0x7f5ffff5,0x715ffff5,
	0x755ffff5,0x715ffff5,0x7f5ffff5,0x7f4ffff6,0x716ffffa,0x756ffffa,0x716ffffa,0x7f6ffffa,
	0x5577fffa,0x6a77fffa,0x5537fffa,0x68b7fff2,0x5507ff86,0x7fd1f830,0xb1000386,0x9ffff82e,
	0x32e,     0x49ffffae,0x59b6ddae,0x58000420,0x45fff597,0x54000417,


	0xffff5fff,0xf8ff4fff,0xfa1e6fff,0xfbe2e783,0xf9f8f037,0xfdfbfbe7,0xfdf01bef, 0xfde3c3ef,
	0xfdcff3df,0xfc1ff9df,0xf1bff81f,0x8fbffce1,0x7fbffefc,0x3fbffefe,0xcfbffef9, 0xe7bffef3,
	0xf99ffec7,0xfcdffc3f,0xfd0ff01f,0xfd8183df,0xfdec3bcf,0xf9e7f3ef,0xfbf3f7e7, 0xfbfbf7f7,
	0xf3e1e7f7,0xf71de003,0xf0feefff,0xf7fe6fff,0xffff4fff,0xffff1fff};

int               tSzUsr = 8,		     tSize = 8,
                  tType = 0,                 press = 10,                   
                   scrX = 0,                  scrY = 0,
                     px = 0,                    py = 0,
                      x = 0,                     y = 0,
                     ox = 0,                    oy = 0,
		      f = 0,		      fpos = 0, 		  
	       script[] = null, 	  maxLines = 0,                  
		   chan = -1,                cpHit = 0, 
		  lines = 0;
Choice 		      c = null;
square        squares[] = null;
Graphics              g = null,   	   gChoice = null;
Image 		  gif[] = null, 	       buf = null,
		   cPan = null;
Label               lbl = new Label();
MediaTracker	tracker = null;
Polygon 	      p = new Polygon();
Random      	      r = new Random();
Thread          running = null,		   imgload = null;
static final String  ads[] = {"Is it interactive yet?","Is this progress?","Who owns this image?"};
static final String tool[] = { "+ Hair","Line","Goober","Hatch","Ribbon",
		  "Snow", "wRake","Spindle","Splat", "Thorny",
	          "Tinsel","Jaggy", "Prop","Barcode","Veil","Gunko",
		  "N-Legs","Track","Scallop"
	        };
static final String name[] = {"hup","zir","goo","wir","gu2","wap","dum","hak","iki","rut","fok"};
TV tv = null;

    public void init(){
	int i;
        scrX     = Math.min(getToolkit().getScreenSize().width,size().width);
        scrY     = Math.min(getToolkit().getScreenSize().height,size().height);
	ready    = new boolean[name.length];
        gif      = new Image[name.length];
	setFont(new Font("Helvetica",Font.PLAIN,12));
        squares=new square[col.length];
        initControlPanel();
        initGraphics();
	 try{
               tracker=new MediaTracker(this);
               for(i=0;i<name.length;i++){
                     gif[i] = getImage(new java.net.URL(getCodeBase(),"Img/"+name[i]+".gif"));
                     tracker.addImage(gif[i],i);
               }
	}catch(Exception e) { System.out.println("Intrptd"+e); }
    }

    public void destroy(){ 
	buf.getGraphics().dispose();
    }
    public void update(Graphics g){ 
	paint(g); 
    }
    public void paint(Graphics g){ 
	if(buffered) g.drawImage(buf,0,0,this); 
	else g.drawImage(cPan,0,36,this);
	//c.paintAll(gChoice);
    }
    public void start(){ 
	(imgload = new Thread(this)).start(); 
	(running = new Thread(this)).start(); 
    }

    public void stop(){ 
	if(running != null) running.stop();
	if(imgload != null) imgload.stop();
	tv.stop();
    }

    public void run(){
         Thread.currentThread().setPriority(1);	
	if(Thread.currentThread()==running)
	{
	 while(running != null )
	 {
        	for(lines = 0;lines<maxLines;lines++){
			if(script==null) loadScript();
			else parseLine();
		}
		try { Thread.sleep(30); }
                catch(InterruptedException e) { System.out.println("Intrptd"); }
         }
	}
	else if(Thread.currentThread()==imgload){
		try{
		int i;
		while(imgload != null){
				while(!ready[i=Math.abs(jit(name.length))]){
					if(!down) ready[i] = tracker.checkID(i,true);
					Thread.sleep(100);
				}
				f = i;
				if(noscript){
                                        noscript=false;
                                        setRun();
                                        maxLines =  (getToolkit().getScreenResolution()<80? 10:80);
                                 }
				 /* for(i=0;i<name.length;i++){
				  	if(!ready[i]) break;
				  	else if(i==name.length-1){
						lbl.setText("All scripts loaded.");
						imgload.stop();
						imgload = null;
					}
				  }*/
				Thread.sleep(200);
		}
               	
	     }catch(Exception e) { System.out.println("Intrptd"); }
	}
    }

    public boolean handleEvent(Event e) {
	if(e.id==Event.MOUSE_DRAG){
			penAction(e.x,e.y,tSzUsr,ox,oy);
                        ox = e.x;
                        oy = e.y;
	}
	else if(e.id==Event.MOUSE_DOWN){
			down=true;
			if(wasrunning){
				if(running!=null){
				 	running.stop(); 
				 	running = null;
				}
			}
			if(p.npoints>0) p = new Polygon();
			lines = maxLines;
			px = ox = e.x;
                       	py = oy = e.y;
			if(e.x<36) cpHit = e.y/36;
                        if(e.target instanceof square){
			   for(int i=0;i<col.length;i++) squares[i].switchOff();
			   ((square)e.target).switchOn();
                           g.setColor(((Component)e.target).getBackground());
			}
	}
	else if(e.id==Event.MOUSE_UP){
			px = ox = x;
		        py = oy = y;
			down = false;
			if(wasrunning) (running = new Thread(this)).start();
			if(e.x<36) if(cpHit == e.y/36) doButton(e.y);
	}
	else if(e.id==Event.ACTION_EVENT){
                        if(e.target instanceof Choice)
                        {
                                int i;
                                for(i=0;i<tool.length;i++) 
				    if(((String)e.arg).equals(tool[i])) tType = ++i;
                        }
	}
        return true;
    }


    private void doButton(int y){
            switch(y/36){
                   case 1:  // CLEARSCREEN
			g.setPaintMode();
         		g.fillRect(0,0,scrX,scrY);
         		repaint();
         		lbl.setText("Screen cleared.");
			break;
                   case 2:  // TELEVISION
			tv.channel = ++chan;
                        if(chan<4) tv.start();
			else {
				tv.stop();
				chan = -1;
			}
			drawButton(1,true);
	   		lbl.setText(ads[Math.abs(jit(ads.length))]);
		   	break;
                  case 3: initGraphics(); break;
                  case 4: setRun();       break;
                  case 5:
                          if(y<198){
                              if(tSzUsr<200) 
				          tSzUsr = tSzUsr<<1;
                          }
                          else if(tSzUsr>1) tSzUsr = tSzUsr>>1;
                          lbl.setText("Your tool size:"+tSzUsr);
                          break;
                  case 6: setFill();      break;
                  case 7: setCycle();     break;
           }
	   cpHit = 0;
    }

    private void loadScript()
    {
     java.awt.image.PixelGrabber pg;
     int wid=-1,ht=-1;

	if(ready[f]){
	        if((wid = gif[f].getWidth(this)) < 0) return;
		if((ht  = gif[f].getHeight(this)) < 0) return;
		fpos = 0;
		script = new int[wid*ht];
		pg = new java.awt.image.PixelGrabber(gif[f],0,0,wid,ht,script,0,wid);
		gif[f].getSource().addConsumer(pg);
		try{ if(!pg.grabPixels()){ script=null; return;} }
		catch(InterruptedException e) { System.out.println("ldScr"); script=null; return; }
		if((pg.status() & java.awt.image.ImageObserver.ABORT)!=0){ 
			script=null; return; 
		}
                f = Math.abs(jit(name.length));
         }
	 else lbl.setText("Loading stuff...");
    }


    private void parseLine() 
    {
     int ofpos = fpos,i;
     String line = null;
     char   c0 = 0,chars[];
	while(fpos<script.length){
		if(script[fpos] == -16119286 /*ENDLINE*/ ) {  
			chars = new char[(fpos-ofpos)+1];
			for(i=0;i<chars.length-1;ofpos++,i++)
				chars[i] = (char) (-256^(script[ofpos]>>16));
			chars[i] = '\r';
			line = new String(chars);
			fpos++;
			break;
                }
		fpos++;
	}
	if(line==null){ script = null; return; }
        else{
        	c0 = line.charAt(0);
                if(c0<='9'){
                if(c0>='+'){
                     	StringTokenizer list=new StringTokenizer(line);
			String token;
                        try{
				if((i=list.countTokens())!=3) press = tSize;
				for(;i>0;i--){
				        token = list.nextToken();
				        c0 = token.charAt(0);
					if(c0!='.'){
					       if(i==3){
						   if(c0=='-') press--;
						   else if(c0=='+') press++;
						   else if(c0=='/') press=0;
						   else press = Integer.parseInt(token);
						}
						else if(press==0){
						    if(i==2){
							x  = Integer.parseInt(token);
							if(x>size().width) x -= (size().width);
						     }
						     else{
							  y  = Integer.parseInt(token);
							  if(y>size().height) y -= (size().height);
                                                          ox=px=x;
                                                          oy=py=y;
						     }
						}
						else{
					             if(i==2) x += Integer.parseInt(token);
                                                     else     y -= Integer.parseInt(token);
						}
					}
				}
                        }
                        catch(Exception n){ 
				System.out.println("fpos:"+fpos+"    "+"line:"+line+"  gif: "+gif[f]);
				script=null;
				return; 
			}
                        penAction(x,y,press,ox,oy);
                        ox = x;
                        oy = y;
                 } 
		}
                else
                {
                        if(c0=='d') delShape(line.substring(2));     
			else if(c0=='f') setFill(); 
                        else if(c0=='t'){
			    	tType = getVal(line.substring(2)); 
				c.select(tType-1);
				repaint(0,0,1,1);
                        }
			else if(c0=='s') tSize = getVal(line.substring(2));
			else if(c0=='c') copyRect(line.substring(2));        
			else g.setColor(getColor(c0));                                          
                }
          }
          return;
    }

	
    private synchronized void penAction(int x, int y, int press, int ox, int oy)
    {
      if(press>0)
      {
       int i,dx=0,dy=0;
	switch(tType)
        {
     		case 9:  // SPLATTER
                        dx = Math.abs(x-ox) + press;
                        dy = Math.abs(y-oy) + press;
                        for(i=0;i<press;i++)
				g.drawRect(x+jit(dx),y+jit(dy),1,1);
		case 0:  // LINE
		case 2:  // STROKE
			float k,m;
			double d;
                        i=(press>>2) + 1;
			int sz = (press>>1) + 2;
			
			if(press==1) g.drawLine(x,y,ox,oy);
			else{
			if (Math.abs(ox-x)>Math.abs(oy-y)) {
                               k=oy;d=(y-oy)/(float)(Math.abs(x-ox));
                               m=ox;
                               dx = (ox<x?1:-1);
                               while (m!=x) {
				      doOval((int)m-i,(int)k-i,sz,sz);
                                      k+=d;m+=dx;
                                }
                        } else if(Math.abs(oy-y)!=0) {
                                k=ox;d=(x-ox)/(float)(Math.abs(y-oy));
                                m=oy;
                                dy = (oy<y?1:-1);
                                while (m!=y) {
                                      doOval((int)k-i,(int)m-i,sz,sz);
                                      k+=d;m+=dy;
                                }
                        }
			}
			if(buffered) repaintSpan(x,y,ox,oy,
				Math.max(press+Math.abs(x-ox),press+Math.abs(y-oy)));
                        break;
                case 1:  // CROSSHAIR
                        dy = (press>>3)+1;
			dx=fill?1:2;
                        for(i=(-dy);i<dy+1;i+=dx){
                                g.drawLine(x+i,y,ox+i,oy);
                                g.drawLine(x,y+i,ox,oy+i);
                        }
		    	if(buffered) repaintSpan(x,y,ox,oy,i+1);
                        break;
                case 3:  // GOOBER
                        for(i=0;i<press;i++) g.fillRect(x+jit(press),y+jit(press),2,2);
			if(buffered) repaint(x-i-2,y-i-2,i+i+4,i+i+4);
                        break;
                case 4:  // HATCH
                        px = Math.abs(ox-x) + 1;
                        py = Math.abs(y-oy) + 1;
                        for(i=0;i<press;i+=2){
                              dx += jit(px);
                              dy += jit(py);
			      p.addPoint(x+dx,y+dy);
			      p.addPoint(ox+dx,oy+dy);
                        }
                        endPolygon(true,fill);
			break;
		case 5:  // RIBBON
                      	d = tanPt(x,y,ox,oy); 
			p.addPoint(ox,oy);
                        p.addPoint(x,y);
                        p.addPoint(px,py);
                        p.addPoint(px=(int)(ox+press*((y-oy)/d)),
		                   py=(int)(oy-press*((x-ox)/d)));
                        p.addPoint(x+px-ox, y+py-oy);
			if(!fill) p.addPoint(x,y);
			endPolygon(false,fill);
                        break;
                case 6:  // SNOW
			if(g.getColor()==Color.white) g.setXORMode(Color.black);
                        else 			      g.setXORMode(Color.white);
      			for(i=0;i<press+1;i++) 
			{
				px = x+jit(press);
				py = y+jit(press);
				dx = px + 10;
				for(;px<dx;px+=2) g.drawLine(px,py,px+10,py+10);
			}
                        g.setPaintMode();
			if(buffered) repaint(x-press,y-press,press+press+20,
								press+press+20);
                        break;
                case 15: // VEIL
                        dx = x%2==0? x-press/2:x-press/2+1;
                        dy = y%2==0? y-press/2:y-press/2+1;
			py = dy + press;
                        px = dx + press;
			i=0;
			while(true){
			     g.drawLine(dx+i,dy,dx,dy+i);
                             if(i>=press) break;
			     g.drawLine(px,py-i,px-i,py);
			     i+=2;
			}
			if(buffered) repaint(dx,dy,press,press);
                        break;
		case 7:  // RAKE
                        dx = ox-px;
                        dy = oy-py;
                case 17: // NLEGS       
                case 18: // TRACK
                        d = tanPt(x,y,ox,oy);
			p.addPoint(x,y);
			p.addPoint(ox,oy);
			p.addPoint(px,py);
			p.addPoint(px=(int)(ox+press*((y-oy)/d)),
				   py=(int)(oy-press*((x-ox)/d)));
			if(tType==18){
			 	p.addPoint(x,y);
                         	p.addPoint(x+px-ox,y+py-oy);
			}
                        else if(tType==17){
			 	px+=(x-ox);
                         	py+=(y-oy);
                         	p.addPoint(px,py);
			 	p.addPoint(x,y);
			}
			else{
			 	p.addPoint(ox+dx,oy+dy);
                         	p.addPoint(x+(x-px),y+(y-py));
			}
		        endPolygon(true,fill);
                        break;
                case 8: // SPINDLE
			px=x; py=y;
                        for(i=0;i<24;i+=2){
                                px += ((ox - x)>>2); py += ((oy - y)>>2);         
				p.addPoint(x+jit(2),y+jit(2));
				p.addPoint(px,py);
                        }
		        endPolygon(true,!fill);
			break;
                case 10:  // THORNYNAIL
                case 19:  // SCALLOP
			p.addPoint(x,y);
			p.addPoint(ox,oy);
			if(tType==19) p.addPoint(px,py);
			else { 
			        p.addPoint(x+jit(press),y+jit(press));
                        	p.addPoint(x+jit(press),y+jit(press));
			}
			endPolygon(false,fill);
                        break;
                case 11:  // TINSEL
	        case 16:  // GUNKO		
			press += 3;
			for(i=0;i<press;i++){
                              px = jit(press)+x;
                              py = jit(press)+y;
			      p.addPoint(px,py);
                              if(tType==11){
				 p.addPoint(x,y);
				 p.addPoint(ox,oy);
			      }
                        }
			endPolygon(false,fill);
                        break;
		case 12: // JAGGY
                        d = tanPt(x,y,ox,oy);
			p.addPoint(px,py);	
			p.addPoint(px=(int)(ox+press*((y-oy)/d)),
			           py=(int)(oy-press*((x-ox)/d)));
			p.addPoint(x,y);
			p.addPoint(x+px-ox,y+py-oy);
			p.addPoint(px,py);
			p.addPoint(ox,oy);
                        endPolygon(false,fill);
			break;
                case 14: // BARCODE
			for(i=0;i<50;){
				py=(jit(2)==0?35:45);
				for(dy=0;dy<(dx=(Math.abs(jit(3))+1));dy++) 
					g.drawLine(x+i+dy,y,x+i+dy,y+py);
				if(py==35){ 
					g.drawString((new Integer(i%10)).toString(),
						x+i,y+48); 
				}
				i+=(dx+6);
			}
			if(buffered) repaint(x,y,50,50);
			break;
		case 13:  // PROP
			for(i=0;(i<<4)<4096;i+=press){
				dx = Math.abs(jit(press)); 
                        	doArc(x-dx/2,y-dx/2,dx,dx,jit(360), jit(90));
			}
			if(buffered) repaint(x-press/2,y-press/2,i+press,i+press);
                        break;
                default:
			System.out.println("unknown tool, buddy"+tType+" f="+f);
                        break;
          }
          if(cycle) g.setColor(getColor(col[Math.abs(jit(col.length))])); 
       }
    }

    private int jit(int delta){ 
	return r.nextInt()%delta; 
    }

    private double tanPt(int x,int y,int ox,int oy){
       double d=Math.sqrt(Math.pow((double)(x-ox),2)+Math.pow((double)(y-oy),2));
       if(d!=0) return 4*d;
       else return 0.001;
    }
    
    private void endPolygon(boolean linear,boolean filled){
        if(filled) g.fillPolygon(p);
        else{
	  if(linear){
     		int i;
           	for(i=0;i<p.npoints;i+=2)
		 g.drawLine(p.xpoints[i],p.ypoints[i],
			    p.xpoints[i+1],p.ypoints[i+1]);
	  }
	  else g.drawPolygon(p);
        }	
        if(buffered) repaintBnd(p);     
        p=new Polygon();  
    }

    private void doArc(int x,int y,int w,int h,int s,int r){
	if(fill) g.fillArc(x,y,w,h,s,r);
	else     g.drawArc(x,y,w,h,s,r);
    }

    private void doOval(int x, int y, int w, int h){
       if(fill) g.fillOval(x,y,w,h); 
       else     g.drawOval(x,y,w,h);
    }

    private void repaintBnd(Polygon p){
	Rectangle r = p.getBoundingBox();
	repaint(r.x,r.y,r.width,r.height);
    }

    private void repaintSpan(int x,int y,int ox,int oy,int press){
        if(buffered) repaint(Math.min(ox,x)-press,Math.min(oy,y)-press,
			Math.abs(ox-x)+press+press,Math.abs(oy-y)+press+press);
    }

    private void initControlPanel()
    {
     int i;
     square cb;

	setLayout(new FlowLayout(0,0,0));
	c = new Choice();
	for(i=0;i<tool.length;i++) c.addItem(tool[i]);
        add(c);
	//gChoice = c.getGraphics();
	add(lbl);
	for(i=0;i<col.length;i++){
                squares[i] = new square(getColor(col[i]));
		squares[i].resize(20,20);
		if(squares[i]!=null) add(squares[i]);
		else System.out.println("null cb");
        }

        cPan = createImage(32,250);
	for(i=0;i<7;i++) drawButton(i,false);
	       tv = new TV(getGraphics());
    }


    private void drawButton(int but, boolean paint){
        Graphics tmp = (cPan.getGraphics()).create(0,36*but,36,36);
	tmp.setColor(Color.white);
        tmp.fill3DRect(0,0,32,32,false);
	tmp.setColor(Color.darkGray);
	tmp.fill3DRect(0,32,32,4,true);
	tmp.setColor(Color.black);

        if(but<3){
	  int i,j;
             for(i=0;i<30;i++){
                 for(j=0;j<32;j++){
                    if((icon[i+but*30]&(1<<j))==0) 
                           tmp.drawLine(j,i,j,i);
                 }
             }
	     if(but==1) if(chan>=0) tmp.drawString(new Integer(chan).toString(),7,17);
	}
	else if(but==3){
	 if(noscript==false)
	   if(wasrunning ){
                Polygon p = new Polygon();
                tmp.setColor(getColor('O'));
                 p.addPoint(fill?10:22,5);
                 p.addPoint(fill?25:7,15);
                 p.addPoint(fill?10:22,25);
                 tmp.fillPolygon(p);
           }
           else{
            int px,x,y;
                tmp.setColor(Color.red);
                 for(px=26,x=5,y=21;y<27;px--,y++,x++){
                      tmp.drawLine(x,y,px,y);
                      tmp.drawLine(x,31-y,px,31-y);
                 }
                 tmp.fillRect(5,10,22,12);
           }
	}
	else if(but==4){
			tmp.setColor(Color.gray);
			tmp.fillRect(1,16,30,15);
			tmp.setColor(Color.black);
			tmp.drawArc(4,17,4,3,45,185);
                        tmp.drawArc(3,20,4,3,220,185);
                        tmp.drawLine(11,17,11,23);
                        tmp.drawLine(15,17,20,17);
                        tmp.drawLine(20,17,15,23);
                        tmp.drawLine(15,23,20,23);
                        tmp.drawLine(27,17,23,17);
                        tmp.drawLine(23,17,23,23);
                        tmp.drawLine(23,23,27,23);
                        tmp.drawLine(23,20,27,20);
			int px,x,y;
			for(px=27,x=5,y=25;px>x;px-=2,y++,x+=2){
				tmp.drawLine(x,y,px,y);
				tmp.drawLine(x,31-y,px,31-y);
			}
			tmp.drawLine(2,8,8,8);
			tmp.drawLine(5,8,5,15);
			tmp.drawOval(9,8,5,7);
			tmp.drawOval(16,8,5,7);
			tmp.drawLine(24,8,24,15);
			tmp.drawLine(24,15,28,15);
	}
	else{
	 	if(but==5){
			tmp.drawOval(3,2,26,26);
			tmp.drawOval(6,2,20,26);
			tmp.drawOval(10,2,12,26);
			tmp.drawOval(14,2,4,26);
		}
		else
		{
			int i;
			for(i=0;i<col.length;i++){
				 tmp.setColor(getColor(col[i]));
				 tmp.fillArc(2,1,28,27,i*20,20);
			}
		}
		tmp.setColor(Color.gray);
		tmp.fillArc(3,3,26,26,180,180);
	}
	if(paint) paintCPanel();
	tmp.dispose();
    }


    public void initGraphics()
    {
	buffered = !buffered;
	if(buf==null){ 
		buf = createImage(scrX,scrY);
		g = buf.getGraphics();
		g.setColor(Color.lightGray);
		g.fillRect(0,0,scrX,scrY);
		g.drawImage(cPan,0,36,this);
	}
	Color c = g.getColor();
	if(buffered){
		g = buf.getGraphics();
		paintCPanel();
		repaint();
		lbl.setText("Slower, safer buffered graphics mode");
	}
	else{
		g = getGraphics();
		lbl.setText("FasTA & LooSa UnsAveD graphiCs MoDe");
	}
	g.setColor(c);
	g.clipRect(36,36,scrX,scrY);
    }

    private void copyRect(String s)
    {
     StringTokenizer list = new StringTokenizer(s);
     int cp[],dx,dy,w,h,x,y;

        cp = new int[6];
        for(h=0;h<6;h++) cp[h] = Integer.parseInt(list.nextToken());

        x=Math.min(cp[0],cp[2]);
        y=Math.min(cp[1],cp[3]);
        w=Math.abs(cp[0]-cp[2]);
        h=Math.abs(cp[1]-cp[3]);
        dx=cp[4]-x;
        dy=Math.max(cp[1],cp[3])-cp[5];
        g.copyArea(x,y,w,h,dx,dy);
        if(buffered) repaint(x+dx,y+dy,w,h);
    }

    private void delShape(String s){
     StringTokenizer list = new StringTokenizer(s);
     Polygon p = new Polygon();
	 while(list.hasMoreTokens())
	      p.addPoint(Integer.parseInt(list.nextToken()),
			 Integer.parseInt(list.nextToken()));
         g.fillPolygon(p);
	 repaintBnd(p);
    }

    private int getVal(String s) { 
	StringTokenizer list = new StringTokenizer(s);
	return(Integer.parseInt(list.nextToken())); 
    }

    private void setRun(){
	if(noscript)lbl.setText("No scripts are loaded yet.");
	else{
	drawButton(3,true);
	if(wasrunning){ 
		if(running!=null){
		running.stop();
		running = null;
		}
	}
	else (running = new Thread(this)).start();
	wasrunning = !wasrunning;
        lbl.setText("Automated drawing "+(wasrunning?"STARTED.":"STOPPED."));
	}
    }

    private void  paintCPanel(){
	if(buffered){
		buf.getGraphics().drawImage(cPan,0,36,this);
		repaint(0,36,32,250);
	}
	else paint(getGraphics());
    }

    private void flipButton(int num, boolean on){
        Graphics tmp = (cPan.getGraphics()).create(0,36*num,36,36);
        tmp.setColor(Color.lightGray);
        tmp.drawRect(2,on?1:15,28,14);
        tmp.setColor(Color.blue);
        tmp.drawRect(2,on?15:1,28,14);
	paintCPanel();
    }

    private void setFill(){
	 flipButton(5,!fill);
         fill = !fill; 
	 lbl.setText((fill?"Filling.":"No filling."));
    }

    private void setCycle(){
	flipButton(6,cycle);
	cycle = !cycle;
	lbl.setText("Color cycling "+(cycle?"ON.":"OFF."));
    }

    private Color getColor(char c)
    {
            if(c=='r') return Color.red;
       else if(c=='g') return Color.green;
       else if(c=='B') return Color.blue;
       else if(c=='L') return Color.lightGray;
       else if(c=='G') return Color.gray;
       else if(c=='D') return Color.darkGray;
       else if(c=='C') return Color.cyan;
       else if(c=='m') return Color.magenta;
       else if(c=='y') return Color.yellow;
       else if(c=='p') return Color.pink;
       else if(c=='o') return Color.orange;
       else if(c=='O') return new Color(-8882176);
       else if(c=='P') return new Color(-8912796);
       else if(c=='b') return Color.black;
       else return Color.white;
    }
}
