

      
       /****************************************************
       *
       *       file d:\lsu\cujhuff3.c
       *
       ****************************************************/


#include "d:\lsu\cujhuff.h"




/*   
          code_and_write_output_file(...

          Look at each byte in the input file.
          Code each byte using the item_array.coded.
          When the output buffer (packed bits) is on a byte
          boundary, then write it out to the output file
*/


code_and_write_output_file(item_array, in_file_name, 
                           out_file_name, file_header)
   char   in_file_name[],
          out_file_name[];
   struct item_struct item_array[];
   struct header_struct *file_header;
{
   char  in_buffer[IB_LENGTH],
         out_buffer[OB_LENGTH],
         r[80];

   int   coding,
         counter,
         in_file_desc,
         j,
         not_end_of_file,
         out_file_desc;

   long  bytes_read,
         bytes_written,
         i,
         in_counter,
         in_file_displacement,
         out_counter;


   open_files(in_file_name, out_file_name,
              &in_file_desc, &out_file_desc);

   lseek(in_file_desc, 0L, 0);
   file_header->in_file_length = lseek(in_file_desc, 0L, 2);
   lseek(in_file_desc, 0L, 0);

   output_file_header(file_header, out_file_desc);


   clear_input_buffer(in_buffer);
   clear_output_buffer(out_buffer);

   in_counter           = 0;
   out_counter          = 0;
   in_file_displacement = 0;
   not_end_of_file      = 1;
   counter              = 0;

   while(not_end_of_file){

      position_in_file_displacement(in_file_desc,
                                    in_file_displacement);

      bytes_read = my_read(in_file_desc, in_buffer, IB_LENGTH);
/*printf("\n\t\tread %d bytes", bytes_read);*/

      if(bytes_read < IB_LENGTH)
         not_end_of_file = 0;

      i       = 0;
      coding  = 1;

         while(coding){

            if((counter % 100) == 0)
               printf("\n> Coding - counter=%d\n", counter);
            if((counter % 10) == 0)
               printf(".");
            counter++;
            code_byte(item_array, i, in_buffer, out_buffer,
                      &in_counter, &out_counter);
            i++;
/*printf("\n\n> in_counter=%ld out_counter=%ld\n", 
in_counter, out_counter);*/
                          
                         /**************************************
                         *
                         *   The rest of this function looks
                         *   at the output buffer and writes it
                         *   out when the buffer is on a byte
                         *   boundary.
                         *
                         ***************************************/

            if( (out_counter/8 >= 100)           &&
                (out_counter % 8 == 0) ){
               printf("\n> Writing to output file");
/*printf("\n\t> out count = %d", out_counter/8);*/
               write_output(out_file_desc, out_buffer,
out_counter/8);
               out_counter = 0;
               clear_output_buffer(out_buffer);
            }  /* ends if 100 bytes in out_buffer and on a byte
boundary */

            if(i == bytes_read){
               in_file_displacement = in_file_displacement + i;
               coding = 0;

            }  /* ends if the in_buffer is empty  */

         }  /* ends while coding  */

   }  /*  ends while not_end_of_file  */

   printf("\n> Writing to output file");
   write_output(out_file_desc, out_buffer, out_counter/8);

   close(in_file_desc);
   close(out_file_desc);

}  /* ends code_and_write_output_file  */





/*    
         open_files(...

         Open the input and output file.
*/

open_files(in_file_name, out_file_name, in_file_desc,
out_file_desc)
   char in_file_name[], out_file_name[];
   int        *in_file_desc, *out_file_desc;
{
   int a ,b;

   *out_file_desc = open(out_file_name, O_RDWR | O_CREAT |
O_BINARY,
                         S_IWRITE);
   *in_file_desc  = open(in_file_name, O_RDWR | O_CREAT | O_BINARY,
                         S_IWRITE);

}  /*  ends open_files        */






/*
   output_file_header(...

   This function outputs the short file header
   to the beginning of the compressed file.

*/


output_file_header(file_header, out_file_desc)
   int    out_file_desc;
   struct header_struct *file_header;
{
        int     i;

        char    out_buffer[sizeof(struct header_struct)],

                *charptr,
                name[80];

        charptr = (char *)file_header;
        for(i=0; i<((sizeof(struct header_struct))); i++)
           out_buffer[i] = *charptr++;

        write_output(out_file_desc, out_buffer, 
                     sizeof(struct header_struct));

}       /* ends output_item_array  */





/*    
         clear_input_buffer(in_buffer)

         This clears out the input buffer.
*/

clear_input_buffer(in_buffer)
   char in_buffer[];
{
   int i;
   for(i=0; i<IB_LENGTH; i++)
      in_buffer[i] = ' ';
}  /* ends clear_in_buffer  */




/*    
         clear_output_buffer(out_buffer)

         This clears out the output buffer.
*/

clear_output_buffer(out_buffer)
   char out_buffer[];
{
   int i;
   for(i=0; i<OB_LENGTH; i++)
      out_buffer[i] = 0x00;
}  /*  ends clear_out_buffer  */






