/* xbm2bin.c -- (c) Chris Gerber, 1998 
 */
#include <stdio.h>
#include <stdlib.h>
#include "xbm2bin.h"

/*--- Constants ---*/
#define N_BITS 8

/*--- Types ---*/
typedef char byte[N_BITS];

/*--- Function Prototypes ---*/
int processArgs( int, char ** );
char *bits_to_char ( void );
void output( FILE *, char *);
void bintobyte (unsigned char, byte );
char *make_line( char *,char * );
char *xsize( char * );
int ysize( int );

/*--- Global Constants ---*/
const char *usage = "usage: %s filename [-r] [-xN] [-yN]\n";

/*--- Global Variables ---*/ 
char *oFile;
int reverse = 0;
int xResize = 1, yResize = 1;
int index = 0, rowIndex = 0;

unsigned char bindigit[2] = { '0', '1' };

int main(int argc, char *argv[])
{
  char *p;
  FILE *fp;

  #ifdef DEBUG
   printf( "DEBUG: DEBUG Mode ON.\n" );
  #endif

  if (processArgs( argc, argv ) == 0)
    return 1;

  p = bits_to_char();

  if ((fp = fopen( oFile, "w" )) == NULL) {
    printf( "Error: Couldn't open %s.\n", oFile );
    return 1;
  }

  output( fp, p );
  close( fp );

  free( p );
  return 0;
}

int processArgs( int argc, char *argv[] )
{
  int i=2,x;

  if (--argc < 1)
  {
    printf( usage, argv[0] );
    return 0;

  }
  oFile = argv[1];
  #ifdef DEBUG
   printf("DEBUG: output file = %s\n", oFile );
  #endif

  while (i <= argc)
  {
    #ifdef DEBUG
     printf( "DEBUG: Arg %d\n", i );
    #endif
    if (argv[i][0] == '-') {
      switch (argv[i][1])
      {
        case 'r': case 'R':		/* reverse video option */
          reverse = 1;
          bindigit[0] = '1', bindigit[1] = '0';
          #ifdef DEBUG
           printf( "DEBUG: Reverse mode ON.\n" );
          #endif
          break;
        case 'x': case 'X':		/* x resize option */
          xResize = (int) (argv[i][2] - 0x30);
          #ifdef DEBUG
           printf( "DEBUG: X Scaling = %2X.\n", xResize );
          #endif
          break;
       case 'y': case 'Y':             /* y resize option */
          yResize = (int) (argv[i][2] - 0x30);
          #ifdef DEBUG
           printf( "DEBUG: Y Scaling = %d.\n", yResize );
          #endif
          break;
      }
    }
    i++;
  }
  return 1;
}

char *bits_to_char ()
{
  int i;
  byte thebyte;
  unsigned char *data, *p, mask;

  #ifdef DEBUG1
   printf("\nDEBUG: bits_to_char()\n" );
  #endif

  p = data = (unsigned char *)malloc( WIDTH * HEIGHT );
  if (data == NULL) {
    printf("error: Could not malloc.\n");
    exit( 1 );
  }

  for (i=0; i < ((WIDTH/N_BITS)*HEIGHT); i++) {
    bintobyte( (unsigned char) BITS[i], thebyte );
    memcpy( p, thebyte, N_BITS );
    p += N_BITS;
  }
  #ifdef DEBUG1
   printf("\nDEBUG: return\n" );
  #endif

  return (char *)data;
}

void bintobyte (unsigned char c, byte b)
{ 
  int i=0;
  unsigned char mask;

  for (mask = 0x01, i=0; i < N_BITS; mask <<= 1, i++ ) {
    b[i] = ((c & mask)==mask) ? bindigit[1] : bindigit[0];
  }
}

void output( FILE *fp, char *data )
{
  int row;
  char *line = (char *)malloc( WIDTH + 1 );
  if (line == NULL) return;

  #ifdef DEBUG
   printf("DEBUG: output() malloc'ed new char string.\n");
  #endif

  for (row = 0; row < HEIGHT; row++)
  {
    if (ysize(row)) {
      make_line( line, data );
      fprintf( fp, "%s\n", line ); 

      #ifdef DEBUG1
       printf( "DEBUG:  wrote \"%s\"\n", line );
      #endif
    } else {
      index += WIDTH;
      #ifdef DEBUG
       printf( "DEBUG:  skipping row %d\n", row );
      #endif
    }
  }

  free( line );
}

char *make_line( char *where, char *fromwhat )
{
  int i, realWidth;

  for (i=0; i < WIDTH; i++, index++) {
    where[i] = fromwhat[index];
  }
  where[i] = 0;

  #ifdef DEBUG1
   printf("DEBUG:   make_line() line before resize = \"%s\"\n", where );
  #endif
  return xsize( where );
}

char *xsize( char *what )
{
  char c;
  int putIndex, getIndex;

  if (xResize > 1)
  {
    putIndex = 0; getIndex = 0;
    while (getIndex < WIDTH) {
      c = what[getIndex];
      what[putIndex] = c;
      getIndex += xResize;
      putIndex++;
    }
    what[putIndex] = 0;

    #ifdef DEBUG1
     printf("DEBUG:   xsize() -> \"%s\"\n", what );
    #endif

  }
  return what;
}

int ysize( int row )
{
  int pIndex;

  if (yResize > 1)
  {
    pIndex = 0;
    while ( pIndex < row ) {
      pIndex += yResize;
    }
    #ifdef DEBUG1
     if (row == pIndex)
       printf("DEBUG:  ysize(%d ?= %d) = TRUE\n", row, pIndex );
     else
       printf("DEBUG:  ysize(%d ?= %d) = FALSE\n", row, pIndex );
    #endif

    return ((row==pIndex) ? 1 : 0);
  }
}