/*------------------------------------------------------------------------
--	Michael Irani				Due: 12/18/02		--
--	CS 360					Final			--
--									--
--									--
--	Filename:	tetris.c					--
--									--
--	Description:	Plays tetris.  For full documentation look at   --
--       	ReadMe.txt file.					--
--									--
------------------------------------------------------------------------*/
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>

//width and height of program
static int width = 205;
static int height = 406;

gint level=2;
GtkWidget *spinnerLevel, *spinnerRows, *spinnerColumns;
static GtkWidget *scoreLabel;
int score=0;
int piece, state, posx[4], posy[4], sizex=10, sizey=20;
int mat[40][20];
static gint secondTag;
static gint drawTag;
static gint optionDrawTag;
gboolean pause;
typedef GtkWidget* pointer;
pointer wackyColor[7], colorButton[7], randomSpinner[7];
GtkWidget *aboutwindow, *newgamewindow, *optionswindow, *helpwindow;
GtkWidget *csDialog = NULL;
GtkWidget *name_box;
GdkColor colors[7];
GtkWidget *colorSel;
gboolean wackyBool[7];
int randomSet[7], message = 0;
GtkWidget *optionsArea;
GtkWidget *area;

void get_main_menu( GtkWidget  *window, GtkWidget **menubar );

void about (GtkWidget *widget, gpointer data);
void destroyabout( GtkWidget *widget, gpointer data);

void newgame( int argc, char *argv[]);
void destroynewgame( GtkWidget *widget, gpointer data);

void highScores( int   argc, char *argv[]);
gint destroyhighScores(GtkWidget *widget, gpointer data);

void newhighscore(int argc, char *argv[]);
gint destroynewhighscore(GtkWidget *widget, gpointer data);

void options( int   argc, char *argv[]);
void showColorsel(GtkWidget *widget, gpointer data);
void changeColor(GtkWidget *widget, gpointer data);
void destroyColorsel(GtkWidget *widget, gpointer data);
void wackyFunc (GtkWidget *widget, gpointer data);
gboolean drawOptions(GtkWidget *widget, GdkEvent *event, gpointer data);
void destroyoptions(GtkWidget *widget, gpointer data);

void help( int argc, char *argv[]);
void destroyhelp(GtkWidget *widget, gpointer data);

void pauseFunc(int argc,char *argv[]);
gboolean eventDraw(GtkWidget *widget, GdkEvent *event, gpointer data);
gboolean eventConfigure(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
gint eventDestroy( GtkWidget *widget, GdkEvent *event, gpointer data);

//From KeyPress
gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data);
gint eventFocus(GtkWidget *widget, GdkEvent *event, gpointer data);
gint eventPressKey(GtkWidget *widget, GdkEvent *event, gpointer data);

//Game Play
gboolean newpiece();
gboolean movedown();
void moveright();
void moveleft();
void changestate();
void check();
gint linker(gpointer data);

static GtkItemFactoryEntry menu_items[] = {
  { "/_Game", 		NULL, 		NULL, 0, "<Branch>" },
  { "/Game/_New Game", 	"<control>N", 	newgame, 0, NULL },
  { "/Game/_Pause", 	"<control>P", 	pauseFunc, 0, NULL },
  { "/Game/_Best Scores","<control>B", 	highScores, 0, NULL },
  { "/Game/sep1", 	NULL, 		NULL, 0, "<Separator>" },
  { "/Game/Quit", 	"<control>Q", 	gtk_main_quit, 0, NULL },
  { "/_Options", 	NULL, 		NULL, 0, "<Branch>" },
  { "/Options/Object _Settings","<control>S", options, 0, NULL },
  { "/_Help", 		NULL, 		NULL, 0, "<LastBranch>" },
  { "/Help/_How to Play", 	NULL,	help, 0, NULL },
  { "/Help/_About", 	NULL,		about, 0, NULL }
};

