; /*  you can execute this file to compile it (if you're using lattice/SAS C )
lc books
blink from LIB:c.o books.o LIB LIB:lcm.lib LIB:lc.lib LIB:amiga.lib  
quit
*/

#include <MYLIB:ISAMLibPROTO.h>
#include <stdio.h>

struct Library *ISAMBase = NULL;

/* remove proto parm-names if your compiler can't handle them. */
/* remove protos entirely, "   "      "       "     "     "    */

void FFlush ( void );
void MultiScan ( char *str, int len );
void FlushScan ( char *fmt, void *ptr );
void FillOut ( char *str, int strlen, int len );
BOOL HandlePrefix ( int keyno, void **ppprefix, int *pplen );
BOOL HandleKey ( int keyno, void **ppkey );
BOOL HandleRange ( int keyno, int itertype, void **ppfrom, void **ppto );
void EditBook ( void );
void ListCategories ( void );
void ListBooks ( void );
int main ( int argc, char *(argv[]) );


  struct Book {
     /* 00 */  char  Title [30];
     /* 30 */  char  Author [30];
     /* 60 */  char  Publisher [30];
     /* 90 */  UWORD Copyright;
     /* 92 */  char  Category;
     /* 93 */  char  Form;  /* P-aperback, H-ardCover, T-radePB, C-offeeTable */
     /* 94 */  UWORD Pages;
     /* 96 */  float Value;
  }; /*100 */

  struct Category {
     /* 00 */  char Code;
     /* 01 */  char Name [30];
  }; /* 31 */


#define MAXKEYLEN   30
#define MAXKEYLENP1 (MAXKEYLEN+1)


  extern int _OSERR;
  char str80[81];
  FILE *fp;
  int len, i, select, keyno;
  long ErrorCode;
  ULONG  RecNo, tmpRecNo, CountMax, Count;

  char c, FileDev, from [MAXKEYLENP1], to [MAXKEYLENP1], key [MAXKEYLENP1];
  char prefix [MAXKEYLENP1]; 
  char KeyReturn [MAXKEYLENP1];  /* enough for largest key, plus 1 */
  void *KeyRet = &KeyReturn[0];

  void *pfrom, *pto, *pkey, *pprefix;
  int itertype;
  ULONG ISAMHandleB, ISAMHandleC;
  UWORD uwfrom, uwto, uwkey;
  char SpecsFileNameB [] = "DATA:Book.specs";
  char SpecsFileNameC [] = "DATA:BookCat.specs";
  BOOL Lockk;
  float ffrom, fto, fkey;
  struct Book BRec;
  struct Category CRec;

                             
/*--------------------------------- FFlush -----------------------------------*/
void FFlush ()
/* if any string output is cut off because it's too long ( Ex: "%16s") */
/* we don't want the overflow to count for part of the next scanf.     */
{
  char c;

  while ( (c = getchar () ) != '\n' )
    ;

  return;
}


/*------------------------------ FlushScan ----------------------------------*/
void FlushScan ( fmt, ptr )

/* this function preforms a scan, and flushes anything past the first     */
/* whitespace, so we don't start assigning extra input to the next scanf. */

char *fmt;
void *ptr;
{
  scanf ( fmt, ptr );
  FFlush ();
}

/*------------------------------- MultiScan ---------------------------------*/
void MultiScan ( str, len )  /* for those times we want multi-word strings */
char *str;
int len;
{
  char c;

  while ( (c = getchar () ) == ' ' )
    ;

  for ( i=0; ((c != '\n') && ( i < len )); i++ )
  {
    str [i] = c;
    c = getchar ();
  }
  str [i] = '\0';

  if ( c != '\n' )
    FFlush ();

  return;
}


/*-------------------------------- FillOut ----------------------------------*/
void FillOut ( str, strlen, len )
char *str;
int strlen, len;
{
  int i;


  if ( ( str == NULL ) || ( len == 0 ) )
    return;

  for ( i=strlen; i<len; i++ )
    str[i] = ' ';

  return;
}


