/*
 * ADR.C - address book.  Illustrates use of index file functions.
 *
 *                      Copyright (c) 1987, Jim Mischel
 * Modifications:
 *
 * 08/21/87 - jim - original coding
 *
 */

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "index.h"

typedef struct {
  char first_name[31],
       last_name[31],
       business[31],
       street[31],
       city[26],
       state[3],
       zip[10],
       phone1[11],
       phone2[11],
       name_key[21];
} address_rec;

#define ed printf("\033[2J")    /* erase display */
#define el printf("\033[K")     /* erase line */

void cup(int row, int col);
void edit_it(void);
void change_item(int item);
void get_ret(void);
void usage(void);
void lookup(void);
void list_forward(void);
void list_backward(void);
int icmp_string(void *arg1, void *arg2);

char *adr_file;                 /* file descriptor for indexed file routines */
address_rec addr;

int main(int argc, char *argv[])
{
  unsigned offset;
  char c;

  if (!argc) {
    usage();
    return(1);
  }

  offset = (char *) &addr.name_key - (char *) &addr;

  if ((adr_file = iopen(argv[1],sizeof(address_rec),offset,1,icmp_string)) == NULL) {
    printf("\nCannot open file %s\n",argv[1]);
    printf("Error status is %X\n",ierrno);
    return(1);
  }

  do {
    ed;
    cup(3,34);  printf("ADDRESS BOOK");
    cup(24,1);  printf("(L)ookup, (F)orward list, (B)ackward list, (Q)uit");
    cup(23,1);  printf("Enter function ");
    switch (c = toupper(getche())) {
      case 'L' :
        lookup();
        break;
      case 'F' :
        list_forward();
        break;
      case 'B' : list_backward();
    }
  } while (c != 'Q');

  ed;
  iclose(adr_file);
  return(0);
}

void lookup(void)
{
  char quit = 0;
  char tempkey[24];

  do {
    ed;                         /* erase display */
    cup(3,34);  printf("ADDRESS BOOK");
    cup(5,1);   printf(" 1. Key        :");
    cup(6,1);   printf(" 2. First name :");
    cup(7,1);   printf(" 3. Last name  :");
    cup(8,1);   printf(" 4. Business   :");
    cup(9,1);   printf(" 5. Street     :");
    cup(10,1);  printf(" 6. City       :");
    cup(11,1);  printf(" 7. State      :");
    cup(12,1);  printf(" 8. Zip        :");
    cup(13,1);  printf(" 9. Home phone :");
    cup(14,1);  printf("10. Work phone :");
    tempkey[0] = 21;
    cup(5,18);
    cgets(tempkey);
    if (tempkey[1] == 0)
      quit = 1;
    else {
      strcpy(addr.name_key,&tempkey[2]);
      edit_it();
    }
  } while(!quit);
  return;
}

void edit_it(void)
{
  int item;
  char c,
       trash[6];

  if (iread(adr_file,&addr)) {
    cup(23,1); printf("%s Not found.  Add new record? ",addr.name_key);
    if (toupper(getche()) != 'Y')
      return;                   /* not found */
    cup(23,1); el;              /* erase line */
    for (item = 2; item <= 10; change_item(item++));
    if (iwrite(adr_file,&addr)) {
      cup(23,1); printf("Error write.  Status is %X.\n",ierrno);
      get_ret();
      return;
    }
  }
  else {
    cup(5,18);  puts(addr.name_key);
    cup(6,18);  puts(addr.first_name);
    cup(7,18);  puts(addr.last_name);
    cup(8,18);  puts(addr.business);
    cup(9,18);  puts(addr.street);
    cup(10,18); puts(addr.city);
    cup(11,18); puts(addr.state);
    cup(12,18); puts(addr.zip);
    cup(13,18); puts(addr.phone1);
    cup(14,18); puts(addr.phone2);
  }
  do {
    cup(23,1); printf("Enter function * (C,D,Q)");
    cup(23,16);
    switch (c = toupper(getche())) {
      case 'C'  :
        do {
          cup(23,1); el;
          printf("Enter item to change ");
          trash[0] = 3;
          cgets(trash);
          if (trash[1] == 0)
            item = 0;
          else {
            item = atoi(&trash[2]);
            if (item > 1 && item < 11)
              change_item(item);
          }
        } while (item != 0);
        if (irewrite(adr_file,&addr)) { /* update the record */
          cup(23,1);  printf("Error rewrite.  Status is %X\n",ierrno);
          get_ret();
          return;
        }
        break;
      case 'D'  :
        if (idelete(adr_file,&addr)) {
          cup(23,1); printf("Error delete.  Status is %X\n",ierrno);
          get_ret();
          return;
        }
        c = 'Q';
        break;
      case 'Q'  :
        break;
      default   :
        putch('\007');
    } /* switch */
  } while (c != 'Q');
} /* edit_it */

