/****************************************
  netpuyo(client)
  graph.c --- low-level graphic operation
  (C) Oct 3, 1997 ROYALPANDA
*****************************************/

#include<stdio.h>
#include<X11/Xlib.h>
#include<X11/xpm.h>

#include"graph/puyo0.xpm"
#include"graph/puyo1.xpm"
#include"graph/puyo2.xpm"
#include"graph/puyo3.xpm"
#include"graph/puyo4.xpm"
#include"graph/puyo5.xpm"
#include"graph/wall.xpm"

#include"netpuyo.h"
#include"netpuyo_x.h"

static int Pic[2][8][14]; /* 画面の内容、下位3ビットが色、上位5ビットが形 */

static int S_pic[2][14];   /* 予告ぷよ、0は無し、2から */


/* Pic[p][x][y] を実際に描画 */

void draw( int p, int x, int y )
{
  int c,sy;

  if( x < 0 || x > 7 || y < 0 || y > 13 )
    return;

  if( Pic[p][x][y] == NOTHING )
    return;

  c = Pic[p][x][y] & 7;
  sy =  ( Pic[p][x][y] >> 3 ) * 32;
  x *= 32;
  y *= 32;
  XSetClipOrigin( Disp,Gc_mask[c],x,y-sy );
  XCopyArea( Disp,Char_p[c],Scr_w[p],Gc_mask[c],0,sy,32,32,x,y );
}


/* Pic[p][x][y] をセットして画面を更新 */

void draw_pic( int p, int x, int y, int color, int style )
{
  if( color != NOTHING && color != JAMA )
    color += style << 3;
  if( Pic[p][x][y] != color ){
    Pic[p][x][y] = color;
    XClearArea( Disp,Scr_w[p],x*32,y*32,32,32,False );
    draw(p,x,y);
  }
}

/* NEXTを描画 */

void draw_next( int p )
{
  int i;

  XClearWindow( Disp,Next_w[p] );

  if( P[p].next[0] == -1 )
    return;

  XSetClipOrigin( Disp,Gc_mask[P[p].next[0]],0,32-0 );
  XCopyArea( Disp,Char_p[P[p].next[0]],Next_w[p],Gc_mask[P[p].next[0]],
	    0,0,32,32,0,32 );

  XSetClipOrigin( Disp,Gc_mask[P[p].next[1]],0,0-512 );
  XCopyArea( Disp,Char_p[P[p].next[1]],Next_w[p],Gc_mask[P[p].next[1]],
	    0,512,32,32,0,0 );

  XSetClipOrigin( Disp,Gc_mask[P[p].next[2]],12-p*24,128-0 );
  XCopyArea( Disp,Char_p[P[p].next[2]],Next_w[p],Gc_mask[P[p].next[2]],
	    0,0,32,32,12-p*24,128 );

  XSetClipOrigin( Disp,Gc_mask[P[p].next[3]],12-p*24,96-512 );
  XCopyArea( Disp,Char_p[P[p].next[3]],Next_w[p],Gc_mask[P[p].next[3]],
	    0,512,32,32,12-p*24,96 );
}


/* 予告ぷよを実際に描画 */

void draw_stock( int p,int i )
{
  int c,x,y;

  if( i < 0 || i > 14 )
    return;

  x = (i % 7) * 32 + 16;
  y = (1 - i / 7 ) * 32;

  c = S_pic[p][i];
  if( c ){
    XSetClipOrigin( Disp,Gc_mask[0],x,y-c*32 );
    XCopyArea( Disp,Char_p[0],Stock_w[p],Gc_mask[0],0,c*32,32,32,x,y );
  }
}


/* 予告ぷよの数を計算して描画 */

