static const char rcsid[] = "$Header: c:/mctex/imagen/rcs/epson.c 1.1 91/08/05 23:40:37 ROOT_DOS Exp Locker: ROOT_DOS $";

/* Copyright (c) 1993 Neal Becker
 * All rights reserved.
 * Permission to copy for any purpose is hereby granted
 * so long as this copyright notice remains intact.
*/

/*
$Log:	epson.c $
 * Revision 1.1  91/08/05  23:40:37  ROOT_DOS
 * Initial revision
 * 
*/

#include "epson.h"


#if defined( __MSDOS__ ) && !defined( __GNUC__ )
#  include <mem.h>
#endif /* __MSDOS__ */

#include <stdlib.h>
#include "PROTO.h"

BitMapRow::BitMapRow() {
  if( ( Bits = new char[ HBytes ] ) == 0 )
    GripeOutOfMemory( HBytes, "BitMap" );
  Printed = Length = 0;
  Start = MaxShort;
}

void BitMapRow::Clear() {
  memset( Bits, 0, HBytes );
  Printed = Length = 0;
  Start = MaxShort;
}
  
BitMap::BitMap() {
  for( int i = 0; i < ( BitMapRows + ExtraRows ); i++ ) {
    if( ( Rows[ i ] = new BitMapRow ) == NULL )
      GripeOutOfMemory( sizeof( BitMapRow ), "BitMap" );
  }
}

void BitMap::Clear() {
  for( int i = 0; i < ( BitMapRows + ExtraRows ); i++ )
    Rows[ i ]->Clear();
}

#if defined __MSDOS__ && !defined( __GNUC__ )

#include <alloc.h>
void ReportMem() {
  fprintf( stderr,"%lX Bytes Left\n", (unsigned long)farcoreleft() );
}

#else /* __MSDOS__ */

void ReportMem() {}

#endif /* __MSDOS__ */

void epson::PrintBitMap( BitMap& theBitMap ) {
  for( DviPos = 0; DviPos < BitMapRows; DviPos ++ ) {
    if( theBitMap.NeedToPrint( DviPos ) )
      PrintRow( theBitMap, DviPos );
  }
  if( ferror( fp ) )
    panic( "error writing output" );
}

void epson::PrintRow( BitMap& theBitMap, int Row ) {
  SetVpos( Row );
  Output8Rows( theBitMap, Row );
};

void epson::Output8Rows( BitMap& theBitMap, int Row ) {
  int FirstBytePos = theBitMap.FindFirst( Row );
  int RealSpaces = FirstBytePos / 3;
  int TotalSpaces = RealSpaces + LeftMarginSpaces;
  int HByte = 0;			/* current byte pos */
  if( TotalSpaces > 0 ) {
    if( HasFastSpace ) {
      fputs( "\x1b" "f0", fp );
      fputc( TotalSpaces, fp );
    }
    else {
      for( int i = 0; i < TotalSpaces; i++ )
        fputc( ' ', fp );
    }
    HByte += RealSpaces * 3;
  }
  int LastBytePos = theBitMap.FindLength( Row );
  int NumBits = 8 * ( LastBytePos - HByte + 1 );
  char n1 = NumBits & 0xff;
  char n2 = (unsigned)(NumBits) >> 8;
  fputs( "\x1b" "*" "\x3", fp );
  fputc( n1, fp );
  fputc( n2, fp );
  char Bytes[ 8 ];
  for( ; HByte <= LastBytePos; HByte++ ) {
    Encode8Bytes( theBitMap, Row, HByte, Bytes );
    for( int HBit = 7; HBit >= 0; HBit-- )
      fputc( Bytes[ HBit ], fp );
  }
  Eol();
  for( int V = 0; V < 8; V++ ) {
    int TheRow = Row + ( V * 3 );
    if( TheRow >= BitMapRows ) break;
    theBitMap.Mark( TheRow );
  }
}


void epson::Encode8Bytes( BitMap& theBitMap, int Row, int HByte, char Bytes[ 8 ] ) {
  memset( Bytes, 0, 8 );
  for( int VBit = 0; VBit < 8; VBit++ ) {
    int TheRow = Row + ( VBit * 3 );
    if( TheRow >= BitMapRows ) break;
    char TheChar = theBitMap.Rows[ TheRow ]->Bits[ HByte ];
    char TheMask = BitMask[ 7 - VBit ];
    for( int HBit = 0; HBit <= 7; HBit++ )
      if( TheChar & BitMask[ HBit ] )
        Bytes[ HBit ] |= TheMask;
  }
}

int BitMap::FindLength( int Row ) {
  for( int i = 0, l = 0; i < 8; i++ ) {
    int TheRow = Row + ( i * 3 );
    if( TheRow >= BitMapRows ) break;
    l = max( l, Rows[ TheRow ]->Length );
  }
  return l;
}

int BitMap::FindFirst( int Row ) {
  for( int i = 0, l = 0xff; i < 8; i++ ) {
    int TheRow = Row + ( i * 3 );
    if( TheRow >= BitMapRows ) break;
    l = min( l, Rows[ TheRow ]->Start );
  }
  return l;
}

void epson::SetVpos( int n ) {
  while( n - PrintPos > 255 )
    Vaddv( 255 );
  Vaddv( n - PrintPos );
}

void epson::Vaddv( int n ) {
  fputs( "\x1b" "J", fp );
  fputc( n, fp );
  PrintPos += n;
}
