/**************************************************************************/
/*                             Hookto   Utility                           */
/*                                                                        */
/*                                 M\Cooper                               */
/*                                PO Box 237                              */
/*                        St. David, AZ 85630-0237                        */
/*                     -------------------------------                    */
/*                         thegrendel@theriver.com                        */
/*                http://personal.riverusers.com/~thegrendel/             */
/*                                                                        */
/**************************************************************************/

#include <ctype.h>
#include <conio.h>
#include "srch.h"

#define FILE_OPENING_ERROR 3
#define FILENAME_MAXLEN 8
#define CR "\n"
#define FILE_SUFFIX ".hk2"
#define MAXLEN 30
#define LINE_LEN 80
#define NOARGS 1
#define INCREMENT 1
#define SPACE ' '
#define WD 8
#define BINGOLEN 8
#define SINGLE 1
#define NULL_ 0
#define MAXSTRLEN 80
#define FILEPREFIXLEN 7
#define BLOTTO '@'
#define XOUT '@'
#define WILDCARD '?'
#define FILLCHAR '_'

#define PRINTMSG(X) printf( X );\
fprintf( fp, "%s", X );\
fprintf( fp, "%s", CR )

#define FORMATMSG(Y) strcpy( tempstr, Y );\
center( tempstr )


#define CRET() printf( CR )

#define BUFFERSIZE 8192


typedef enum { FALSE, TRUE } Boolean;



void getword( char *boardword, char *lset, char *filename );
void center ( char *string_to_center );
char *strsubtract( char *mainstr, char *substr );
Boolean isanagram( char *letterset, char *word );
Boolean wordtest(  char *boardword, char *letterset, char *word );

void main( int argc, char **argv )
{

   char letterset [ MAXLEN ],
        boardword [ MAXLEN ],
        filename [ MAXLEN ];

	 if( argc < NOARGS + 2 )
	    {
	    printf( "\n" );
            printf( "\nEnter the word on the board ... " );
            gets( boardword );
	    puts("Enter your tiles ... " );
	    gets( letterset );
     strcpy( filename, "word.lst" );
	    }
	 else
     if( argc == NOARGS + 2 )
	       {
        strcpy( boardword, *( argv + 1 ) );
        strcpy( letterset, *( argv + 2 ) );
        strcpy( filename, "word.lst" );
        }
   else
     {
     strcpy( boardword, *( argv + 1 ) );
     strcpy( letterset, *( argv + 2 ) );
     strcpy( filename,  *( argv + 3 ) );
     }

	 getword( boardword, letterset, filename );
}



/**********************************WORDTEST********************************/
/* Function tests if word is constructible from Word on Board & Letterset */
/*      Args in: char * onboardword, char *letterset, char *word          */
/*   Returns: error_flag == TRUE (1) if constructible, FALSE (0) if not   */
/**************************************************************************/

Boolean wordtest(  char *onboardword, char *letterset, char *word )
{

   char *diffstr;

      if( !strstr( word, onboardword ) )
         return( FALSE ); 


      diffstr = strsubtract( word, onboardword );
          
      if( !isalpha( *diffstr ) )
         return( FALSE ); 

      if( isanagram( letterset, diffstr ) )
         return( TRUE );  


       return( FALSE );
}