void change_item(int item)
{
  char temp[35];
  switch (item) {
    case 2 :
      cup(6,18);
      temp[0] = 31;
      cgets(temp);
      strcpy(addr.first_name,&temp[2]);
      break;
    case 3 :
      cup(7,18);
      temp[0] = 31;
      cgets(temp);
      strcpy(addr.last_name,&temp[2]);
      break;
    case 4 :
      cup(8,18);
      temp[0] = 31;
      cgets(temp);
      strcpy(addr.business,&temp[2]);
      break;
    case 5 :
      cup(9,18);
      temp[0] = 31;
      cgets(temp);
      strcpy(addr.street,&temp[2]);
      break;
    case 6 :
      cup(10,18);
      temp[0] = 26;
      cgets(temp);
      strcpy(addr.city,&temp[2]);
      break;
    case 7 :
      cup(11,18);
      temp[0] = 3;
      cgets(temp);
      strcpy(addr.state,&temp[2]);
      break;
    case 8 :
      cup(12,18);
      temp[0] = 10;
      cgets(temp);
      strcpy(addr.zip,&temp[2]);
      break;
    case 9 :
      cup(13,18);
      temp[0] = 11;
      cgets(temp);
      strcpy(addr.phone1,&temp[2]);
      break;
    case 10 :
      cup(14,18);
      temp[0] = 11;
      cgets(temp);
      strcpy(addr.phone2,&temp[2]);
      break;
  } /* switch */
} /* change_item */

void list_forward(void)
{
  ed;
  if (istart(adr_file,START_FILE,&addr)) {
    printf("Error starting file.  Error code is %X\n",ierrno);
    return;
  }
  while (!iread_next(adr_file,&addr))
    printf("%s:  %s %s\n",addr.name_key,addr.first_name,addr.last_name);
  get_ret();
}

void list_backward(void)
{
  ed;
  if (istart(adr_file,END_FILE,&addr)) {
    printf("Error starting file.  Error code is %X\n",ierrno);
    return;
  }
  while (!iread_prev(adr_file,&addr))
    printf("%s:  %s %s\n",addr.name_key,addr.first_name,addr.last_name);
  get_ret();
}

void cup(int row, int col)
{
  char rows[6],
       cols[6];
  itoa(row,rows,10);
  itoa(col,cols,10);
  printf("\033[%s;%sH",rows,cols);
}

void get_ret(void)
{
  cup(24,1);  printf("Press any key ... ");
  getche();
}

/*
 * icmp_string() - string comparison routine.  Returns:
 *		-1 if arg1 < arg2
 *		 0 if arg1 == arg2
 *		 1 if arg1 > arg2
 */
int icmp_string(void *arg1, void *arg2)
{
  int r;

  return(((r = strcmp((char *)arg1, (char *)arg2)) == 0) ? 0 :
         (r > 0) ? 1 : -1);
}

void usage(void)
{
  printf("Usage: adr <filename>\n");
}