void stock( int p )
{
  int i,s,k,pic;
  static int num[6] = { 1,6,30,180,360,720 };

  s = P[p].stock;
  k = 5;
  i = 0;

  do{
    if( s >= num[k] ){
      s -= num[k];
      if( S_pic[p][i] != k+2 ){
	S_pic[p][i] = k+2;
	XClearArea( Disp,Stock_w[p],(i%7)*32+16,(1-i/7)*32,32,32,False );
	draw_stock( p,i );
      }
      i++;
    }else
      k--;
  }while( k >= 0 && i < 14 );

  for( ; i < 14 ; i++ )
    if( S_pic[p][i] != 0 ){
      S_pic[p][i] = 0;
      XClearArea( Disp,Stock_w[p],(i%7)*32+16,(1-i/7)*32,32,32,False );
    }
}


/* Xpmのエラー処理 */

static void xpm_err( int err,char *file )
{
  if( err ){
    if( file == NULL )
      fprintf(stderr,"%s: %s\n",Myname,XpmGetErrorString(err));
    else
      fprintf(stderr,"%s: %s: %s\n",Myname,file,XpmGetErrorString(err));

    exit(1);
  }
}


/* グラフィックの作成／読み込み */

static void make_graphic( char *g_dir, char **wall )
{
  int i;
  char fname[256];
  XpmAttributes attr;
  Pixmap mask;

  static char **xpmdata[] = {
    puyo0_xpm,puyo1_xpm,puyo2_xpm,puyo3_xpm,puyo4_xpm,puyo5_xpm,
  };

  attr.valuemask = XpmColormap|XpmCloseness;
  attr.colormap = Cmap;
  attr.closeness = 0xffff;

  if( g_dir == NULL ){
    for( i = 0 ; i < 6 ; i++ ){
      xpm_err( XpmCreatePixmapFromData( Disp,DefaultRootWindow(Disp),
				       xpmdata[i],&Char_p[i],&mask,&attr ),
	      NULL);
      
      Gc_mask[i] = XCreateGC( Disp,DefaultRootWindow(Disp),0,NULL );
      XSetClipMask( Disp,Gc_mask[i],mask );
    }
  }else{
    attr.valuemask |= XpmSize;
    for( i = 0 ; i < 6 ; i++ ){
      sprintf( fname,"%s/puyo%d.xpm",g_dir,i);
      xpm_err( XpmReadFileToPixmap( Disp,DefaultRootWindow(Disp),fname,
				   &Char_p[i],&mask,&attr ),
	      fname);
      Gc_mask[i] = XCreateGC( Disp,DefaultRootWindow(Disp),0,NULL );
      XSetClipMask( Disp,Gc_mask[i],mask );
    }
  }

  for( i = 0 ; i < 2 ; i++ ){
    if( wall[i] == NULL )
      xpm_err( XpmCreatePixmapFromData( Disp,DefaultRootWindow(Disp),
				       wall_xpm,&Wall_p[i],NULL,&attr ),
	      NULL);
    else
      xpm_err( XpmReadFileToPixmap( Disp,DefaultRootWindow(Disp),wall[i],
				   &Wall_p[i],NULL,&attr ),
	      wall[i]);
  }
}


/* Xlib関係の前処理 */

void init_graph( char *g_dir, char **wall )
{
  int p,x,y;

  make_graphic( g_dir,wall );

  Gc_nomask = XCreateGC( Disp,DefaultRootWindow(Disp),0,NULL );

  for( p = 0 ; p < 2 ; p++ ){
    for( y = 0 ; y < 14 ; y++ ){
      for( x = 0 ; x < 8 ; x++ )
	Pic[p][x][y] = NOTHING;
    }
  }
} 

/* 画面を初期化、壁の描画 */

void clear_scr( void )
{
  int p,x,y;

  for( p = 0 ; p < 2 ; p++ ){
    for( y = 0 ; y < 13 ; y++ ){
      Pic[p][0][y] = WALL;
      Pic[p][7][y] = WALL;
      for( x = 1 ; x < 7 ; x++ )
	Pic[p][x][y] = NOTHING;
    }

    for( x = 0 ; x < 8 ; x++ )
      Pic[p][x][13] = WALL;

    XClearArea(Disp,Scr_w[p],0,0,0,0,True);
  }
}