int main( int argc, char *argv[] )
{
  GtkWidget *window;
  GtkWidget *vbox;
  GtkWidget *menubar;

  srand(time(NULL));

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (eventDestroy),NULL);
  gtk_window_set_title (GTK_WINDOW(window), "Tetris");
  gtk_widget_set_usize (GTK_WIDGET(window), width, height);

  vbox = gtk_vbox_new (FALSE, 1);
  gtk_container_border_width (GTK_CONTAINER (vbox), 1);
  gtk_container_add (GTK_CONTAINER (window), vbox);
  gtk_widget_show (vbox);

  //MENU
  get_main_menu (window, &menubar);
  gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, TRUE, 0);
  gtk_widget_show (menubar);

  //SCORE
  scoreLabel = gtk_label_new("Score: ");
  gtk_box_pack_start (GTK_BOX(vbox),scoreLabel,FALSE,FALSE,0);
  gtk_widget_show(scoreLabel);

  //DRAWING AREA
  area = gtk_drawing_area_new();
  gtk_widget_set_usize(area, width, height);
  gtk_box_pack_start (GTK_BOX (vbox),area, TRUE, TRUE, 0);
  gtk_widget_show(area);
  gtk_signal_connect (GTK_OBJECT(area), "expose-event", GTK_SIGNAL_FUNC(eventDraw), NULL);
  gtk_signal_connect (GTK_OBJECT(area), "configure-event", GTK_SIGNAL_FUNC(eventConfigure), NULL);

  //KEY PRESS
  gtk_signal_connect (GTK_OBJECT(window),"focus_in_event",GTK_SIGNAL_FUNC(eventFocus),NULL);
  gtk_signal_connect (GTK_OBJECT(window),"focus_out_event",GTK_SIGNAL_FUNC(eventFocus),NULL);
  gtk_signal_connect (GTK_OBJECT(window),"key_press_event",GTK_SIGNAL_FUNC(eventPressKey),NULL);

  //about box
  {
    GtkWidget *aboutvbox;
    GtkWidget *aboutbutton;
    GtkWidget *aboutlabel;

    aboutwindow = gtk_window_new (GTK_WINDOW_POPUP);
    aboutvbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (aboutvbox), 10);
    gtk_container_add (GTK_CONTAINER (aboutwindow), aboutvbox);
    gtk_widget_show(aboutvbox);

    aboutlabel = gtk_label_new ("Tetris : \n\n2002, Michael Irani\nmirani1@binghamton.edu");
    gtk_box_pack_start (GTK_BOX (aboutvbox), aboutlabel, TRUE, TRUE, 0);
    gtk_widget_show(aboutlabel);

    aboutbutton = gtk_button_new_with_label ("close");
    gtk_signal_connect (GTK_OBJECT (aboutbutton), "clicked",GTK_SIGNAL_FUNC(destroyabout),aboutwindow);
    gtk_box_pack_start (GTK_BOX (aboutvbox), aboutbutton, FALSE, FALSE, 0);
    gtk_widget_show(aboutbutton);
  }
  //new game dialog
  {
    GtkWidget *newgamevbox;
    GtkWidget *newgamelevelhbox;
    GtkWidget *newgamerowhbox;
    GtkWidget *newgamecolhbox;
    GtkWidget *newgamedonehbox;
    GtkWidget *newgamebutton;
    GtkWidget *newgameoption;
    GtkWidget *newgamelabel;
    GtkAdjustment *newgameadj;

    newgamewindow = gtk_window_new (GTK_WINDOW_DIALOG);
    gtk_signal_connect (GTK_OBJECT (newgamewindow), "destroy",GTK_SIGNAL_FUNC (gtk_main_quit),NULL);
    gtk_window_set_title (GTK_WINDOW (newgamewindow), "New Game");

    newgamevbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (newgamevbox), 10);
    gtk_container_add (GTK_CONTAINER (newgamewindow), newgamevbox);

    //---Level
    newgamelevelhbox = gtk_hbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX (newgamevbox), newgamelevelhbox, TRUE, TRUE, 5);

    newgamelabel = gtk_label_new ("Level :  ");
    gtk_misc_set_alignment (GTK_MISC (newgamelabel), 0, 0.5);
    gtk_box_pack_start (GTK_BOX (newgamelevelhbox), newgamelabel, TRUE, TRUE, 0);

    newgameadj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 9.0, 1.0, 5.0, 0.0);
    spinnerLevel = gtk_spin_button_new (newgameadj, 0, 0);
    gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinnerLevel), TRUE);
    gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinnerLevel),GTK_SHADOW_OUT);
    gtk_box_pack_start (GTK_BOX (newgamelevelhbox), spinnerLevel, TRUE, TRUE, 0);

    //---Rows
    newgamerowhbox = gtk_hbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX (newgamevbox), newgamerowhbox, TRUE, TRUE, 5);

    newgamelabel = gtk_label_new ("Rows :  ");
    gtk_misc_set_alignment (GTK_MISC (newgamelabel), 0, 0.5);
    gtk_box_pack_start (GTK_BOX (newgamerowhbox), newgamelabel, TRUE, TRUE, 0);

    newgameadj = (GtkAdjustment *) gtk_adjustment_new (20.0, 10.0, 40.0, 1.0, 5.0, 0.0);
    spinnerRows = gtk_spin_button_new (newgameadj, 0, 0);
    gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinnerRows), TRUE);
    gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinnerRows),GTK_SHADOW_OUT);
    gtk_box_pack_start (GTK_BOX (newgamerowhbox), spinnerRows, TRUE, TRUE, 0);

    //---Columns
    newgamecolhbox = gtk_hbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX (newgamevbox), newgamecolhbox, TRUE, TRUE, 5);

    newgamelabel = gtk_label_new ("Columns :  ");
    gtk_misc_set_alignment (GTK_MISC (newgamelabel), 0, 0.5);
    gtk_box_pack_start (GTK_BOX (newgamecolhbox), newgamelabel, TRUE, TRUE, 0);

    newgameadj = (GtkAdjustment *) gtk_adjustment_new (10.0, 6.0, 20.0, 1.0, 5.0, 0.0);
    spinnerColumns = gtk_spin_button_new (newgameadj, 0, 0);
    gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinnerColumns), TRUE);
    gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinnerColumns),GTK_SHADOW_OUT);
    gtk_box_pack_start (GTK_BOX (newgamecolhbox), spinnerColumns, TRUE, TRUE, 0);

    //---Options and done
    newgamedonehbox = gtk_hbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX (newgamevbox), newgamedonehbox, TRUE, TRUE, 5);

    newgameoption = gtk_button_new_with_label("Options");
    gtk_signal_connect (GTK_OBJECT (newgameoption), "clicked", GTK_SIGNAL_FUNC (options), NULL);
    gtk_box_pack_start(GTK_BOX (newgamedonehbox), newgameoption, FALSE, FALSE, 0);

    newgamelabel = gtk_label_new ("     ");
    gtk_misc_set_alignment (GTK_MISC (newgamelabel), 0, 0.5);
    gtk_box_pack_start (GTK_BOX (newgamedonehbox), newgamelabel, TRUE, TRUE, 0);

    newgamebutton = gtk_button_new_with_label("DONE");
    gtk_signal_connect (GTK_OBJECT (newgamebutton), "clicked", GTK_SIGNAL_FUNC (destroynewgame),newgamewindow);
    gtk_box_pack_start(GTK_BOX (newgamedonehbox), newgamebutton, FALSE, FALSE, 0);
  }
  //set inital colors
  {
    colors[0].red=(0*0xFFFF);             //square
    colors[0].green=(gushort)(250*0xFFFF);
    colors[0].blue=(0*0xFFFF);
    wackyBool[0]=FALSE;
    randomSet[0]=2;

    colors[1].red=(gushort)(250*0xFFFF);  //'T'
    colors[1].green=(0*0xFFFF);
    colors[1].blue=(0*0xFFFF);
    wackyBool[1]=FALSE;
    randomSet[1]=2;

    colors[2].red=(0*0xFFFF);             //Line
    colors[2].green=(0*0xFFFF);
    colors[2].blue=(0*0xFFFF);
    wackyBool[2]=TRUE;
    randomSet[2]=1;

    colors[3].red=(0*0xFFFF);             //'S'
    colors[3].green=(0*0xFFFF);
    colors[3].blue=(gushort)(250*0xFFFF);
    wackyBool[3]=FALSE;
    randomSet[3]=3;

    colors[4].red=(gushort)(250*0xFFFF);  //backwards 'S'
    colors[4].green=(gushort)(250*0xFFFF);
    colors[4].blue=(0*0xFFFF);
    wackyBool[4]=FALSE;
    randomSet[4]=3;

    colors[5].red=(gushort)(250*0xFFFF);  //'L'
    colors[5].green=(0*0xFFFF);
    colors[5].blue=(gushort)(250*0xFFFF);
    wackyBool[5]=FALSE;
    randomSet[5]=3;

    colors[6].red=(0*0xFFFF);             //backwards 'L'
    colors[6].green=(gushort)(250*0xFFFF);
    colors[6].blue=(gushort)(20*0xFFFF);
    wackyBool[6]=FALSE;
    randomSet[6]=3;
  }
  //Options Dialog
  {
    GtkWidget *table;
    GtkWidget *done;
    GtkWidget *label;
    GtkAdjustment *adj;
    gint ref;

    optionswindow = gtk_window_new (GTK_WINDOW_DIALOG);
    gtk_signal_connect (GTK_OBJECT (optionswindow), "destroy",GTK_SIGNAL_FUNC (destroyoptions),NULL);
    gtk_window_set_title (GTK_WINDOW (optionswindow), "Options");

    table = gtk_table_new (4,9, FALSE);
    gtk_table_set_col_spacings(GTK_TABLE(table), 8);
    gtk_container_add (GTK_CONTAINER (optionswindow), table);
    gtk_widget_show(table);

    //DRAWING AREA
    optionsArea = gtk_drawing_area_new();
    gtk_widget_set_usize(optionsArea, 50, 340);
    gtk_table_attach_defaults(GTK_TABLE(table),optionsArea,0,1,1,8);
    gtk_widget_show(optionsArea);

    //Headings
    label = gtk_label_new ("Piece");
    gtk_table_attach_defaults(GTK_TABLE(table),label,0,1,0,1);

    label = gtk_label_new ("Random Setting");
    gtk_table_attach_defaults(GTK_TABLE(table),label,1,2,0,1);

    label = gtk_label_new ("Color Settings");
    gtk_table_attach_defaults(GTK_TABLE(table),label,2,3,0,1);

    label = gtk_label_new ("Wacky Color");
    gtk_table_attach_defaults(GTK_TABLE(table),label,3,4,0,1);

    //sets up the options for all the pieces.
    for (ref=0; ref<7; ref++)
    {
      adj = (GtkAdjustment *) gtk_adjustment_new (randomSet[ref], 0.0, 50.0, 1.0, 5.0, 0.0);
      randomSpinner[ref] = gtk_spin_button_new (adj, 0, 0);
      gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (randomSpinner[ref]), TRUE);
      gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (randomSpinner[ref]),GTK_SHADOW_OUT);
      gtk_table_attach_defaults(GTK_TABLE(table),randomSpinner[ref],1,2,ref+1,ref+2);

      colorButton[ref] = gtk_button_new_with_label("Change");
      gtk_signal_connect (GTK_OBJECT (colorButton[ref]), "clicked", GTK_SIGNAL_FUNC (showColorsel),(gpointer)ref);
      gtk_table_attach_defaults(GTK_TABLE(table),colorButton[ref],2,3,ref+1,ref+2);

      wackyColor[ref] = gtk_check_button_new_with_label("Click to Set");
      gtk_signal_connect (GTK_OBJECT (wackyColor[ref]), "clicked", GTK_SIGNAL_FUNC (wackyFunc),(gpointer)ref);
      gtk_table_attach_defaults(GTK_TABLE(table),wackyColor[ref],3,4,ref+1,ref+2);
      gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON(wackyColor[ref]),TRUE);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wackyColor[ref]),wackyBool[ref]);
    }

    done = gtk_button_new_with_label("DONE");
    gtk_signal_connect (GTK_OBJECT (done), "clicked", GTK_SIGNAL_FUNC (destroyoptions),optionswindow);
    gtk_table_attach_defaults(GTK_TABLE(table), done,1,4,8,9);
  }
  //help dialog
  {
    GtkWidget *helpvbox;
    GtkWidget *done;
    GtkWidget *title;
    GtkWidget *info;

    helpwindow = gtk_window_new (GTK_WINDOW_DIALOG);
    gtk_signal_connect (GTK_OBJECT(helpwindow), "destroy", GTK_SIGNAL_FUNC (destroyhelp), NULL);
    gtk_window_set_title (GTK_WINDOW(helpwindow), "How to Play");

    helpvbox = gtk_vbox_new (FALSE, 1);
    gtk_container_border_width (GTK_CONTAINER (helpvbox), 1);
    gtk_container_add (GTK_CONTAINER (helpwindow), helpvbox);

    title = gtk_label_new ("How to Play Tetris: \n ");
    gtk_box_pack_start (GTK_BOX (helpvbox), title, FALSE, TRUE, 0);
    
    
    //prints out the message in a text box
    info = gtk_text_new (NULL, NULL);
    gtk_text_set_editable(GTK_TEXT(info), FALSE);
    gtk_text_insert(GTK_TEXT(info), NULL, NULL, NULL,"Blocks of different shapes drop from the top of the screen into a box. Each block is made up of four small squares arranged to make a larger square, an L-shape or a column. As the blocks fall they can be rotated(by pressing the up arrow) or moved horizontally (right/left arrow) so that every space in the box is filled(the block's vertical movement can be sped up with the down arrow). When a horizontal line is completed, that line is ""destroyed"" giving you 10 points and moving the rest of the placed pieces down by one square. If a line remains incomplete, another line must be finished above stack, reducing the space in which falling shapes can be manipulated.  Eventually the blocks reach the top of the screen and the game ends.",-1);
    gtk_text_insert(GTK_TEXT(info), NULL, NULL, NULL,"To start a game click on Game then New Game and select the options you want.  You can set the number of rows/columns you want and the level you would like to start on.  Then click done or options.  The options menu will allow you to set the colors of the pieces and the chances that the pieces will drop down.  To view the best scores click on Game then Best Scores.  To Pause the game click on Game then Pause.",-1);
    gtk_box_pack_start (GTK_BOX (helpvbox), info, FALSE, TRUE, 0);


    done = gtk_button_new_with_label("DONE");
    gtk_signal_connect (GTK_OBJECT (done), "clicked", GTK_SIGNAL_FUNC (destroyhelp),NULL);
    gtk_box_pack_start (GTK_BOX (helpvbox), done, FALSE, TRUE, 0);
  }

  gtk_widget_show (window);
  gtk_main ();

  return(0);
}