/*    
          position_in_file_displacement(...

          This sets the pointer to the input file
          to the desired located specificied by
          in_file_discplacement.
*/


position_in_file_displacement(in_file_desc, in_file_displacement)
   int  in_file_desc;
   long in_file_displacement;
{
   long position;
   position = lseek(in_file_desc, 0L, 0);
   position = lseek(in_file_desc, in_file_displacement, 0);

}  /*  ends position_in_file_displacement  */




/*    
         code_byte(...

         This function looks at the input file byte and
         sets the bits in the output buffer.
*/

code_byte(item_array, byte, in_buffer, out_buffer, in_counter,
out_counter)
   char   in_buffer[], out_buffer[];
   long   byte;
   long   *in_counter, *out_counter;
   struct item_struct item_array[];
{
   char out_code[CODE_LENGTH];
   int  i;

   find_output_code(item_array, out_code, in_buffer[byte]);
   *in_counter = *in_counter + 1;

            /*****************************************
            *
            *   Set the output code to either ONE or
            *   ZERO.
            *
            ******************************************/

   for(i=0; i<CODE_LENGTH; i++){
      if(out_code[i] == ONE){
         set_bit_to_1(out_counter, out_buffer);
         *out_counter = *out_counter + 1;
      }  /* ends if out_code == ONE */

      if(out_code[i] == ZERO){
         clear_bit_to_0(out_counter, out_buffer);
         *out_counter = *out_counter + 1;
      }  /* ends if out_code == ZERO */
   }         /* ends loop over i             */
}         /*  ends code_byte             */




/*   
           find_output_code(...

           Search through the item_array to find the correct

           character and its code.
*/


find_output_code(item_array, out_code, in_character)
   struct item_struct item_array[];
   char   out_code[];
   char   in_character;
{
   int i, j, searching;

   i = 0;
   searching = 1;
   while(searching){
      if(item_array[i].character == in_character){
         searching = 0;
         for(j=0; j<CODE_LENGTH; j++){
            out_code[j] = item_array[i].coded[j];
         }  /* ends loop over j          */
      }     /* ends if there is a match  */
      else
         i++;
   }            /* ends while searching         */
}            /* ends find_output_code         */




/*   
           set_bit_to_1(out_counter, out_buffer)

           This function sets the specified bit in the output
           buffer to a 1.
*/


set_bit_to_1(out_counter, out_buffer)
   long *out_counter;
   char out_buffer[];
{
   int  bit_in_byte,
        byte_in_buffer;
   char temp;
   bit_in_byte          = *out_counter % 8;
   byte_in_buffer = *out_counter / 8;
   switch(bit_in_byte){
      case 0:
        temp = out_buffer[byte_in_buffer] | SET_BIT_ZERO;
        break;
      case 1:
        temp = out_buffer[byte_in_buffer] | SET_BIT_ONE;
        break;
      case 2:
        temp = out_buffer[byte_in_buffer] | SET_BIT_TWO;
        break;
      case 3:
        temp = out_buffer[byte_in_buffer] | SET_BIT_THREE;
        break;
      case 4:
        temp = out_buffer[byte_in_buffer] | SET_BIT_FOUR;

        break;
      case 5:
        temp = out_buffer[byte_in_buffer] | SET_BIT_FIVE;
        break;
      case 6:
        temp = out_buffer[byte_in_buffer] | SET_BIT_SIX;
        break;
      case 7:
        temp = out_buffer[byte_in_buffer] | SET_BIT_SEVEN;
        break;
   }  /* ends switch           */
   out_buffer[byte_in_buffer] = temp;
}     /* ends set_bit_to_1 */






/*  
           clear_bit_to_0(out_counter, out_buffer)

           This function sets the specified bit in the
           output buffer to 0.
*/


clear_bit_to_0(out_counter, out_buffer)
   long *out_counter;
   char out_buffer[];
{
   int  bit_in_byte,
        byte_in_buffer;
   char temp;

   bit_in_byte    = *out_counter % 8;
   byte_in_buffer = *out_counter / 8;

   switch(bit_in_byte){
      case 0:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_ZERO;
        break;
      case 1:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_ONE;
        break;
      case 2:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_TWO;
        break;
      case 3:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_THREE;
        break;
      case 4:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_FOUR;
        break;
      case 5:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_FIVE;
        break;
      case 6:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_SIX;
        break;

      case 7:
        temp = out_buffer[byte_in_buffer] & CLEAR_BIT_SEVEN;
        break;
   }  /* ends switch */
   out_buffer[byte_in_buffer] = temp;
}  /* ends clear_bit_to_0 */







/*    
          write_output(...

          This function writes the output buffer to the
          output file.
*/

write_output(out_file_desc, out_buffer, number_of_bytes)
   char out_buffer[];
   int  out_file_desc;
   long number_of_bytes;
{
   int bytes_written;

   bytes_written = write(out_file_desc, out_buffer,
number_of_bytes);
/*printf("\n> wrote %d bytes", bytes_written);*/

}  /*  ends write_output  */
/* End of File */
