//
/* ----------------------------------------------------------------------------------------------
    adder32.java	32ビットの加算							ver. 1.00 (JDK 1.02)
    														ueyama@infonet.co.jp  2002.01.04
---------------------------------------------------------------------------------------------- */

import java.applet.Applet;
import java.awt.*;
import java.util.*;

public class adder32 extends Applet
{
	int			S[]=new int[4];										// 8ビット演算の和
	int			S1=0,  S4=0;										// 演算ステップ数
	int			X1=58, Y1=26;										// 32ビット演算表示オフセット
	int			X4=30, Y4=236;										// 8ビット演算表示オフセット
	boolean		C=false;											// Carry
	boolean		Ac=true;											// Add with Carry
	boolean		B8=false;											// true: 8, false: 32 ビット演算
	int			Bp=19;												// 2進数表示ピッチ
	int			Op=Bp*8+20;											// 1バイト表示ピッチ
	long		La=0, Lb=0;
	String		Sa, Sb, Ss;
	String		Ba[]=new String[4], Bb[]=new String[4], Bs[]=new String[4];
	int			A[]=new int[4], B[]=new int[4];
	int			grn=Integer.valueOf("ccffcc",16).intValue();		// 表示色の定義
	int			orn=Integer.valueOf("ffcccc",16).intValue();
	int			blu=Integer.valueOf("ccffff",16).intValue();
	int			pnk=Integer.valueOf("ffccff",16).intValue();
	int			bgc;
	Image		Img;
	Random		rnd=new Random();
	Graphics	gr;
	
	public void init()
	{
		String	Bg=getParameter("BgColor");
		bgc=Integer.valueOf(Bg,16).intValue();
		setBackground(new Color(bgc)); 
		MediaTracker mt=new MediaTracker(this);
		Img=getImage(getCodeBase(), getParameter("figure"));
		mt.addImage(Img, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		gr=getGraphics();
		new_ab();
	}
	
	public void cal_sum()											// 8ビット演算 和の文字列をつくる
	{
		for(int i=0;i<4;i++)
		{
			if(Ac) Bs[3-i]=Ss.substring(i*8,(i+1)*8);				// 8ビットに分割する
			else   Bs[3-i]=Integer.toString((Integer.parseInt(Ba[3-i],2)+Integer.parseInt(Bb[3-i],2))%256,2);
			while(Bs[3-i].length()<8) Bs[3-i]="0"+Bs[3-i];			// "0" を加えて8ビットにする
		}
	}
	
	public void b_to_s()
	{
		Sa=Long.toString(La,2);										// 2進数文字列をつくる
		Sb=Long.toString(Lb,2);
		Ss=Long.toString(La+Lb,2);
		while(Sa.length()<32) Sa="0"+Sa;							// "0" を加えて32ビットにする
		while(Sb.length()<32) Sb="0"+Sb;
		while(Ss.length()<32) Ss="0"+Ss;
		A[3]=(int)La/16777216; A[2]=(int)(La/65536)%256; A[1]=(int)(La/256)%256; A[0]=(int)La%256;
		B[3]=(int)Lb/16777216; B[2]=(int)(Lb/65536)%256; B[1]=(int)(Lb/256)%256; B[0]=(int)Lb%256;
		for(int i=0;i<4;i++)
		{
			Ba[i]=Integer.toString(A[i],2);							// 2進数文字列をつくる
			while(Ba[i].length()<8) Ba[i]="0"+Ba[i];				// "0" を加えて8ビットにする
			Bb[i]=Integer.toString(B[i],2);
			while(Bb[i].length()<8) Bb[i]="0"+Bb[i];
		}
	}

	public void new_ab()											// 加数・被加数を作る
	{
		int  i, f=1;
		while(f>0)
		{
			La=(long)Math.abs(rnd.nextInt());
			Lb=(long)Math.abs(rnd.nextInt());
			b_to_s();
			for(i=0;i<3;i++) if(A[i]+B[i]>256) f=0;					// 加算でキャリーが立つ
			if(La+Lb>0x7fffffffL) f=1;
			if(A[3]+B[3]<32) f=1;
		}
		cal_sum();
	}
	
	public boolean inside(int x, int a, int b)
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}
	