//**************************MAIN MENU*************************************************
void get_main_menu( GtkWidget  *window, GtkWidget **menubar )
//this function creates the main menu.
{
  GtkItemFactory *item_factory;
  GtkAccelGroup *accel_group;
  gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
  accel_group = gtk_accel_group_new ();
  item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
  /* This function generates the menu items. Pass the item factory,
     the number of items in the array, the array itself, and any
     callback data for the the menu items. */
  gtk_item_factory_create_items (GTK_ITEM_FACTORY(item_factory), nmenu_items, menu_items, NULL);
  /* Attach the new accelerator group to the window. */
  gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
  if (menubar)
    *menubar = gtk_item_factory_get_widget (GTK_ITEM_FACTORY(item_factory), "<main>");
}



//**************************ABOUT BOX*************************************************
void about(GtkWidget *widget, gpointer data)// int   argc, char *argv[])
//this function creates the pop up window about box
{
  pause = TRUE;
  gtk_widget_show(aboutwindow);
}

void destroyabout( GtkWidget *widget, gpointer data)
//destroys the about box
{
  pause=FALSE;
  gtk_widget_hide(GTK_WIDGET(data));
}



//**************************NEW GAME DIALOG******************************************
void newgame(int   argc, char *argv[])
//this function creates the dialog box that asks the user what level they
// would like to play, and there is a button to start the game.
{
  pause = TRUE;
  
  if (drawTag>0)
  {
    gtk_timeout_remove (drawTag);
    eventDraw(area,NULL,NULL);
  }
  
  message = 0;
  gtk_widget_show_all (newgamewindow);
}

void destroynewgame( GtkWidget *widget, gpointer data)
//destroy new game dialog
{
  int y=0, x, delay;

  score=0;
  pause=FALSE;
  drawTag = gtk_timeout_add (50, (GtkFunction)eventDraw, area);
  
  while (y<sizey)		//initialize matrix to 0
  {
    x=0;
    while(x<sizex)
    {
      mat[y][x]=0;
      x++;
    }
    y++;
  }

  //get the number of rows and columns the user entered
  sizex = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinnerColumns));
  sizey = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinnerRows));

  //get the level to start on
  level = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinnerLevel));

  //set the delay
  if(level==1) delay = 250;
  else if (level==2) delay = 220;
  else if (level==3) delay = 205;
  else if (level==4) delay = 190;
  else if (level==5) delay = 175;
  else if (level==6) delay = 160;
  else if (level==7) delay = 145;
  else if (level==8) delay = 130;
  else if (level==9) delay = 115;
  if (secondTag>0)gtk_timeout_remove (secondTag);
    secondTag = gtk_timeout_add (delay, (GtkFunction)linker, NULL);

  newpiece();
  gtk_widget_hide(GTK_WIDGET(data));
}