/*------------------------------ HandlePrefix -------------------------------*/
BOOL HandlePrefix ( keyno, ppprefix, plen )
int keyno, *plen;
void **ppprefix;
{
  switch ( keyno )
  {
    case 0 :
    case 1 : 
    case 2 :
         printf ( "\nprefix :" );
         MultiScan  ( prefix, 10 );
         len = strlen ( prefix );
         *ppprefix = &prefix[0];
         *plen = len;
         printf ( "\n'%s'", prefix );
         printf ( "\n" );
         break;

    case 4 :
         printf ( "\nprefix :" );
         FlushScan  ( "%2s", &prefix );
         len = strlen ( prefix );
         *ppprefix = &prefix[0];
         *plen = len;
         printf ( "\n'%s'", prefix );
         printf ( "\n" );
         ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &prefix[0],
                                            FALSE, ' ', &tmpRecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_NO_SUCH_RECORD :
             printf ( "\nNo such Category." );
             break;

           case OK :
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         if ( ErrorCode != OK )
           return ( FALSE );
         break;

    default:
         break;
  }

  return ( TRUE );
}


/*------------------------------ HandleKey -------------------------------*/
BOOL HandleKey ( keyno, ppkey )
int keyno;
void **ppkey;
{
  switch ( keyno )
  {
    case 0 :
    case 1 : 
    case 2 :
         printf ( "\nkey :" );
         MultiScan  ( key, 10 );
         FillOut ( key, strlen ( key ), 10 );
         *ppkey = &key[0];
         printf ( "\n'%10.10s'", key );
         printf ( "\n" );
         break;

    case 4 :
         printf ( "\nkey :" );
         FlushScan  ( "%2s", &key );
         FillOut ( key, strlen ( key ), 2 );
         *ppkey = &key[0];
         printf ( "\n'%2.2s'", key );
         printf ( "\n" );
         ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &key[0],
                                            FALSE, ' ', &tmpRecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_NO_SUCH_RECORD :
             printf ( "\nNo such Category." );
             break;

           case OK :
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         if ( ErrorCode != OK )
           return ( FALSE );
         break;

    case 5 :
         printf ( "\nkey :" );
         FlushScan  ( "%1s", &key );
         *ppkey = &key[0];
         printf ( "\n'%1.1s'", key );
         printf ( "\n" );
         break;

    case 3 :
    case 6 :
         printf ( "\nkey :" );
         FlushScan  ( "%hu", &uwkey );
         *ppkey = &uwkey;
         printf ( "\n%hu", uwkey );
         printf ( "\n" );
         break;

    case 7 :
         printf ( "\nkey :" );
         FlushScan  ( "%hf", &fkey );
         *ppkey = &fkey;
         printf ( "\n%8.2hf", fkey );
         printf ( "\n" );
         break;

    default:
         break;
  }

  return ( TRUE );;
}