	public void dsp_img(int x, int y, int n, int m)					// 画像の表示
	{
		Graphics	gx=gr.create();
		int			w=0,h=0, ox=0,oy=0;
		switch(n)
		{
			case  0: w= 16; h= 24; ox=  0; oy=  0; break;			// 数字
			case  1: w= 26; h= 23; ox=183; oy=  0; break;			// |> ボタン
			case  2: w= 26; h= 23; ox=183; oy= 23; break;			// レ  ボタン
			case  9: w= 26; h= 23; ox=261; oy=  0; break;			// □  ボタン
			case  3: w= 12; h= 16; ox=  0; oy= 24; break;			// Carry 表示用数字
			case  4: w= 14; h= 14; ox= 60; oy= 18; break;			// Check Box
			case  5: w= 27; h= 14; ox= 88; oy= 18; break;			// "ADD"
			case  6: w= 95; h= 14; ox= 88; oy= 18; break;			// "ADD with Carry"
			case  7: w= 94; h= 19; ox= 88; oy= 32; break;			// "10進数表示"
			case  8: w= 11; h= 18; ox= 48; oy=  0; break;			// 数字
		}
		gx.clipRect(x,y,w,h);
		gx.drawImage(Img,x-(ox+w*m),y-oy,this);
		gx.dispose();
	}
	
	public void dsp_bin(int x, int y, String s, int n)				// 2進数の表示
	{
		for(int i=n-1;i>=0;i--) dsp_img(x+Bp*i,y,0,Integer.parseInt(s.substring(i,i+1)));
	}
	