//**************************HIGH SCORES DIALOG****************************************
void highScores( int   argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *vbox;
  GtkWidget *button;
  GtkWidget *label;
  FILE *infile;
  char mes[80];
  int num,size;

  pause=TRUE;
  if (drawTag>0)
  {
    gtk_timeout_remove (drawTag);
    eventDraw(area,NULL,NULL);
  }
  
  window = gtk_window_new (GTK_WINDOW_POPUP);
  vbox = gtk_vbox_new (FALSE, 5);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
  gtk_container_add (GTK_CONTAINER (window), vbox);
  gtk_widget_show(vbox);

  infile = fopen("highscores.txt","r");

  //if there were no problems reading from file print the best scores
  if(infile)
  {
    label = gtk_label_new ("     ******Best Scores******     \n");
    gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
    gtk_widget_show(label);

    //reads in all the scores and names
    while(fgets(mes, 30, infile))
    {
      char temp[30];
      int count=0,mespos;
      fscanf(infile,"%d",&num);
      size = log10(num) + 1;
      while(count<size)
      {
        temp[count]=(num%10)+'0';
        num/=10;
        count++;
      }

      count--;
      mespos=strlen(mes);

      //print out proper number of spaces
      mes[mespos]=' ';
      mes[mespos+1]=' ';
      mespos+=2;
      while(count>=0)
      {
        mes[mespos]=temp[count];
        mespos++;
        count--;
      }
      mes[mespos]='\0';
      label = gtk_label_new (mes);
      gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
      gtk_widget_show(label);
    }
    fclose(infile);
  }
  //do this if file doesn't open properly
  else
  {
    label = gtk_label_new ("Error Reading from file.");
    gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
    gtk_widget_show(label);
  }

  button = gtk_button_new_with_label ("close");
  gtk_signal_connect (GTK_OBJECT (button), "clicked",GTK_SIGNAL_FUNC(destroyabout),window);
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  gtk_widget_show(button);

  gtk_widget_show(window);
}

gint destroyhighScores(GtkWidget *widget, gpointer data)
{
  pause = FALSE;
  drawTag = gtk_timeout_add (50, (GtkFunction)eventDraw, area);
  
  gtk_widget_destroy(GTK_WIDGET(data));
  return (0);
}



//**************************NEW HIGH SCORES DIALOG******************************************
void newhighscore(int argc, char *argv[])
//comes up if the player deserves to be in the high scores table
{
  FILE *infile;
  char names[5][80];
  int scores[5], read_count = 0;
  int won = 0;

  infile = fopen ("highscores.txt", "r");
  if (infile)
  {
    while( (fscanf(infile,"%s\t%d", names[read_count],&scores[read_count])==2) && (read_count<5) )
    {
      if ( (score > scores[read_count]) && (won == 0) )
      {
	won = 1;
      }
      read_count++;
    }
    fclose(infile);
  }
  if (read_count<4)
    won = 1;


  if (won == 1)
  {
    GtkWidget *window;
    GtkWidget *vbox;
    GtkWidget *button;
    GtkWidget *label;
    window = gtk_window_new (GTK_WINDOW_DIALOG);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
    gtk_container_add (GTK_CONTAINER (window), vbox);
    gtk_widget_show(vbox);

    label = gtk_label_new ("You have won a \nplace on the high \nscorers table.\n\nPlease Enter Your Name: ");
    gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
    gtk_widget_show(label);

    name_box = gtk_entry_new_with_max_length(30);
    gtk_entry_set_text(GTK_ENTRY(name_box), "");
    gtk_entry_set_editable (GTK_ENTRY(name_box), TRUE);
    gtk_entry_set_visibility(GTK_ENTRY(name_box),TRUE);
    gtk_box_pack_start (GTK_BOX (vbox), name_box, FALSE, FALSE, 0);
    gtk_widget_show(name_box);

    button = gtk_button_new_with_label ("DONE");
    gtk_signal_connect (GTK_OBJECT (button), "clicked",GTK_SIGNAL_FUNC(destroynewhighscore),window);
    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
    gtk_widget_show(button);

    gtk_widget_show(window);
  }
}

gint destroynewhighscore(GtkWidget *widget, gpointer data)
{
  FILE *outfile;
  FILE *infile;
  gchar *player_name, names[5][80];
  int scores[5], read_count = 0, write_count = 0;
  int won = 0;
  
  player_name = gtk_entry_get_text(GTK_ENTRY(name_box));
  infile = fopen ("highscores.txt", "r");
  if (infile)
  {
    while( (fscanf(infile,"%s\t%d", names[read_count],&scores[read_count])==2) && (read_count<5) )
    {
      read_count++;
    }
    fclose(infile);
  }

  outfile = fopen("highscores.txt","w");
  if (outfile)
  {
    while( ((write_count-won) < read_count) && (write_count < 5) )
    {
      if ((score > scores[write_count])&&(won == 0))
      {
        won=1;
        fprintf(outfile,"%s\n%d\n",player_name,score);
      }
      else
        fprintf(outfile,"%s\n%d\n",names[write_count-won],scores[write_count-won]);

      write_count++;
    }
    //if player falls in last place
    if (won == 0)
      fprintf(outfile,"%s\n%d\n",player_name,score);

    fclose(outfile);
  }

  gtk_widget_destroy(GTK_WIDGET(data));
  return (0);
}



//**************************OPTIONS MENU AND ALL LINKED INFO**************************
void options( int   argc, char *argv[])
{
  optionDrawTag = gtk_timeout_add (50, (GtkFunction)drawOptions, optionsArea);
  if (drawTag>0)
  {
    gtk_timeout_remove (drawTag);
    eventDraw(area,NULL,NULL);
  }
  pause=TRUE;
  gtk_widget_show_all (optionswindow);
}


void showColorsel(GtkWidget *widget, gpointer data)
{
  GtkWidget *button;

  if (csDialog == NULL)
  {
     csDialog = gtk_color_selection_dialog_new ("Selected color fills piece");
     gtk_signal_connect (GTK_OBJECT(csDialog),"destroy", GTK_SIGNAL_FUNC(destroyColorsel),NULL);

     colorSel = GTK_COLOR_SELECTION_DIALOG(csDialog)->colorsel;
     gtk_signal_connect(GTK_OBJECT(colorSel),"color_changed", GTK_SIGNAL_FUNC(changeColor), data);

     button = GTK_COLOR_SELECTION_DIALOG(csDialog)->ok_button;
     gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(destroyColorsel), NULL);
     button = GTK_COLOR_SELECTION_DIALOG(csDialog)->cancel_button;
     gtk_signal_connect(GTK_OBJECT(button),"clicked", GTK_SIGNAL_FUNC(destroyColorsel), NULL);
  }
  gtk_widget_show (csDialog);
}

void changeColor(GtkWidget *widget, gpointer data)
{
  gdouble colorArray[4];
  int temp = (int)data;

  gtk_color_selection_get_color (GTK_COLOR_SELECTION(colorSel), colorArray);
  colors[temp].red = (gushort)(0xFFFF *colorArray[0]);
  colors[temp].green = (gushort)(0xFFFF *colorArray[1]);
  colors[temp].blue = (gushort)(0xFFFF *colorArray[2]);
}

void destroyColorsel(GtkWidget *widget, gpointer data)
{
  if (csDialog != NULL)
  {
    gtk_widget_destroy (csDialog);
    csDialog = NULL;
  }
}