/*************************************************************/
void getword( char *boardword, char *letter_set, char *filename )
{

	char	l_set [ MAXLEN ],
		word [ MAXLEN ],
                bword [ MAXLEN ],
		tempstr [ MAXLEN + 1 ],
		targetfile [ MAXLEN ],
                wd [ WD ],
  bar [ LINE_LEN + 1 ],
  double_bar [ LINE_LEN + 1],
  savefilename [ MAXLEN ];

	FILE *fptr,
      *fp;

	int fnamelen,
            dl;
	long wcount = 0L;

   char ad0[] = "HOOKTO",
        Name[] = "M\\Cooper",
        ad1[] = "PO Box 237",
        ad2[] = " St. David, AZ 85630-0237",
        ad3[] = "thegrendel@theriver.com",
        ad4[] = "http://personal.riverusers.com/~thegrendel",
        Underline[] = "--------",
        *ptr;

      strncpy( savefilename, letter_set, FILEPREFIXLEN );
      while ( ptr = strchr( savefilename, '?') )
             *ptr = FILLCHAR;
      *( savefilename + FILEPREFIXLEN ) = NULL;
      strcat( savefilename, FILE_SUFFIX );



	   memset( bar, '-', LINE_LEN );
	   *( bar + LINE_LEN ) = NULL;
	   memset( double_bar, '=', LINE_LEN );
	   *( double_bar + LINE_LEN ) = NULL;



	   strcpy( l_set, letter_set );


	   if( !( fptr = fopen( filename, "rt" ) ) )
		 {
		 printf( "\7\7\7Cannot open Wordfile!" );
		 exit( FILE_OPENING_ERROR );
		 }
      if( setvbuf( fptr, NULL, _IOFBF, BUFFERSIZE ) )
         exit( FILE_OPENING_ERROR + 1 );



      if( !( fp = fopen( savefilename, "wt" ) ) )
          {
          printf( "\7\7Cannot open file to save words in!" );
          exit( FILE_OPENING_ERROR );
          }

       if( setvbuf( fp, NULL, _IOFBF, BUFFERSIZE ) )
          exit( FILE_OPENING_ERROR + 2 );





	   /*************opening credits*************/
	   clrscr();

    PRINTMSG(double_bar);

    FORMATMSG(ad0);
    PRINTMSG(tempstr);
    CRET();

    FORMATMSG(Underline);
    PRINTMSG(tempstr);
    CRET();

    FORMATMSG(Name);
    PRINTMSG(tempstr);
    CRET();

    FORMATMSG(Underline);
    PRINTMSG(tempstr);
    CRET();
  
    FORMATMSG(ad1);
    PRINTMSG(tempstr);
    CRET();

    FORMATMSG(ad2);
    PRINTMSG(tempstr);
    CRET();
  
    FORMATMSG(ad3);
    PRINTMSG(tempstr);
    CRET();
  
    FORMATMSG(ad4);
    PRINTMSG(tempstr);
    CRET();

    PRINTMSG(double_bar);
    CRET();

   /****************************************/




     sprintf( tempstr,
            "Now searching word file = %s = for matches." , filename );
     center( tempstr ); 
     printf( "\n\n%s\n", tempstr );


		 /*********************Main Loop*************/	 
		  while( fgets( word, MAXLEN, fptr ) != NULL )

			if( wordtest( boardword, letter_set, word ) )
			   {
                           dl = strlen( word ) - strlen( boardword);
                           if( dl >= BINGOLEN )
                               {
                               strcpy( bword, "*" );
                               strcat( bword, word );
                               fprintf( fp, "%s", bword );
                               }
                           else  
			       fprintf( fp, "%s", word );
			   wcount++;
			   }
		  /*******************************************/


          

         sprintf( tempstr, "%ld match(es) saved in file === %s ===.",
                  wcount, savefilename );
         center( tempstr );
         printf( "\n\n%s\n\n\n", tempstr );

         fprintf( fp, CR );
         fprintf( fp, CR );
         sprintf( tempstr, 
        "%ld word(s) can be hooked onto = %s = using tile set = %s =.",
          wcount, boardword, letter_set );
          center( tempstr );
          fprintf( fp, "%s", tempstr );


         fclose( fptr );
         fclose ( fp );

         return;

}




char *strsubtract( char *mainstr, char *substr )
{
   char buffer_a [MAXSTRLEN],
        buffer_b [MAXSTRLEN],
        *dpos;
   register char *t_pos,
                 *ptra;
   static char diffstr [MAXSTRLEN];

      strcpy( buffer_a, mainstr );
      strcpy( buffer_b, substr );
      ptra = buffer_a;
      dpos = diffstr;

      while( *ptra )
          {
          if( ( t_pos = strchr( buffer_b, *ptra ) ) == NULL )
              {
              *dpos = *ptra;
              dpos++;
               } 
           else 
              *t_pos = BLOTTO;
           ptra++;
          }

         *dpos = 0;


         return( diffstr );

}


/**********************************ISANAGRAM*******************************/
/*       Function tests if word is constructible from Letterset           */
/*                 Args in: char *letterset, char *word                   */
/*   Returns: error_flag == TRUE (1) if constructible, FALSE (0) if not   */
/**************************************************************************/

Boolean isanagram( char *letterset, char *word )
{
	Boolean error_flag = TRUE;
	static char dup_lset[ MAXLEN ];
	register char *letpos;

	 strcpy( dup_lset, letterset );
         strcat( dup_lset, "\n" );

		while( *word )
			{
			if( ( letpos  = strchr( dup_lset, *word++ ) ) != NULL )
				*letpos = XOUT;
      else
         if( ( letpos = strchr( dup_lset, WILDCARD ) ) != NULL ) 
            *letpos = XOUT;

			else
				{ error_flag = FALSE; break; }
			}

		return( error_flag );
}



void center( char *str )
{
   int padding;
   char st [ LINE_LEN + INCREMENT ];

	 padding = LINE_LEN / 2 - strlen( str ) / 2;
	 memset( st, SPACE, padding );
	 *( st + padding ) = NULL;  //Terminate string
	 strcat( st, str );
	 strcpy( str, st );

	 return;
}