	public void dsp_dec(int y, int n)								// n: 0 = 32 bit,  1〜4 = 8 bit
	{
		int i, l, v, x=162;
		String dec, bin="";
		
		dsp_img(x-108, y-1, 7, 0);
		if(n==0) v=Integer.parseInt(Ss,2);
		else
		{
			for(i=n; i>0; i--) bin+=Bs[i-1];
			v=Integer.parseInt(bin,2);
		}
		dec=Integer.toString(v);
		l=dec.length();
		
		for(i=0;i<12;i++, x+=13)
		{
			gr.setColor(new Color(bgc));
			gr.fillRect(x, y, 13, 18);
			dsp_img(x, y, 8, (i=0;i--)											// 8ビット演算部の表示
		{
			x=Op*(3-i)+X4;
			gr.setColor(new Color(blu));
			gr.fillRect(x-4, Y4-4, Bp*8+4, 32);
			gr.fillRect(x-4, Y4+40-4, Bp*8+4, 32);
			dsp_bin(x, Y4, Ba[i], 8);
			dsp_bin(x, Y4+40, Bb[i], 8);
			dsp_ans4(x, i);
		}
	}
	
	public void dsp_cary(int x, int y, int n)						// Carry の表示
	{
		int c, f=(C)?1:0, d=(n%8==7 && y>Y1)?2:0;
		
		if(B8 && !Ac && n%8==7) c=0;
		else c=(Integer.parseInt(Sa.substring(31-n,32-n))+Integer.parseInt(Sb.substring(31-n,32-n))+f)/2;
		dsp_img(x+2, y, 3, c+d);
		if(n==31) dsp_img(x+2, y, 3, 4);
		C=(c==1)?true:false;
	}
	
	public void dsp_ans1()											// 32ビット加算の和の表示
	{
		gr.setColor(new Color((S1>0)? orn: bgc));
		gr.fillRect(X1-4,Y1+86-4,Bp*32+4,32);
		if(S1>0) gr.setColor(new Color(orn-0x006666));
		for(int i=0;i<3;i++) gr.fillOval(Bp*8*(i+1)+X1-3,Y1+116,6,6);
		if(S1>0) dsp_bin(X1, Y1+86, Ss, 32);
	}
	
	public void dsp_ans4(int x, int n)								// 8ビット加算の和の表示
	{
		gr.setColor(new Color((S4>n)? pnk: bgc));
		gr.fillRect(x-4, Y4+86-4, Bp*8+4, 32);
		if(S4>n) dsp_bin(x, Y4+86, Bs[n], 8);
	}
	
	public void paint(Graphics g)
	{
		int		i,j;
	
		dsp_img(X4 -26,Y4 +40,0,2); dsp_img(X1-26,Y1+40,0,2);		// + 符号の表示
		dsp_img(630,Y1+130,2,(S1==0)?2:0);
		dsp_img(630,Y4+130,2,(S4==0)?2:0);							// レ  ボタンの表示
		dsp_img(660,Y1+130,1,(S1==0)?0:2);
		dsp_img(660,Y4+130,1,(S4>3)?2:0);							// |> ボタンの表示
		dsp_img(590,Y4+130,9,(S4>0)?2:0);							// □  ボタンの表示
		dsp_add();													// 加算数値の表示
		if(S1>0) for(i=0;i<32;i++) dsp_cary(Bp*(31-(i+1))+X1, Y1-24, i);
		if(S1>0) dsp_dec(Y1+134, 0);
		for(i=3;i>=0;i--)
		{
			if(i0) dsp_dec(Y4+134, S4);
		dsp_img(382,Y4+135,4,(Ac)?1:0);								// ADD Check Box
		dsp_img(458,Y4+135,4,(Ac)?0:1);								// ADD with Carry Check Box
		dsp_img(402,Y4+135,5,0);									// "ADD"
		dsp_img(478,Y4+135,6,0);									// "ADD with Carry"
	}
	
	public boolean mouseDown(Event e, int mx, int my)
	{
		int     i,n=99,x;
		long    l=0, m=1;
		boolean a=false;
		
		if(inside(my,Y1+130,Y1+130+23))								// 32 ビット演算
		{
			B8=false;
			if(inside(mx,660,660+26) && S1==0)						// |> ボタン
			{
				dsp_img(660,Y1+130,1,1);
				dsp_img(590,Y4+130,9,2);
				for(i=0;i<32;i++) dsp_cary(Bp*(31-(i+1))+X1, Y1-24, i);
			}
			if(inside(mx,630,630+26) && S1>0)						// レ  ボタン
			{
				dsp_img(630,Y1+130,2,1);
				if(S4==0) dsp_img(590,Y4+130,9,0);
			}
		}
		if(inside(my,Y4+130,Y4+130+23))								// 8 ビット演算
		{
			B8=true;
			if(inside(mx,660,660+26) && S4<4)						// |> ボタン
			{
				dsp_img(660,Y4+130,1,1);
				dsp_img(590,Y4+130,9,2);
				for(i=0;i<8;i++)
				{
					n=S4*8+i;
					dsp_cary(Op*(3-(n+1)/8)+Bp*(7-(i+1)%8)+X4, Y4-24, n);
				}
			}
			if(inside(mx,630,630+26) && S4>0)						//  レ  ボタン
			{
				dsp_img(630,Y4+130,2,1);
				if(S1==0) dsp_img(590,Y4+130,9,0);
			}
			if(inside(mx,590,590+26) && S1==0 && S4==0) dsp_img(590,Y4+130,9,1);	//  □  ボタン
			if(inside(mx,382,574))									// 加算切り替え
			{
				Ac=!Ac;
				dsp_img(382,Y4+135,4,(Ac)?1:0);						// "ADD" Check Box
				dsp_img(458,Y4+135,4,(Ac)?0:1);						// "ADD with Carry" Check Box
				cal_sum();
			}
		}
		if(S1+S4==0 && (inside(my,Y1-4,Y1+68) || inside(my,Y4-4,Y4+68)))	// 数値の編集
		{
			x=mx-X4; i=152;
			if((inside(x,0,i) || inside(x,Op,Op+i) || inside(x,Op*2,Op*2+i) || inside(x,Op*3,Op*3+i)) && my>Y4-4) n=(x-20*(x/Op))/Bp;
			if(inside(mx-X1,0,Bp*32) && my0) dsp_dec(Y1+134, 0);
		}
		if(inside(my,Y4+130,Y4+130+23))								// 8 ビット演算
		{
			int i;
			
			if(inside(mx,660,660+26) && S4<4)						// |> ボタン
			{
				S4++;
				dsp_img(630,Y4+130,2,0);
				dsp_img(660,Y4+130,1,(S4>3)?2:0);
				dsp_ans4(Op*(3-S4+1)+X4, S4-1);
				dsp_dec(Y4+134, S4);
			}
			if(inside(mx,630,630+26))								// レ  ボタン
			{
				S4=0; C=false;
				dsp_img(630,Y4+130,2,2);
				dsp_img(660,Y4+130,1,0);
				if(S1==0) dsp_img(660,Y4+130,1,0);
				for(i=0;i<4;i++) dsp_ans4(Op*(3-i)+X4, i);
				gr.setColor(new Color(bgc));
				gr.fillRect(0,Y4-24,size().width,16);
				gr.fillRect(54,Y4+132, 258,20);
			}
			if(inside(mx,590,590+26) && S1==0 && S4==0)				//  □  ボタン
			{
				dsp_img(590,Y4+130,9,0);
				new_ab();
				dsp_add();
			}
		}
		return true;
	}
}
//
戻る