void wackyFunc (GtkWidget *widget, gpointer data)
{
  int temp = (int)data;

  wackyBool[temp] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(wackyColor[temp]));
}

gboolean drawOptions(GtkWidget *widget, GdkEvent *event, gpointer data)
//draws pieces to options screen
{
  int wid=12, hei=12, count;
  int x, y;
  //color
  static GdkColormap *colormap = NULL;
  static GdkGC *gc = NULL;
  GdkColor color;
  int randomred = rand(), randomgreen = rand(), randomblue = rand();
  gboolean randomSet;
  int optionsMatrix[27][3];
  
  for(y=0;y<27;y++)
    for(x=0;x<3;x++)
      optionsMatrix[y][x] = 0;
  optionsMatrix[1][1] = 1;
  optionsMatrix[2][1] = 1;
  optionsMatrix[1][2] = 1;
  optionsMatrix[2][2] = 1;
  
  optionsMatrix[4][1] = 2;
  optionsMatrix[5][0] = 2;
  optionsMatrix[5][1] = 2;
  optionsMatrix[5][2] = 2;
  
  optionsMatrix[7][1] = 3;
  optionsMatrix[8][1] = 3;
  optionsMatrix[9][1] = 3;
  optionsMatrix[10][1] = 3;
  
  optionsMatrix[12][1] = 4;
  optionsMatrix[13][1] = 4;
  optionsMatrix[13][2] = 4;
  optionsMatrix[14][2] = 4;
  
  optionsMatrix[17][1] = 5;
  optionsMatrix[18][1] = 5;
  optionsMatrix[16][2] = 5;
  optionsMatrix[17][2] = 5;
  
  optionsMatrix[20][1] = 6;
  optionsMatrix[21][1] = 6;
  optionsMatrix[22][1] = 6;
  optionsMatrix[20][2] = 6;
  
  optionsMatrix[24][1] = 7;
  optionsMatrix[25][2] = 7;
  optionsMatrix[26][2] = 7;
  optionsMatrix[24][2] = 7;
  
  y=0;
  
  if (colormap == NULL)
  {
    colormap = gdk_colormap_get_system();
    gc = gdk_gc_new(widget->window);
  }  

  //Game Board
  while(y<27)
  {
    x=0;
    while(x<3)
    {
      randomSet = FALSE;
      //color selector for each object
      for (count=0;count<7;count++)
      {
        if (optionsMatrix[y][x]==count+1)		//square
        {
          color.red=colors[count].red;
          color.green=colors[count].green;
          color.blue=colors[count].blue;
	  randomSet = wackyBool[count];
	  break;
        }
      }

      if (randomSet)
      {
        color.red=(gushort)(0xFFFF * randomred);
        color.green=(gushort)(0xFFFF * randomgreen);
        color.blue=(gushort)(0xFFFF * randomblue);
      }

      gdk_color_alloc(colormap,&color);
      gdk_gc_set_foreground(gc, &color);
      if (optionsMatrix[y][x]!=0)
      {
        gdk_draw_rectangle(widget->window, gc, TRUE, (x*wid)+1, (y*hei)+1,wid-2,hei-2);
	gdk_draw_rectangle(widget->window, widget->style->white_gc, FALSE, (x*wid), y*hei,wid-1,hei-1);
      }
      x++;
    }
    y++;
  }

  return (TRUE);
}


void destroyoptions(GtkWidget *widget, gpointer data)
{
  int count = 0;
  if (optionDrawTag>0)gtk_timeout_remove (optionDrawTag);
  drawTag = gtk_timeout_add (50, (GtkFunction)eventDraw, area);

  for (;count<7; count++)
    randomSet[count] = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(randomSpinner[count]));
  pause = FALSE;
  gtk_widget_hide(GTK_WIDGET(data));
}




//**************************HELP DIALOG BOX*******************************************
void help( int argc, char *argv[])
{ 
  pause = TRUE;   
  gtk_widget_show_all (helpwindow);
}

void destroyhelp(GtkWidget *widget, gpointer data)
{ 
  pause = FALSE; 
  gtk_widget_hide (helpwindow);
}




//**************************PAUSE******************************************************
void pauseFunc(int argc,char *argv[])
{
  if (pause)
  {
    pause=FALSE;
    drawTag = gtk_timeout_add (50, (GtkFunction)eventDraw, area);
  }
  else
  {
    if (drawTag>0)
    {
      gtk_timeout_remove (drawTag);
      eventDraw(area,NULL,NULL);
    }
    pause=TRUE;
    eventDraw(area,NULL,NULL);
  }
}




//*************************DRAWS PLAYING BOARD*****************************************
gboolean eventDraw(GtkWidget *widget, GdkEvent *event, gpointer data)
//draws board and pieces to screen
{
  int wid=width/sizex, hei=height/sizey, count;
  int x, y=0;
  //color
  static GdkColormap *colormap = NULL;
  static GdkGC *gc = NULL;
  GdkColor color;
  gchar printScore[30]=" ";
  int randomred = rand(), randomgreen = rand(), randomblue = rand();
  gboolean randomSet;
  int spaceFix;

  if (wid>hei)
    wid=hei;
  else
    hei=wid;
  spaceFix = (int)((width - (wid * sizex)) / 2);

  if (colormap == NULL)
  {
    colormap = gdk_colormap_get_system();
    gc = gdk_gc_new(widget->window);
  }

  //SCORE
  sprintf (printScore,"Score: %d",score);
  gtk_label_set_text(GTK_LABEL(scoreLabel),printScore);

  //Game Board
  while(y<sizey)
  {
    x=0;
    while(x<sizex)
    {
      randomSet = FALSE;
      //color selector for each object
      for (count=0;count<7;count++)
      {
        if (mat[y][x]==count+1)		//square
        {
          color.red=colors[count].red;
          color.green=colors[count].green;
          color.blue=colors[count].blue;
	  randomSet = wackyBool[count];
	  break;
        }
      }

      if (randomSet)
      {
        color.red=(gushort)(0xFFFF * randomred);
        color.green=(gushort)(0xFFFF * randomgreen);
        color.blue=(gushort)(0xFFFF * randomblue);
      }

      gdk_color_alloc(colormap,&color);
      gdk_gc_set_foreground(gc, &color);
      if (mat[y][x]!=0)
      {

        gdk_draw_rectangle(widget->window, gc, TRUE, (x*wid)+1+spaceFix, (y*hei)+1,wid-2,hei-2);
	gdk_draw_rectangle(widget->window, widget->style->white_gc, FALSE, (x*wid)+spaceFix, y*hei,wid-1,hei-1);
      }
      else
        gdk_draw_rectangle(widget->window, widget->style->black_gc, TRUE, (x*wid)+spaceFix, y*hei,wid,hei);
      x++;
    }
    y++;
  }
  
  //MESSAGES
  if (message == 1)
  {
    GdkFont *font;
    gchar string[] = "GAME OVER";
    font = gdk_font_load("10x20");
    if (font != NULL)
    {
      gdk_draw_string(widget->window, font, widget->style->white_gc,(int)((width/2)-40),(int)((height/2)-20), string);
      gdk_font_unref(font);
    }
  }
  else if (pause)
  {
    GdkFont *font;
    gchar string[] = "PAUSE";
    font = gdk_font_load("10x20");
    if (font != NULL)
    {
      gdk_draw_string(widget->window, font, widget->style->white_gc,(int)((width/2)-25),(int)((height/2)-20), string);
      gdk_font_unref(font);
    }
  }

  return (TRUE);
}