/*----------------------------- HandleRange ------------------------------*/
BOOL HandleRange ( keyno, itertype, ppfrom, ppto )
int keyno, itertype;
void **ppfrom, **ppto;
{
  *ppfrom = NULL;
  *ppto   = NULL;

  switch ( keyno )
  {
    case 0 :
    case 1 :
    case 2 :
         if ( (itertype == 1) || ((itertype >=4) && (itertype <=9)) )
           {
             printf ( "\nfrom :" );
             MultiScan  ( from, 10 );
             FillOut ( from, strlen ( from ), 10 );
             *ppfrom = &from[0];
             printf ( "\n'%10.10s'", from );
             printf ( "\n" );
           }

         if ( (itertype >=2) && (itertype <=7) )
           {
             printf ( "\nto :" );
             MultiScan  ( to, 10 );
             FillOut ( to, strlen ( to ), 10 );
             *ppto = &to[0];
             printf ( "\n'%10.10s'", to );
             printf ( "\n" );
           }
         break;


    case 4 : 
         if ( (itertype == 1) || ((itertype >=4) && (itertype <=9)) )
           {
             printf ( "\nfrom :" );
             FlushScan  ( "%2s", &from );
             FillOut ( from, strlen ( from ), 2 );
             *ppfrom = &from[0];
             printf ( "\n'%2.2s'", from );
             printf ( "\n" );
             ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &from[0],
                                            FALSE, ' ', &tmpRecNo, &CRec );
             switch ( ErrorCode )
             {
               case ERROR_NO_SUCH_RECORD :
                 printf ( "\nNo such Category." );
                 break;

               case OK :
                 break;

               default :
                 printf ( "\nError %ld.", ErrorCode );
                 break;
             }
             if ( ErrorCode != OK )
               return ( FALSE );
           }

         if ( (itertype >=2) && (itertype <=7) )
           {
             printf ( "\nto :" );
             FlushScan  ( "%2s", &to );
             FillOut ( to, strlen ( to ), 2 );
             *ppto = &to[0];
             printf ( "\n'%2.2s'", to );
             printf ( "\n" );
             ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &to[0],
                                            FALSE, ' ', &tmpRecNo, &CRec );
             switch ( ErrorCode )
             {
               case ERROR_NO_SUCH_RECORD :
                 printf ( "\nNo such Category." );
                 break;

               case OK :
                 break;

               default :
                 printf ( "\nError %ld.", ErrorCode );
                 break;
             }
             if ( ErrorCode != OK )
               return ( FALSE );
           }
         break;


    case 5 : 
         if ( (itertype == 1) || ((itertype >=4) && (itertype <=9)) )
           {
             printf ( "\nfrom :" );
             FlushScan  ( "%1s", &from );
             *ppfrom = &from[0];
             printf ( "\n'%1.1s'", from );
             printf ( "\n" );
           }

         if ( (itertype >=2) && (itertype <=7) )
           {
             printf ( "\nto :" );
             FlushScan  ( "%1s", &to );
             *ppto = &to[0];
             printf ( "\n'%1.1s'", to );
             printf ( "\n" );
           }
         break;


    case 3 :
    case 6 :
         if ( (itertype == 1) || ((itertype >=4) && (itertype <=9)) )
           {
             printf ( "\nfrom :" );
             FlushScan  ( "%hu", &uwfrom );
             *ppfrom = &uwfrom;
             printf ( "\n%hu", uwfrom );
             printf ( "\n" );
           }

         if ( (itertype >=2) && (itertype <=7) )
           {
             printf ( "\nto :" );
             FlushScan  ( "%hu", &uwto );
             *ppto = &uwto;
             printf ( "\n%hu", uwto );
             printf ( "\n" );
           }
         break;


    case 7 :
         if ( (itertype == 1) || ((itertype >=4) && (itertype <=9)) )
           {
             printf ( "\nfrom :" );
             FlushScan  ( "%hf", &ffrom );
             *ppfrom = &ffrom;
             printf ( "\n%8.2hf", ffrom );
             printf ( "\n" );
           }

         if ( (itertype >=2) && (itertype <=7) )
           {
             printf ( "\nto :" );
             FlushScan  ( "%hf", &fto );
             *ppto = &fto;
             printf ( "\n%8.2hf", fto );
             printf ( "\n" );
           }
         break;


    default:
         break;
  }

  return ( TRUE );
}