//**************************MESSAGING*************************************************
gboolean eventConfigure(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{
  width = event->width;
  height = event->height;
  return (TRUE);
}

gint eventDestroy( GtkWidget *widget, GdkEvent *event, gpointer data)
{
  gtk_main_quit();
  return (0);
}

gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
{ return (FALSE);
}

gint eventFocus(GtkWidget *widget, GdkEvent *event, gpointer data)
{ return(TRUE);
}



//**************************KEY PRESS*************************************************
gint eventPressKey(GtkWidget *widget, GdkEvent *event, gpointer data)
//this function handles the key presses.  If a key is pressed the proper
// function is called from this function.
{
  GdkEventKey *key = (GdkEventKey *)event;
  if(key->keyval==65361)		//left arrow
    moveleft();
  if(key->keyval==65362)		//up arrow
    changestate();
  if(key->keyval==65363)		//right arrow
    moveright();
  if(key->keyval==65364)		//down arrow
    movedown();
  return (TRUE);
}



//**************************NEW PIECE*************************************************
gboolean newpiece()
//this function gets a new piece
{
  int count=0, total=0;
  for (;count<7;count++)
    total+=randomSet[count];

  piece = rand()%total;

  total=0;
  for (count=0;count<7;count++)
  {
    total += randomSet[count];
    if (piece<total)
    {
      piece = count+1;
      break;
    }
  }

  check();
  posx[0]=(int)sizex/2;
  posy[0]=0;
  state = 1;

  if(piece==1)			//square
  {
    posx[1] = posx[0]+1;
    posy[1] = 0;
    posx[2] = posx[0];
    posy[2] = 1;
    posx[3] = posx[0]+1;
    posy[3] = 1;
  }
  else if(piece==2)		//T figure
  {
    posy[0] = 1;
    posx[1] = posx[0]-1;
    posy[1] = 1;
    posx[2] = posx[0];
    posy[2] = 0;
    posx[3] = posx[0]+1;
    posy[3] = 1;
  }
  else if(piece==3)		//line
  {
    posy[0] = 2;
    posx[1] = posx[0];
    posy[1] = 0;
    posx[2] = posx[0];
    posy[2] = 1;
    posx[3] = posx[0];
    posy[3] = 3;
  }
  else if(piece==4)		//'S' Figure
  {
    posy[0] = 1;
    posx[1] = posx[0]+1;
    posy[1] = 1;
    posx[2] = posx[0];
    posy[2] = 0;
    posx[3] = posx[0]+1;
    posy[3] = 2;
  }
  else if(piece==5)		//backwards 'S'
  {
    posy[0] = 1;
    posx[1] = posx[0]-1;
    posy[1] = 1;
    posx[2] = posx[0];
    posy[2] = 0;
    posx[3] = posx[0]-1;
    posy[3] = 2;
  }
  else if(piece==6)		//'L'
  {
    posx[1] = posx[0]-1;
    posy[1] = 0;
    posx[2] = posx[0]+1;
    posy[2] = 0;
    posx[3] = posx[0]+1;
    posy[3] = 1;
  }
  else if(piece==7)		//backwards 'L'
  {
    posx[1] = posx[0]+1;
    posy[1] = 0;
    posx[2] = posx[0]-1;
    posy[2] = 0;
    posx[3] = posx[0]-1;
    posy[3] = 1;
  }
  
  //sets the piece to the proper entries
  if ((mat[posy[0]][posx[0]]==0)&&
      (mat[posy[1]][posx[1]]==0)&&
      (mat[posy[2]][posx[2]]==0)&&
      (mat[posy[3]][posx[3]]==0))
  {
    mat[posy[0]][posx[0]]=piece;
    mat[posy[1]][posx[1]]=piece;
    mat[posy[2]][posx[2]]=piece;
    mat[posy[3]][posx[3]]=piece;

    return (TRUE);
  }
  message = 1;
  return (FALSE);
}



//**************************PIECE MOVEMENT*************************************************
gboolean movedown()
//this function moves the piece one position down.
{
  if (( (posy[0]+1) >= sizey)||
      ( (posy[1]+1) >= sizey)||
      ( (posy[2]+1) >= sizey)||
      ( (posy[3]+1) >= sizey)||
      (pause) ){
    return (FALSE);
  }
	
  //checks to see if either space is blank or space is occupied by
  // object itself
  if( ( (mat[posy[0]+1][posx[0]] == 0) ||
        ( (((posy[0]+1) == posy[1]) && (posx[0]==posx[1])) ||
	  (((posy[0]+1) == posy[2]) && (posx[0]==posx[2])) ||
	  (((posy[0]+1) == posy[3]) && (posx[0]==posx[3]))
	)
      )&&
      ( (mat[posy[1]+1][posx[1]] == 0) ||
        ( (((posy[1]+1) == posy[0]) && (posx[1]==posx[0])) ||
          (((posy[1]+1) == posy[2]) && (posx[1]==posx[2])) ||
	  (((posy[1]+1) == posy[3]) && (posx[1]==posx[3]))
	)
      )&&
      ( (mat[posy[2]+1][posx[2]] == 0) ||
        ( (((posy[2]+1) == posy[0]) && (posx[2]==posx[0])) ||
          (((posy[2]+1) == posy[1]) && (posx[2]==posx[1])) ||
	  (((posy[2]+1) == posy[3]) && (posx[2]==posx[3]))
	)
      )&&
      ( (mat[posy[3]+1][posx[3]] == 0) ||
        ( (((posy[3]+1) == posy[0]) && (posx[3]==posx[0])) ||
          (((posy[3]+1) == posy[1]) && (posx[3]==posx[1])) ||
	  (((posy[3]+1) == posy[2]) && (posx[3]==posx[2]))
	)
      ))
  {
    mat[posy[0]][posx[0]] = 0;
    mat[posy[1]][posx[1]] = 0;
    mat[posy[2]][posx[2]] = 0;
    mat[posy[3]][posx[3]] = 0;
    posy[0]++;
    posy[1]++;
    posy[2]++;
    posy[3]++;
    mat[posy[0]][posx[0]]=piece;
    mat[posy[1]][posx[1]]=piece;
    mat[posy[2]][posx[2]]=piece;
    mat[posy[3]][posx[3]]=piece;

    return (TRUE);
  }

  return (FALSE);
}

void moveright()
//this function moves the piece one position to the right.
{
  if (( (posx[0]+1) >= sizex)||
      ( (posx[1]+1) >= sizex)||
      ( (posx[2]+1) >= sizex)||
      ( (posx[3]+1) >= sizex)||
      (pause) ){
    return ;
  }

  //checks to see if either space is blank or space is occupied by
  // object itself
  if( ( (mat[posy[0]][posx[0]+1] == 0) ||
        ( ((posy[0] == posy[1]) && ((posx[0]+1)==posx[1])) ||
	  ((posy[0] == posy[2]) && ((posx[0]+1)==posx[2])) ||
	  ((posy[0] == posy[3]) && ((posx[0]+1)==posx[3]))
	)
      )&&
      ( (mat[posy[1]][posx[1]+1] == 0) ||
        ( ((posy[1] == posy[0]) && ((posx[1]+1)==posx[0])) ||
          ((posy[1] == posy[2]) && ((posx[1]+1)==posx[2])) ||
	  ((posy[1] == posy[3]) && ((posx[1]+1)==posx[3]))
	)
      )&&
      ( (mat[posy[2]][posx[2]+1] == 0) ||
        ( ((posy[2] == posy[0]) && ((posx[2]+1)==posx[0])) ||
          ((posy[2] == posy[1]) && ((posx[2]+1)==posx[1])) ||
	  ((posy[2] == posy[3]) && ((posx[2]+1)==posx[3]))
	)
      )&&
      ( (mat[posy[3]][posx[3]+1] == 0) ||
        ( ((posy[3] == posy[0]) && ((posx[3]+1)==posx[0])) ||
          ((posy[3] == posy[1]) && ((posx[3]+1)==posx[1])) ||
	  ((posy[3] == posy[2]) && ((posx[3]+1)==posx[2]))
	)
      ))
  {
    mat[posy[0]][posx[0]] = 0;
    mat[posy[1]][posx[1]] = 0;
    mat[posy[2]][posx[2]] = 0;
    mat[posy[3]][posx[3]] = 0;
    posx[0]++;
    posx[1]++;
    posx[2]++;
    posx[3]++;
    mat[posy[0]][posx[0]]=piece;
    mat[posy[1]][posx[1]]=piece;
    mat[posy[2]][posx[2]]=piece;
    mat[posy[3]][posx[3]]=piece;
  }
}

void moveleft()
//this function moves the piece one position to the left.
{
  if (( (posx[0]-1) < 0)||
      ( (posx[1]-1) < 0)||
      ( (posx[2]-1) < 0)||
      ( (posx[3]-1) < 0)||
      (pause) ){
    return ;
  }

  //checks to see if either space is blank or space is occupied by
  // object itself
  if( ( (mat[posy[0]][posx[0]-1] == 0) ||
        ( ((posy[0] == posy[1]) && ((posx[0]-1)==posx[1])) ||
	  ((posy[0] == posy[2]) && ((posx[0]-1)==posx[2])) ||
	  ((posy[0] == posy[3]) && ((posx[0]-1)==posx[3]))
	)
      )&&
      ( (mat[posy[1]][posx[1]-1] == 0) ||
        ( ((posy[1] == posy[0]) && ((posx[1]-1)==posx[0])) ||
          ((posy[1] == posy[2]) && ((posx[1]-1)==posx[2])) ||
	  ((posy[1] == posy[3]) && ((posx[1]-1)==posx[3]))
	)
      )&&
      ( (mat[posy[2]][posx[2]-1] == 0) ||
        ( ((posy[2] == posy[0]) && ((posx[2]-1)==posx[0])) ||
          ((posy[2] == posy[1]) && ((posx[2]-1)==posx[1])) ||
	  ((posy[2] == posy[3]) && ((posx[2]-1)==posx[3]))
	)
      )&&
      ( (mat[posy[3]][posx[3]-1] == 0) ||
        ( ((posy[3] == posy[0]) && ((posx[3]-1)==posx[0])) ||
          ((posy[3] == posy[1]) && ((posx[3]-1)==posx[1])) ||
	  ((posy[3] == posy[2]) && ((posx[3]-1)==posx[2]))
	)
      ))
 {
    mat[posy[0]][posx[0]] = 0;
    mat[posy[1]][posx[1]] = 0;
    mat[posy[2]][posx[2]] = 0;
    mat[posy[3]][posx[3]] = 0;
    posx[0]--;
    posx[1]--;
    posx[2]--;
    posx[3]--;
    mat[posy[0]][posx[0]]=piece;
    mat[posy[1]][posx[1]]=piece;
    mat[posy[2]][posx[2]]=piece;
    mat[posy[3]][posx[3]]=piece;
  }
}

void changestate()
//changes the state of the object.
{
  if (pause)
    return;

  if (piece == 2)		//T
  {
    if (state == 1)
    {
      if (mat[posy[0]+1][posx[0]]==0)
      {
        mat[posy[1]][posx[1]] = 0;
	posy[1] = posy[0]+1;
	posx[1] = posx[0];
	mat[posy[1]][posx[1]] = piece;
	state = 2;
      }
    }
    else if (state == 2)
    {
      if ((mat[posy[0]][posx[0]-1]==0)&&(posx[0]!=0))
      {
        mat[posy[2]][posx[2]] = 0;
	posy[2] = posy[0];
	posx[2] = posx[0]-1;
	mat[posy[2]][posx[2]] = piece;
	state = 3;
      }
    }
    else if (state == 3)
    {
      if (mat[posy[0]-1][posx[0]]==0)
      {
        mat[posy[3]][posx[3]] = 0;
	posy[3] = posy[0]-1;
	posx[3] = posx[0];
	mat[posy[3]][posx[3]] = piece;
	state = 4;
      }
    }
    else if (state == 4)
    {
      if ((mat[posy[0]][posx[0]+1]==0)&&((posx[0]+1)<sizex))
      {
        mat[posy[1]][posx[1]] = 0;
	posy[1] = posy[2];
	posx[1] = posx[2];
	posy[2] = posy[3];
	posx[2] = posx[3];
	posy[3] = posy[0];
	posx[3] = posx[0]+1;
	mat[posy[3]][posx[3]] = piece;
	state = 1;
      }
    }
  }
  //-------------------------------
  else if (piece == 3)		//LINE
  {
    if (state == 1)
    {
      if ( (mat[posy[0]][posx[0]-1] == 0) &&
           (mat[posy[0]][posx[0]+1] == 0) &&
	   (mat[posy[0]][posx[0]+2] == 0) &&
	   ((posx[0]+2)<sizex) && (posx[0]!=0) )
      {
        mat[posy[1]][posx[1]] = 0;
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[1] = posy[0];
	posx[1] = posx[0]-1;
	posy[2] = posy[0];
	posx[2] = posx[0]+1;
	posy[3] = posy[0];
	posx[3] = posx[0]+2;
	mat[posy[1]][posx[1]] = piece;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 2;
      }
    }
    else if (state == 2)
    {
      if ( (mat[posy[0]-2][posx[0]] == 0) &&
           (mat[posy[0]-1][posx[0]] == 0) &&
	   (mat[posy[0]+1][posx[0]] == 0) &&
	   ((posx[0]-2)>=0) &&
	   ((posx[0]+1)<sizex) )
      {
        mat[posy[1]][posx[1]] = 0;
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[1] = posy[0]-2;
	posx[1] = posx[0];
	posy[2] = posy[0]-1;
	posx[2] = posx[0];
	posy[3] = posy[0]+1;
	posx[3] = posx[0];
	mat[posy[1]][posx[1]] = piece;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 1;
      }
    }
  }
  //-------------------------------
  else if (piece == 4)		//'S'
  {
    if (state == 1)
    {
      if ( (mat[posy[0]+1][posx[0]] == 0) &&
	   (mat[posy[0]+1][posx[0]-1] == 0) &&
	   (posx[0]!=0) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0]+1;
	posx[2] = posx[0]-1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0];
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 2;
      }
    }
    else if (state == 2)
    {
      if ( (mat[posy[0]-1][posx[0]] == 0) &&
	   (mat[posy[0]+1][posx[0]+1] == 0) &&
	   ((posx[0]+1)<sizex) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0]-1;
	posx[2] = posx[0];
	posy[3] = posy[0]+1;
	posx[3] = posx[0]+1;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 1;
      }
    }
  }
  //-------------------------------
  else if (piece == 5)		//backwards 'S'
  {
    if (state == 1)
    {
      if ( (mat[posy[0]+1][posx[0]] == 0) &&
	   (mat[posy[0]+1][posx[0]+1] == 0) &&
	   ((posx[0]+1)<sizex))
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0]+1;
	posx[2] = posx[0]+1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0];
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 2;
      }
    }
    else if (state == 2)
    {
      if ( (mat[posy[0]-1][posx[0]] == 0) &&
	   (mat[posy[0]+1][posx[0]-1] == 0) &&
	   (posx[0]!=0) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0]-1;
	posx[2] = posx[0];
	posy[3] = posy[0]+1;
	posx[3] = posx[0]-1;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 1;
      }
    }
  }
  //-------------------------------
  else if (piece == 6)		//'L'
  {
    if (state == 1)
    {
      if ( (mat[posy[0]-1][posx[0]] == 0) &&
           (mat[posy[0]-1][posx[0]+1] == 0) &&
	   (mat[posy[0]+1][posx[0]] == 0) &&
	   ((posx[0]+1)<sizex) )
      {
        mat[posy[1]][posx[1]] = 0;
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[1] = posy[0]-1;
	posx[1] = posx[0];
	posy[2] = posy[0]-1;
	posx[2] = posx[0]+1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0];
        mat[posy[1]][posx[1]] = piece;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 2;
      }
    }
    else if (state == 2)
    {
      if ( (mat[posy[0]][posx[0]+1] == 0) &&
	   (mat[posy[0]][posx[0]+2] == 0) &&
	   ((posx[0]+2)<sizex) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0];
	posx[2] = posx[0]+1;
	posy[3] = posy[0];
	posx[3] = posx[0]+2;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 3;
      }
    }
    else if (state == 3)
    {
      if ( (mat[posy[0]+1][posx[0]-1] == 0) &&
	   (mat[posy[0]+1][posx[0]] == 0) &&
	   (posx[0]!=sizex) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0]+1;
	posx[2] = posx[0]-1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0];
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 4;
      }
    }
    else if (state == 4)
    {
      if ( (mat[posy[0]][posx[0]-1] == 0) &&
           (mat[posy[0]][posx[0]+1] == 0) &&
	   (mat[posy[0]+1][posx[0]+1] == 0) &&
	   ((posx[0]+1)<sizex) &&
	   (posx[0]!=sizex) )
      {
        mat[posy[1]][posx[1]] = 0;
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[1] = posy[0];
	posx[1] = posx[0]-1;
	posy[2] = posy[0];
	posx[2] = posx[0]+1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0]+1;
        mat[posy[1]][posx[1]] = piece;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 1;
      }
    }
  }
  //-------------------------------
  else if (piece == 7)		//backwards 'S'
  {
    if (state == 1)
    {
      if ( (mat[posy[0]-1][posx[0]] == 0) &&
           (mat[posy[0]+1][posx[0]] == 0) &&
	   (mat[posy[0]+1][posx[0]+1] == 0) &&
	   ((posx[0]+1)<sizex) )
      {
        mat[posy[1]][posx[1]] = 0;
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[1] = posy[0]-1;
	posx[1] = posx[0];
	posy[2] = posy[0]+1;
	posx[2] = posx[0];
	posy[3] = posy[0]+1;
	posx[3] = posx[0]+1;
        mat[posy[1]][posx[1]] = piece;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 2;
      }
    }
    else if (state == 2)
    {
      if ( (mat[posy[0]][posx[0]-2] == 0) &&
	   (mat[posy[0]][posx[0]-1] == 0) &&
	   ((posx[0]-2)>=0) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0];
	posx[2] = posx[0]-2;
	posy[3] = posy[0];
	posx[3] = posx[0]-1;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 3;
      }
    }
    else if (state == 3)
    {
      if ( (mat[posy[0]-1][posx[0]-1] == 0) &&
	   (mat[posy[0]+1][posx[0]] == 0) &&
	   (posx[0]!=0) )
      {
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[2] = posy[0]-1;
	posx[2] = posx[0]-1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0];
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 4;
      }
    }
    else if (state == 4)
    {
      if ( (mat[posy[0]][posx[0]+1] == 0) &&
           (mat[posy[0]][posx[0]-1] == 0) &&
	   (mat[posy[0]+1][posx[0]-1] == 0) &&
	   ((posx[0]+1)<sizex) &&
	   (posx[0]!=0))
      {
        mat[posy[1]][posx[1]] = 0;
        mat[posy[2]][posx[2]] = 0;
        mat[posy[3]][posx[3]] = 0;
	posy[1] = posy[0];
	posx[1] = posx[0]+1;
	posy[2] = posy[0];
	posx[2] = posx[0]-1;
	posy[3] = posy[0]+1;
	posx[3] = posx[0]-1;
        mat[posy[1]][posx[1]] = piece;
        mat[posy[2]][posx[2]] = piece;
        mat[posy[3]][posx[3]] = piece;
        state = 1;
      }
    }
  }
}



//**************************LINE CHECKER********************************************
void check()
//this function checks if a line is filled, and then gets rid
// of that line and brings all other lines down.
{
  int y=sizey-1, x;

  //looks for a filled row
  while (y>=0)
  {
    x=0;
    while(x<sizex)
    {
      if(mat[y][x] == 0)
        break;
        
      //if a row is filled it is removed and all rows on top move down one.
      x++;
      if (x==sizex)
      {
        int c=1, delay;
        score+=10;
        
        //change speed every ten lines
        if((level<10)&&((score%100)==0))
        {  
          level++;
        
          if (level==2) delay = 220;
          else if (level==3) delay = 205;
          else if (level==4) delay = 190;
          else if (level==5) delay = 175;
          else if (level==6) delay = 160;
          else if (level==7) delay = 145;
          else if (level==8) delay = 130;
          else delay = 115;
         
          if (secondTag>0)gtk_timeout_remove (secondTag);
          secondTag = gtk_timeout_add (delay, (GtkFunction)linker, NULL);
        }
        
        while((y-c)>=0)
        {  
          x=0;
          while(x<sizex)
          {
            mat[(y-c)+1][x]=mat[y-c][x];
            x++;
          }
          c++;
        }
        y++;
      }
    }
    y--;
  }
}



//**************************LINKER*************************************************** 
gint linker(gpointer data)
//this function links the playing functions.  When a new piece is 
// needed this function asks for one.  If not it moves the piece 
// down one position, till game is over.
{
  if (pause)
    return (TRUE);
  if (!movedown())
    if (!newpiece())
    {
      newhighscore(1,"");
      if (drawTag>0)gtk_timeout_remove(drawTag);
      eventDraw(area,NULL, NULL);
      return (FALSE); 		//end of game
    }
  return (TRUE);
}