/*-------------------------------- EditBook ---------------------------------*/
void EditBook ()
{
  for (;;)
  {
    printf ( "\nCurrent Record:\n" );

    printf ( "\nTitle     : '%30.30s'", BRec.Title );
    printf ( "\nAuthor    : '%30.30s'", BRec.Author );
    printf ( "\nPublisher : '%30.30s'", BRec.Publisher );
    printf ( "\nCopyright : %4u",       BRec.Copyright );
    printf ( "\nCategory  : '%c'",      BRec.Category );
    printf ( "\nForm      : '%c'",      BRec.Form );
    printf ( "\nPages     : %6u",       BRec.Pages );
    printf ( "\nValue     : %8.2lf",    BRec.Value );

    printf ( "\n\n" );
    

    printf ( "\nEdit: \n" );
    printf ( "\n1 : Title       5 : Category" );
    printf ( "\n2 : Author      6 : Form" );
    printf ( "\n3 : Publisher   7 : Pages" );
    printf ( "\n4 : Copyright   8 : Value" );
    printf ( "\n\n0  : end Edit\n\nSELECT ?" );

    FlushScan ( "%d", &select );
    printf ( "\n" );


    if ( select == 0 )
      break;


    switch ( select )
    {
      case 1 :
         printf ( "\nTitle ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( BRec.Title, str80, 30 );
         break;

      case 2 :
         printf ( "\nAuthor ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( BRec.Author, str80, 30 );
         break;

      case 3:
         printf ( "\nPublisher ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( BRec.Publisher, str80, 30 );
         break;

      case 4 :
         printf ( "\nCopyright Year ?" );
         FlushScan  ( "%hu", &BRec.Copyright );
         break;

      case 5 :
         printf ( "\nCategory ?" );
         FlushScan  ( "%1s", str80 );  
         BRec.Category = toupper ( str80[0] );
         ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &BRec.Category,
                                            FALSE, ' ', &tmpRecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_NO_SUCH_RECORD :
             printf ( "\nNo such Category." );
             break;

           case OK :
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         break;

      case 6 :
         printf ( "\nForm (P/H/T/C) ?" );
         FlushScan  ( "%1s", &BRec.Form );
         BRec.Form = toupper ( BRec.Form );
         break;

      case 7 :
         printf ( "\nNumber of Pages ?" );
         FlushScan  ( "%hu", &BRec.Pages );
         break;

      case 8 :
         printf ( "\nValue ?" );
         FlushScan  ( "%hf", &BRec.Value );
         break;

      default :
         printf ( "\nNo such option." );
         break;
    }

    continue;
  }

  return;
}


/*---------------------------- ListCategories ----------------------------*/
void ListCategories ()
{
  ErrorCode = SetUpISAMIterationRange ( ISAMHandleC, 0, 0, NULL, NULL );
  if ( ErrorCode != OK )
    {
      printf ( "\nCouldn't set up list." );
      printf ( "\nError %ld.", ErrorCode );
      return;
    }
  if (( ErrorCode = CountISAMRecords ( ISAMHandleC, 0, 0L, &Count )) != OK )
    {
      printf ( "\nCouldn't count Categories." );
      printf ( "\nError %ld.", ErrorCode );
      return;
    }
  switch ( Count )
  {
    case 0L : printf ( "\nThere are no Categories." );         break;
    case 1L : printf ( "\nThere is 1 Category." );             break;
    default : printf ( "\nThere are %lu Categories.", Count ); break;
  }
  if ( Count == 0L )
    return;

  for (;;)
  {
    printf ( "\n\nPrint the List to someplace other than the screen? (Y/N) " );
    FlushScan  ( "%1s", &FileDev );
    FileDev = toupper ( FileDev );
    if ( ( FileDev == 'Y' ) || ( FileDev == 'N' ) )
      break;
    printf ( "\nNot an option." );
  }

  if ( FileDev == 'Y' )
    {
      printf ( "\nFile/Device Name: " );
      FlushScan  ( "%80s", str80 );
      if ( ( fp = fopen ( str80, "w" )) == NULL )
        {
          printf ( "\nCouldn't open '%s' for output.", str80 );
          printf ( "\nError: %d", _OSERR );
          return;
        }
    }
   else
    {
      fp = stdout;
    }

  fprintf ( fp, "\n\nCODE ---------- Category ----------\n" );

  fprintf ( fp,   "\n===================================\n" );

  do
    {
      ErrorCode = ReadNextISAMRecord ( ISAMHandleC, 0,
                          FALSE, ' ', &RecNo, &CRec );
      switch ( ErrorCode )
      {
        case OK :
          fprintf ( fp, "\n  %c    %30.30s", CRec.Code, CRec.Name );
          break;

        case ERROR_NO_MORE_RECORDS :
          break;

        default :
          fprintf ( fp, "\nError %ld.", ErrorCode );
          break;
      }
    }
  while ( ErrorCode == OK );

  if ( FileDev == 'Y' )
    {
      fclose ( fp );
    }

  return;  
}


/*------------------------------- ListBooks ------------------------------*/
void ListBooks ()
{
  for (;;)
  {
    printf ( "\nList Books by what key: \n" );
    printf ( "\n1 : Title       5 : Category/Form" );
    printf ( "\n2 : Author      6 : Form" );
    printf ( "\n3 : Publisher   7 : Pages" );
    printf ( "\n4 : Copyright   8 : Value" );
    printf ( "\n\nSELECT ?" );

    FlushScan ( "%d", &select );
    printf ( "\n" );
    if ( ( select < 1 ) || ( select > 8 ) )
      {
        printf ( "\nNo such option." );
        continue;
      }
    keyno = select - 1;
    break;
  }

  for (;;)
  {
    printf ( "\nList by:\n" );
    printf ( "\n1 : All key values." );
    printf ( "\n2 : Range of key values." );
    printf ( "\n3 : One key value." );
    printf ( "\n4 : Key prefix (keys 1/2/3/5 only). " );
    printf ( "\n\nSELECT ?" );

    FlushScan ( "%d", &select );
    printf ( "\n" );
    if ( ( select < 1 ) || ( select > 4 ) )
      {
        printf ( "\nNo such option." );
        continue;
      }
    if ( select==4 )
      switch ( keyno+1 )
      {
        case 1 : case 2 : case 3 : case 5 :
          break;

        default:
          printf ( "\nNot valid for key selected." );
          continue;
      }
    break;
  }

  switch ( select )
  {
    case 1 : 
    case 2 : itertype = ( select == 1 ) ? 0 : 7;
             if ( !HandleRange ( keyno, itertype, &pfrom, &pto ))
               return;
             ErrorCode = SetUpISAMIterationRange ( ISAMHandleB,
                                (UWORD) keyno, (UBYTE) itertype, pfrom, pto );
             break;
             
    case 3 : if ( !HandleKey ( keyno, &pkey) )
               return;
             ErrorCode = SetUpISAMIterationKey ( ISAMHandleB, (UWORD) keyno,
                                                   pkey );
             break;

    case 4 : if ( !HandlePrefix ( keyno, &pprefix, &len) )
               return;
             ErrorCode = SetUpISAMIterationPrefix ( ISAMHandleB, (UWORD) keyno,
                                         pprefix, len );
             break;

    default: break;
  }
  if ( ErrorCode != OK )
    {
      printf ( "\nCouldn't set up list." );
      printf ( "\nError %ld.", ErrorCode );
      return;
    }

  printf ( "\nStop Counting at how many Books: " );
  FlushScan  ( "%lu", &CountMax );
  printf ( "\n" );

  if (( ErrorCode = CountISAMRecords ( ISAMHandleB, (UWORD) keyno,
                                       CountMax, &Count )) != OK )
    {
      printf ( "\nCouldn't count Books." );
      printf ( "\nError %ld.", ErrorCode );
      return;
    }
  switch ( Count )
  {
    case 0L : printf ( "\nThere are no Books" );         break;
    case 1L : printf ( "\nThere is 1 Book" );            break;
    default : printf ( "\nThere are %lu Books", Count ); break;
  }
  printf ( " matching that criteria." );
  if ( Count == 0L )
    return;

  for (;;)
  {
    printf ( "\n\nPrint the List to someplace other than the screen? (Y/N) " );
    FlushScan  ( "%1s", &FileDev );
    FileDev = toupper ( FileDev );
    if ( ( FileDev == 'Y' ) || ( FileDev == 'N' ) )
      break;
    printf ( "\nNot an option." );
  }

  if ( FileDev == 'Y' )
    {
      printf ( "\nFile/Device Name: " );
      FlushScan  ( "%80s", str80 );
      if ( ( fp = fopen ( str80, "w" )) == NULL )
        {
          printf ( "\nCouldn't open '%s' for output.", str80 );
          printf ( "\nError: %d", _OSERR );
          return;
        }
    }
   else
    {
      fp = stdout;
    }
  fprintf ( fp, "\n" );
  fprintf ( fp,
"\nRECNO ----------- TITLE ------------ ----------- AUTHOR -----------" );
  fprintf ( fp,
"\n      --------- PUBLISHER ---------- COPY. CAT. FORM -$VALUE- #PAGES\n" );
  fprintf ( fp,
"\n====================================================================\n" );

  do
    {
      ErrorCode = ReadNextISAMRecord ( ISAMHandleB, (UWORD) keyno,
                          FALSE, ' ', &RecNo, &BRec );
      switch ( ErrorCode )
      {
        case OK :
          fprintf ( fp, "\n%5lu %30.30s %30.30s\n      ", RecNo,
                    BRec.Title, BRec.Author );
          fprintf ( fp, "%30.30s %4hu   %c     %c  %8.2f %6hu\n",
                    BRec.Publisher, BRec.Copyright, BRec.Category, BRec.Form,
                    BRec.Value, BRec.Pages );
          break;

        case ERROR_NO_MORE_RECORDS :
          break;

        default :
          fprintf ( fp, "\nError %ld.", ErrorCode );
          break;
      }
    }
  while ( ErrorCode == OK );

  if ( FileDev == 'Y' )
    {
      fclose ( fp );
    }

  return;  
}


/*================================= MAIN =================================*/

main ( argc, argv )
int argc;
char *(argv[]);
{
  if ( (ISAMBase = OpenLibrary ( "isam.library", 0 )) == NULL )
    {
      printf ( "\nCouldn't open ISAM library.\n\n" );
      exit ( 5 );
    }

  if (( ErrorCode = OpenISAMFile ( SpecsFileNameB, TRUE, 'R', 
                                   TRUE, &ISAMHandleB )) != OK )
    {
      printf ( "\nError %ld.", ErrorCode );
      goto END;
    }
  if (( ErrorCode = OpenISAMFile ( SpecsFileNameC, TRUE, 'R', 
                                   TRUE, &ISAMHandleC )) != OK )
    {
      printf ( "\nError %ld.", ErrorCode );
      goto END;
    }

  for (;;)
  {
    printf ( "\n" );
    printf ( "\n1  : Store  Book     5 : Store  Book Category" );
    printf ( "\n2  : Modify Book     6 : Modify Book Category" );
    printf ( "\n3  : Delete Book     7 : Delete Book Category" );
    printf ( "\n4  : List   Books    8 : List   Book Categories" );
    printf ( "\n\n0  : exit\n\nSELECT ?" );

    FlushScan ( "%d", &select );
    printf ( "\n" );


    if ( select == 0 )
      break;



    switch ( select )
    {
      case 1 :
         printf ( "\nCategory ?" );
         FlushScan  ( "%1s", str80 );  
         BRec.Category = toupper ( str80[0] );
         ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &BRec.Category,
                                            FALSE, ' ', &tmpRecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_NO_SUCH_RECORD :
             printf ( "\nNo such Category." );
             break;

           case OK :
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         if ( ErrorCode != OK )
           break;

         printf ( "\nTitle ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( BRec.Title, str80, 30 );

         printf ( "\nAuthor ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( BRec.Author, str80, 30 );

         printf ( "\nPublisher ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( BRec.Publisher, str80, 30 );

         printf ( "\nCopyright Year ?" );
         FlushScan  ( "%hu", &BRec.Copyright );

         printf ( "\nForm (P/H/T/C) ?" );
         FlushScan  ( "%1s", &BRec.Form );  
         BRec.Form = toupper ( BRec.Form );

         printf ( "\nNumber of Pages ?" );
         FlushScan  ( "%hu", &BRec.Pages );

         printf ( "\nValue ?" );
         FlushScan  ( "%hf", &BRec.Value );


         printf ( "\nEnter a number to Store Book: ('-1' to abort) ");
         FlushScan  ( "%d", &i );
         printf ( "\n" );
         if ( i == -1 )
           break;
       
         ErrorCode = StoreISAMRecord ( ISAMHandleB, &BRec, FALSE, ' ', &RecNo );
         switch ( ErrorCode )
         {
           case OK :
             printf ( "\nRecord# %lu", RecNo );
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         break;
 

      case 2 :
         printf ( "\nRec# :" );
         FlushScan  ( "%lu", &RecNo );
         printf ( "\n" );

         ErrorCode = ReadISAMRecord ( ISAMHandleB, RecNo, FALSE, ' ', &BRec );
         switch ( ErrorCode )
         {
           case ERROR_DELETED_RECORD :
             printf ( "\nThat record has been deleted." );
             break;

           case ERROR_RECORD_TOO_HIGH :
             printf ( "\nThat record number is too high." );
             break;

           case OK :
             break;

           default:
             printf ( "\nError %ld.", ErrorCode );
	 }
         if ( ErrorCode != OK )
           break;

         EditBook ();
           

         printf ( "\nEnter a number to Modify Book: ('-1' to abort) ");
         FlushScan  ( "%d", &i );
         printf ( "\n" );
         if ( i == -1 )
           break;
       
         ErrorCode = ModifyISAMRecord ( ISAMHandleB, RecNo, &BRec );
         switch ( ErrorCode )
         {
           case OK :
             printf ( "\nBook Modified." );
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         break;


      case 3 :
         printf ( "\nRec# :" );
         FlushScan  ( "%lu", &RecNo );
         printf ( "\n" );

         ErrorCode = ReadISAMRecord ( ISAMHandleB, RecNo, FALSE, ' ', &BRec );
         switch ( ErrorCode )
         {
           case ERROR_DELETED_RECORD :
             printf ( "\nThat record has been deleted." );
             break;

           case ERROR_RECORD_TOO_HIGH :
             printf ( "\nThat record number is too high." );
             break;

           case OK :
             printf ( "\nTitle     : '%30.30s'", BRec.Title );
             printf ( "\nAuthor    : '%30.30s'", BRec.Author );
             printf ( "\nPublisher : '%30.30s'", BRec.Publisher );
             printf ( "\nCopyright : %4u",       BRec.Copyright );
             printf ( "\nCategory  : '%c'",      BRec.Category );
             printf ( "\nForm      : '%c'",      BRec.Form );
             printf ( "\nPages     : %6u",       BRec.Pages );
             printf ( "\nValue     : %8.2lf",    BRec.Value );
             printf ( "\n" );
             break;

           default:
             printf ( "\nError %ld.", ErrorCode );
	 }
         if ( ErrorCode != OK )
           break;

         printf ( "\nEnter a number to Delete Book: ('-1' to abort) ");
         FlushScan  ( "%d", &i );
         printf ( "\n" );
         if ( i == -1 )
           break;
       
         ErrorCode = DeleteISAMRecord ( ISAMHandleB, RecNo );
         switch ( ErrorCode )
         {
           case ERROR_DELETED_RECORD :
             printf ( "\nThat record has been deleted." );
             break;

           case ERROR_RECORD_TOO_HIGH :
             printf ( "\nThat record number is too high." );
             break;

           case OK :
             printf ( "\nRecord deleted." );
             break;

           default:
             printf ( "\nError %ld.", ErrorCode );
	 }
         break;
 

      case 4 :
         ListBooks ();
         break;


      case 5 :
         printf ( "\nCategory Code ?" );
         FlushScan  ( "%1s", &CRec.Code );  
         CRec.Code = toupper ( CRec.Code );

         printf ( "\nCategory Name ?" );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( CRec.Name, str80, 30 );


         printf ( "\nEnter a number to Store Category: ('-1' to abort) ");
         FlushScan  ( "%d", &i );
         printf ( "\n" );
         if ( i == -1 )
           break;
       
         ErrorCode = StoreISAMRecord ( ISAMHandleC, &CRec, FALSE, ' ', &RecNo );
         switch ( ErrorCode )
         {
           case ERROR_RECORD_EXISTS :
             printf ( "\nThat Category already exists." );
             break;

           case OK :
             printf ( "\nRecord# %lu", RecNo );
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         break;


      case 6 :
         printf ( "\nCategory Code ?" );
         FlushScan  ( "%1s", &CRec.Code );  

         ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &CRec.Code,
                                            FALSE, ' ', &RecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_NO_SUCH_RECORD :
             printf ( "\nNo such Category." );
             break;

           case OK :
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         if ( ErrorCode != OK )
           break;
         printf ( "\n'%30.30s'\n", CRec.Name );
         
         printf ( "\nNew Category Code ?" );
         FlushScan  ( "%1s", str80 );  
         CRec.Code = toupper ( str80[0] );

         printf ( "\nNew Category Name ?" );
         printf ( "\n(currently: '%30.30s')\n", CRec.Name );
         MultiScan  ( str80, 30 );     
         FillOut ( str80, strlen ( str80 ), 30 );
         strncpy ( CRec.Name, str80, 30 );

         printf ( "\nEnter a number to Modify Category: ('-1' to abort) ");
         FlushScan  ( "%d", &i );
         printf ( "\n" );
         if ( i == -1 )
           break;
       
         ErrorCode = ModifyISAMRecord ( ISAMHandleC, RecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_RECORD_EXISTS :
             printf ( "\nThat Category already exists." );
             break;

           case OK :
             printf ( "\nCategory Modified." );
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         break;


      case 7 :
         printf ( "\nCategory Code ?" );
         FlushScan  ( "%1s", &CRec.Code );  

         ErrorCode = ReadUniqueISAMRecord ( ISAMHandleC, 0, &CRec.Code,
                                            FALSE, ' ', &RecNo, &CRec );
         switch ( ErrorCode )
         {
           case ERROR_NO_SUCH_RECORD :
             printf ( "\nNo such Category." );
             break;

           case OK :
             break;

           default :
             printf ( "\nError %ld.", ErrorCode );
             break;
         }
         if ( ErrorCode != OK )
           break;

         printf ( "\nCategory Code: '%c'",      CRec.Code );
         printf ( "\n         Name: '%30.30s'", CRec.Name );
         printf ( "\n" );

         printf ( "\nEnter a number to Delete Category: ('-1' to abort) ");
         FlushScan  ( "%d", &i );
         printf ( "\n" );
         if ( i == -1 )
           break;
       
         ErrorCode = DeleteISAMRecord ( ISAMHandleC, RecNo );
         switch ( ErrorCode )
         {
           case OK :
             printf ( "\nCategory deleted." );
             break;

           default:
             printf ( "\nError %ld.", ErrorCode );
	 }
         break;


      case 8 :
         ListCategories ();
         break;


      default :
         printf ( "\nNo such option." );
         break;
    }

    continue;
  }  /* for */


END:

  if ( ISAMHandleB && (( ErrorCode = CloseISAMFile ( ISAMHandleB )) != OK ))
    printf ( "\nError %ld.", ErrorCode );

  if ( ISAMHandleC && (( ErrorCode = CloseISAMFile ( ISAMHandleC )) != OK ))
    printf ( "\nError %ld.", ErrorCode );

  CloseLibrary ( ISAMBase );

  printf ( "\n\n" );

  return;
}
