/****************************************************************************

    PROGRAM: mail.c

    PURPOSE: Mailing List Program
             Multiple addresses with Create, Edit and Delete
 
    VERSION: 2.00

    DATE:    11/16/88

****************************************************************************/

#include <windows.h>
#include "mail.h"
#include <stdlib.h>

/* GLOBAL VARIABLES */
char szAppName[10];
char szAbout[10];
char szTitle[22];
int MessageLength;
HANDLE hAccelTable;
static HANDLE hInst;

/* FILE GLOBALS */
char szFileName[BUFFER_SIZE];  /* User-selected file name */
char szFirst[26];              /* First record field */
char szLast[26];
char szAddress[41];
char szCity[21];
char szState[3];
char szZip[6];
char szRecord[132];
char szAddressNo[4];
char szFlag[2];
char szHeader[132];
char szBuffer[BUFFER_SIZE];    /* General purpose buffer */
OFSTRUCT ofDataFile;           /* File structure */

/* PRINTING GLOBALS */
int szLineHeight;
int szCharWidth;
int szPageHeight;
int szPageWidth;
int szPagePtr;

/* FORWARD REFERENCES */
long FAR PASCAL MailWndProc(HWND, unsigned, WORD, LONG);
void PASCAL MenuProc(HWND, WORD);
BOOL FAR PASCAL GetFileName(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL SaveAsDialogBoxProc(HWND, unsigned, WORD, LONG);
int read(int, char *, unsigned int);
int write(int, char *, unsigned int);
int GetData(HWND);
BOOL FAR PASCAL EditBoxProc(HWND, unsigned, WORD, LONG);
void recfield(char[], char[], int);
BOOL FAR PASCAL AddressDialogBoxProc(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL DelBoxProc(HWND, unsigned, WORD, LONG);
BOOL PASCAL CreateAddressNo(HWND);
BOOL PASCAL EditAddressNo(HWND);
BOOL PASCAL DelAddressNo(HWND);

/* PROCEDURE FOR ABOUT BOX */
BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
   if (message == WM_COMMAND) {
      EndDialog(hDlg, TRUE);
      return(TRUE);
      }
   else
   if (message == WM_INITDIALOG)
      return(TRUE);
   else
      return(FALSE);
}

/* FIRST-TIME INITIALIZATION */
BOOL MailInit(hInstance)
HANDLE hInstance;
{
   NPWNDCLASS pMailClass;
   /* Load strings from RC file to variables here */
   LoadString(hInstance, IDSNAME, (LPSTR)szAppName, 10);  /* MAIL */
   LoadString(hInstance, IDSABOUT, (LPSTR)szAbout, 10);   /* About */
   MessageLength = LoadString(hInstance, IDSTITLE, (LPSTR)szTitle, 22); /* Title */
   pMailClass = (NPWNDCLASS) LocalAlloc(LPTR, sizeof(WNDCLASS));
   pMailClass->hCursor        = LoadCursor(NULL, IDC_ARROW);
   pMailClass->hIcon          = LoadIcon(hInstance, (LPSTR)szAppName);
   pMailClass->lpszMenuName   = (LPSTR) szAppName;
   pMailClass->lpszClassName  = (LPSTR) szAppName;
   pMailClass->hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
   pMailClass->hInstance      = hInstance;
   pMailClass->style          = CS_HREDRAW | CS_VREDRAW;
   pMailClass->lpfnWndProc    = MailWndProc;
   if (!RegisterClass((LPWNDCLASS)pMailClass))
      /* Initialization failed - windows deallocates all allocated memory */
      return(FALSE);
   LocalFree((HANDLE)pMailClass);
   return(TRUE);  /* Initialization succeeded */
}

/* MAIN PROGRAM PROCEDURE */
int PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, cmdShow)
HANDLE hInstance, hPrevInstance;
LPSTR lpszCmdLine;
int cmdShow;
{
   MSG   msg;
   HDC   hDC;
   HWND  hWnd;
   HMENU hMenu;
   if (!hPrevInstance) {
      /* Call initialization procedure if this is first instance */
      if (!MailInit(hInstance))
         return(FALSE);
      }
   else {
      /* Get data from previous instance */
      GetInstanceData(hPrevInstance,(NPSTR)szAppName, 10);
      GetInstanceData(hPrevInstance,(NPSTR)szAbout, 10);
      GetInstanceData(hPrevInstance,(NPSTR)szTitle, 22);
      }
   hWnd = CreateWindow((LPSTR)szAppName,
                      (LPSTR)szTitle,
                      WS_TILEDWINDOW,
                      0,
                      0,
                      0,
                      0,
                      (HWND)NULL,
                      (HMENU)NULL,
                      (HANDLE)hInstance,
                      (LPSTR)NULL
                      );
   /* Save instance handle for DialogBox */
   hInst = hInstance;
   /* Insert "About..." into system menu */
   hMenu = GetSystemMenu(hWnd, FALSE);
   ChangeMenu(hMenu, 0, NULL, 999, MF_APPEND | MF_SEPARATOR);
   ChangeMenu(hMenu, 0, (LPSTR)szAbout, IDSABOUT, MF_APPEND | MF_STRING);

   /* Disable menu items until file is opened */
   EnableMenuItem(GetMenu(hWnd),
      MENU_PRINT,
      MF_DISABLED | MF_BYCOMMAND);
   EnableMenuItem(GetMenu(hWnd),
      MENU_CREATE,
      MF_DISABLED | MF_BYCOMMAND);
   EnableMenuItem(GetMenu(hWnd),
      MENU_EDIT,
      MF_DISABLED | MF_BYCOMMAND);
   EnableMenuItem(GetMenu(hWnd),
      MENU_DELETE,
      MF_DISABLED | MF_BYCOMMAND);
   /* and grey nonvalid options */
   EnableMenuItem(GetMenu(hWnd),
      MENU_PRINT,
      MF_GRAYED | MF_BYCOMMAND);
   EnableMenuItem(GetMenu(hWnd),
      MENU_CREATE,
      MF_GRAYED | MF_BYCOMMAND);
   EnableMenuItem(GetMenu(hWnd),
      MENU_EDIT,
      MF_GRAYED | MF_BYCOMMAND);
   EnableMenuItem(GetMenu(hWnd),
      MENU_DELETE,
      MF_GRAYED | MF_BYCOMMAND);
            
   /* Load accelerator table */
   hAccelTable = LoadAccelerators(hInst, (LPSTR) "MAIL");
 
   /* Make window visible according to the way the app is activated */
   ShowWindow(hWnd, cmdShow);
   UpdateWindow(hWnd);

   /* Initialize for file I/O */
   memset(szFileName, '\0',BUFFER_SIZE);
   memset(szAddressNo, '\0', sizeof(szAddressNo));
   memset(szHeader, '\0', sizeof(szRecord));
   ClearFields();

   /* Poll messages from event que */
   while
      (GetMessage((LPMSG)&msg, NULL, 0, 0))
      {
      if (TranslateAccelerator(hWnd, hAccelTable, (LPMSG) &msg) == 0)
         {
         TranslateMessage((LPMSG)&msg);
         DispatchMessage((LPMSG)&msg);
         }
      }
   return (int)msg.wParam;
}

/* PROCEDURE FOR WINDOW CLASS */
long FAR PASCAL MailWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
   PAINTSTRUCT ps;
   FARPROC lpprocAbout;
   switch (message) {
   case WM_SYSCOMMAND:
      switch (wParam) {
      case IDSABOUT:
         lpprocAbout = MakeProcInstance((FARPROC)About, hInst);
         DialogBox(hInst, "ABOUTBOX", hWnd, lpprocAbout);
         FreeProcInstance((FARPROC)lpprocAbout);
         break;
      default:
         return(DefWindowProc(hWnd, message, wParam, lParam));
      }
      break;
   case WM_COMMAND:
      MenuProc(hWnd,wParam);
      break;
   case WM_DESTROY:
      PostQuitMessage(0);
      break;
   case WM_PAINT:
      MailPaint(hWnd);
      break;
   default:
      return(DefWindowProc(hWnd, message, wParam, lParam));
      break;
   }
   return (0L);
}

/* PROCEDURE TO PROCESS MENU MESSAGES */
void PASCAL MenuProc(hWnd, wID)
HWND hWnd;
WORD wID;
{
HANDLE hDataFile;
FARPROC lpprocAddress;
int RetVal;
   switch (wID)
      {
      case MENU_NEW:
         ClearFields();
         strcpy(szFileName, "");
         lpprocAddress = MakeProcInstance(SaveAsDialogBoxProc, hInst);
         RetVal = DialogBox(hInst, "SAVEBOX", hWnd, lpprocAddress);
         FreeProcInstance((FARPROC)lpprocAddress);
         if (!RetVal)
            return;
         hDataFile = OpenFile(szFileName,
                             &ofDataFile,
                             OF_PROMPT|OF_CREATE);
         if (hDataFile == -1)
            {
            MessageBox(hWnd,
                      "Cannot Open File",
                      szFileName,
                      MB_OK);
            return;
            }
         /* turn on rest of menu items */
         EnableMenuItem(GetMenu(hWnd),
            MENU_PRINT,
            MF_ENABLED | MF_BYCOMMAND);
         EnableMenuItem(GetMenu(hWnd),
            MENU_CREATE,
            MF_ENABLED | MF_BYCOMMAND);
         EnableMenuItem(GetMenu(hWnd),
            MENU_EDIT,
            MF_ENABLED | MF_BYCOMMAND);
         EnableMenuItem(GetMenu(hWnd),
            MENU_DELETE,
            MF_ENABLED | MF_BYCOMMAND);
         /* Put file name in window */
         strcpy(szTitle+10, szFileName);
         SetWindowText(hWnd, (LPSTR) szTitle);
         memset(szHeader, '\0', sizeof(szRecord));
         InvalidateRect(hWnd, (LPRECT)NULL, TRUE);  /* force repaint */
         break;
      case MENU_OPEN:
         lpprocAddress = MakeProcInstance(GetFileName, hInst);
         RetVal = DialogBox(hInst, "LOADBOX", hWnd, lpprocAddress);
         FreeProcInstance((FARPROC) lpprocAddress);
         if (!RetVal)
            return;
         hDataFile = OpenFile(szFileName,
                             &ofDataFile,
                             OF_READ);
         if (hDataFile == -1)
            {
            MessageBox(hWnd,
                      "Cannot Open File",
                      szFileName,
                      MB_OK);
            return;
            }
         /* put file name in window */
         strcpy(szTitle+10, szFileName);
         SetWindowText(hWnd, (LPSTR) szTitle);
         /* turn on rest of menu items */
         EnableMenuItem(GetMenu(hWnd),
            MENU_PRINT,
            MF_ENABLED | MF_BYCOMMAND);
         EnableMenuItem(GetMenu(hWnd),
            MENU_CREATE,
            MF_ENABLED | MF_BYCOMMAND);
         EnableMenuItem(GetMenu(hWnd),
            MENU_EDIT,
            MF_ENABLED | MF_BYCOMMAND);
         EnableMenuItem(GetMenu(hWnd),
            MENU_DELETE,
            MF_ENABLED | MF_BYCOMMAND);
         lseek(hDataFile, (long) 0, 0);
         read(hDataFile, szRecord, sizeof(szRecord));
         strcpy(szHeader, szRecord);
         InvalidateRect(hWnd, (LPRECT)NULL, TRUE);   /* force repaint */
         break;
      case MENU_PRINT:
         PrintAll(hWnd);
         break;
      case MENU_CREATE:
         CreateAddressNo(hWnd);
         break;
      case MENU_EDIT:
         EditAddressNo(hWnd);
         break;
      case MENU_DELETE:
         DelAddressNo(hWnd);
         break;
    }
    InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
return;
}

/* PROCEDURE TO GET CURRENT FILE DATA */
GetData(hWnd)
HWND hWnd;
{
HANDLE hDataFile;
long address_no;
   hDataFile = OpenFile(szFileName,
                        &ofDataFile,
                        OF_READ);
   if (hDataFile == -1)
      {
      MessageBox(hWnd,
                "Cannot Open File",
                szFileName,
                MB_OK);
      return(0);
      }
   ClearFields();
   address_no = atol(szAddressNo);
   lseek(hDataFile, (long) address_no * sizeof(szRecord), 0);
   read(hDataFile, szRecord, sizeof(szRecord));
   recfield(szFirst, szRecord, 1);
   recfield(szLast, szRecord, 2);
   recfield(szAddress, szRecord, 3);
   recfield(szCity, szRecord, 4);
   recfield(szState, szRecord, 5);
   recfield(szZip, szRecord, 6);
   recfield(szFlag, szRecord,7);
   close(hDataFile);
   return(TRUE);
}

/* CLEAR CURRENT ADDRESS DATA */
ClearFields()
{
   memset(szFirst, '\0', 26);
   memset(szLast, '\0', 26);
   memset(szAddress, '\0', 41);
   memset(szCity, '\0', 21);
   memset(szState, '\0', 3);
   memset(szZip, '\0', 6);
   memset(szRecord, '\0', sizeof(szRecord));
   memset(szFlag, '\0', 2);
}

/* PROCEDURE TO WRITE THE FILE DATA TO DISK */
WriteFileData(hWnd)
HWND hWnd;
{
HANDLE  hDataFile;
FARPROC lpprocAddress;
int     RetVal, len_record;
long    address_no, header_no;
      hDataFile = OpenFile(szFileName,
                          &ofDataFile,
                          OF_READWRITE);
      if (hDataFile == -1)
         {
         MessageBox(hWnd,
                   "Cannot Open File",
                   szFileName,
                   MB_OK);
         return(FALSE);
         }
      address_no = atol(szAddressNo);
      len_record = sprintf(szRecord,"%s%c%s%c%s%c%s%c%s%c%s%c%s%c",
                          szFirst,'~',szLast,'~',szAddress,'~',
                          szCity,'~',szState,'~',szZip,'~',szFlag,'~');
      lseek(hDataFile, (long) address_no * sizeof(szRecord), 0);
      write(hDataFile, szRecord, len_record);
      header_no = atol(szHeader);
      if (address_no > header_no)
         /* update the header record */
         {
         lseek(hDataFile, (long) 0, 0);
         ltoa(address_no, szHeader, 10);
         strcpy(szRecord, szHeader);
         write(hDataFile, szRecord, sizeof(szRecord));
         }
      close (hDataFile);
      return(TRUE);
}

/* PROCEDURE TO GET FILE NAME */
BOOL FAR PASCAL GetFileName(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hCtl;
LONG lListBoxSel;
int i;
char *getcwd(char *, int);
switch (message)
   {
   case WM_INITDIALOG:
      hCtl = GetDlgItem(hDlg, ID_LISTBOX);   /* Get control handle */
      /* Place items in list box */
      getcwd(szBuffer, BUFFER_SIZE);         /* Get current directory */
      DlgDirList(hDlg,            /* handle to dialog box */
                szBuffer,         /* Buffer */
                ID_LISTBOX,       /* Id of list box control */
                ID_EDITPATH,      /* Id of static control for path */
                0);               /* Ask for 'normal' file types */
      /* Set focus on the list box control */
      SetFocus(hCtl);
      return(FALSE);
      break;
   case WM_COMMAND:
      switch(wParam)
         {
         case ID_LISTBOX:
            if ((HIWORD(lParam)) == 1)
               {
               if (DlgDirSelect(hDlg,
                               szBuffer,
                               ID_LISTBOX))
                  {
                  SetDlgItemText(hDlg, ID_EDITPATH, szBuffer);
                  DlgDirList(hDlg,        /* current dialog box */
                            szBuffer,     /* current directory */
                            ID_LISTBOX,   /* list box control */
                            ID_EDITPATH,  /* text control for path */
                            0);           /* File type */
                  }
               }
            /* double click an item is like OK button */
            if ((HIWORD(lParam)) == 2)
               {
               if (!DlgDirSelect(hDlg,
                                szBuffer,
                                ID_LISTBOX))
                  {
                  strcpy(szFileName, szBuffer);
                  EndDialog(hDlg, TRUE);
                  return(TRUE);
                  }
               else
                  {
                  EndDialog(hDlg, FALSE);    /* no file name */
                  return(TRUE);
                  }
               }
            break;
         case ID_OK:
            if (!DlgDirSelect(hDlg,
                             szBuffer,
                             ID_LISTBOX))
               {
               strcpy(szFileName, szBuffer);
               EndDialog(hDlg, TRUE);
               return(TRUE);
               }
            else
               {
               EndDialog(hDlg, FALSE);        /* no file name */
               return(TRUE);
               }
            case ID_CANCEL:
               EndDialog(hDlg, FALSE);
               return(TRUE);
            default:
               return(FALSE);
            }
         break;
      default:
         return(FALSE);
         break;
      }
}

/* PROCEDURE TO SAVEBOX DIALOG BOX */
BOOL FAR PASCAL SaveAsDialogBoxProc(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hCtl;
char *getcwd(char *, int);
switch (message)
   {
   case WM_INITDIALOG:
      getcwd(szBuffer, BUFFER_SIZE);                 /* Get directory */
      SetDlgItemText(hDlg, ID_SAVEPATH, szBuffer);   /* put in box */
      hCtl = GetDlgItem(hDlg, ID_SAVENAME);          /* setup focus */
      SetFocus(hCtl);
      return(FALSE);
      break;
   case WM_COMMAND:
      switch (wParam)
         {
         case ID_OK:
            GetDlgItemText(hDlg, ID_SAVENAME, szFileName, BUFFER_SIZE);
            EndDialog(hDlg, TRUE);        /* We got a file name */
            return(TRUE);
         case ID_CANCEL:
            EndDialog(hDlg, FALSE);
            return(TRUE);
         default:
            return(FALSE);
         }
      break;
   default:
      return(FALSE);
      break;
   }
}

/* WINDOW PAINT PROCEDURE */
MailPaint(hWnd)
HWND hWnd;
{
   PAINTSTRUCT ps;
   HDC         hDC;
   TEXTMETRIC  tmFontInfo;
   int         LineHeight, CharWidth, X, Y, X1;
   BeginPaint(hWnd, (LPPAINTSTRUCT) &ps);   /* prepare to paint */
   hDC = ps.hdc;
   GetTextMetrics(hDC, (LPTEXTMETRIC) &tmFontInfo);
   LineHeight = tmFontInfo.tmExternalLeading + tmFontInfo.tmHeight;
   CharWidth  = tmFontInfo.tmAveCharWidth;
   X = 4 * CharWidth;                     /* four spaces in */
   Y =     tmFontInfo.tmExternalLeading;  /* and leading down */
   TextOut(hDC,
           X,
           Y,
           (LPSTR) "Filename:",
           strlen("Filename:"));
   TextOut(hDC,
           X + (strlen("Filename: ") * CharWidth),
           Y,
           (LPSTR)szFileName,
           strlen(szFileName));
   Y += (2 * LineHeight);
   TextOut(hDC,
           X,
           Y,
           (LPSTR) "Addresses on File: ",
           strlen("Addresses on File: "));
   TextOut(hDC,
           X + (strlen("Addresses on File: ") * CharWidth),
           Y,
           (LPSTR) szHeader,
           strlen(szHeader));
   Y += (2 * LineHeight);
   TextOut(hDC,
           X,
           Y,
           (LPSTR) "Address No:",
           strlen("Address No:"));
   TextOut(hDC,
           X + (strlen("Address No: ") * CharWidth),
           Y,
           (LPSTR) szAddressNo,
           strlen(szAddressNo));
   Y += (2 * LineHeight);
   TextOut(hDC,
           X,
           Y,
           (LPSTR) "Name: ",
           strlen("Name: "));
   X1 = X + (strlen("Name: ") * CharWidth);
   TextOut(hDC,
           X1,
           Y,
           (LPSTR) szFirst,
           strlen(szFirst));
   X1 = X1 + (strlen(szFirst) * CharWidth) + CharWidth;
   TextOut(hDC,
           X1,
           Y,
           (LPSTR) szLast,
           strlen(szLast));
   Y += LineHeight;
   TextOut(hDC,
           X,
           Y,
           (LPSTR) "Address: ",
           strlen("Address: "));
   TextOut(hDC,
           X + (strlen("Address: ") * CharWidth),
           Y,
           (LPSTR) szAddress,
           strlen(szAddress));
   Y += LineHeight;
   TextOut(hDC,
           X,
           Y,
           (LPSTR) "City: ",
           strlen("City: "));
   X1 = X + strlen("City: ") * CharWidth;
   TextOut(hDC,
           X1,
           Y,
           (LPSTR) szCity,
           strlen(szCity));
   X1 = X1 + strlen(szCity) * CharWidth + (2 * CharWidth);
   TextOut(hDC,
           X1,
           Y,
           (LPSTR) " State: ",
           strlen(" State: "));
   X1 = X1 + strlen(" State: ") * CharWidth;
   TextOut(hDC,
           X1,
           Y,
           (LPSTR)szState,
           strlen(szState));
   X1 = X1 + strlen(szState) * CharWidth + (2 * CharWidth);
   TextOut(hDC,
           X1,
           Y,
           (LPSTR) " Zip: ",
           strlen(" Zip: "));
   X1 = X1 + strlen(" Zip: ")*CharWidth;
   TextOut(hDC,
           X1,
           Y,
           (LPSTR) szZip,
           strlen(szZip));
   ValidateRect(hWnd, (LPRECT)NULL);        /* request a repaint */
   EndPaint(hWnd, (LPPAINTSTRUCT) &ps);   
   return(TRUE);
}

/* PROCEDURE TO EDIT DIALOG BOX */
BOOL FAR PASCAL EditBoxProc(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hCtl;
switch (message)
   {
      case WM_INITDIALOG:
         SetDlgItemText(hDlg, ID_FIRST, szFirst);
         SetDlgItemText(hDlg, ID_LAST, szLast);
         SetDlgItemText(hDlg, ID_ADDRESS, szAddress);
         SetDlgItemText(hDlg, ID_CITY, szCity);
         SetDlgItemText(hDlg, ID_STATE, szState);
         SetDlgItemText(hDlg, ID_ZIP, szZip);
         /* Set focus on the first edit control */
         hCtl = GetDlgItem(hDlg, ID_FIRST);    /* get handle */
         SetFocus(hCtl);
         return(FALSE);
         break;
      case WM_COMMAND:
         switch(wParam)
            {
            case ID_OK:
               GetDlgItemText(hDlg, ID_FIRST, (LPSTR)szFirst, 26);
               GetDlgItemText(hDlg, ID_LAST, (LPSTR)szLast, 26);
               GetDlgItemText(hDlg, ID_ADDRESS, (LPSTR)szAddress, 41);
               GetDlgItemText(hDlg, ID_CITY, (LPSTR)szCity, 21);
               GetDlgItemText(hDlg, ID_STATE, (LPSTR)szState, 3);
               GetDlgItemText(hDlg, ID_ZIP, (LPSTR)szZip, 6);
               EndDialog(hDlg, TRUE);
               return(TRUE);
               break;
            case ID_CANCEL:
               EndDialog(hDlg, 0);
               return(TRUE);
            default:
               return(FALSE);
            }
         break;
      default:
         return(FALSE);
         break;
      }
}

/* PROCEDURE TO EXTRACT FIELD FROM RECORD */
void recfield(dest_string, sourc_string, field)
char dest_string[];
char sourc_string[];
int field;
{
   int dest, source;
   /* get to start of field */
   for (source = 0; --field && sourc_string[source] != '\0';)
   {  
      while (sourc_string[source] != '\0' &&
          sourc_string[source] != '~')
          ++source;
      if (sourc_string[source] == '~')
          ++source;
   }
   /* copy from source to destination */
   for (dest = 0; sourc_string[source] != '\0' &&
        sourc_string[source] != '~';
        ++ source, ++dest)
        dest_string[dest] = sourc_string[source];
   dest_string[dest] = '\0';
   return;
}

/* CREATE ADDRESS NUMBER */
BOOL PASCAL CreateAddressNo(hWnd)
HWND hWnd;
{
   HANDLE     hDataFile;
   FARPROC    lpprocAddress;
   int        RetVal, flag;
   long       header_no, address_no;
   ClearFields();
   lpprocAddress = MakeProcInstance(AddressDialogBoxProc, hInst);
   RetVal = DialogBox(hInst, "ADDRESSNOBOX", hWnd, lpprocAddress);
   FreeProcInstance((FARPROC)lpprocAddress);
   if (!RetVal)
      return(FALSE);
   hDataFile = OpenFile(szFileName,
                       &ofDataFile,
                       OF_READWRITE);
   InvalidateRect(hWnd, (LPRECT)NULL, TRUE);  /* force repaint */
   read(hDataFile, szHeader, sizeof(szHeader));
   header_no = atol(szHeader);
   address_no = atol(szAddressNo);
   if (header_no >= address_no)
      {
      lseek(hDataFile, (long) address_no * sizeof(szRecord), 0);
      read(hDataFile, szRecord, sizeof(szRecord));
      recfield(szFlag, szRecord,7);
      if (0 == strncmp("T",szFlag,1))
         {
         MessageBox(hWnd,
                   "Address already on File",
                   "ADDRESS CREATION",
                   MB_OK);
         close(hDataFile);
         return(FALSE);
         }
      }
   close(hDataFile);
   lpprocAddress = MakeProcInstance(EditBoxProc, hInst);
   RetVal = DialogBox(hInst, (LPSTR)"EDITBOX", hWnd, lpprocAddress);
   FreeProcInstance((FARPROC) lpprocAddress);
   if (!RetVal)
      return(FALSE);
   strcpy(szFlag, "T");
   WriteFileData(hWnd);
   return(TRUE);
}

/* EDIT ADDRESS NUMBER */
BOOL PASCAL EditAddressNo(hWnd)
HWND hWnd;
{
HANDLE    hDataFile;
FARPROC   lpprocAddress;
int       RetVal, flag;
long      header_no, address_no;
   lpprocAddress = MakeProcInstance(AddressDialogBoxProc, hInst);
   RetVal = DialogBox(hInst, "ADDRESSNOBOX", hWnd, lpprocAddress);
   FreeProcInstance((FARPROC)lpprocAddress);
   if (!RetVal)
      return(FALSE);
   hDataFile = OpenFile(szFileName,
                       &ofDataFile,
                       OF_READWRITE);
   InvalidateRect(hWnd, (LPRECT)NULL, TRUE);   /* force repaint */
   read(hDataFile, szHeader, sizeof(szHeader));
   header_no = atol(szHeader);
   address_no = atol(szAddressNo);
   if (header_no >= address_no)
      {
      lseek(hDataFile, (long) address_no * sizeof(szRecord), 0);
      read(hDataFile, szRecord, sizeof(szRecord));
      recfield(szFlag, szRecord, 7);
      if (0 != strncmp("T", szFlag, 1))
         {
         MessageBox(hWnd,
                    "Address Not on File",
                    "ADDRESS EDITING",
                    MB_OK);
         close (hDataFile);
         return(FALSE);
         }
      }
   else
      {
      MessageBox(hWnd,
                    "Address Number is too Large",
                    "ADDRESS EDITING",
                    MB_OK);
         close (hDataFile);
         return(FALSE);
         }
      close(hDataFile);
      GetData(hWnd);
      lpprocAddress = MakeProcInstance(EditBoxProc, hInst);
      RetVal = DialogBox(hInst, (LPSTR)"EDITBOX", hWnd, lpprocAddress);
      FreeProcInstance((FARPROC)lpprocAddress);
      if (!RetVal)
         return(FALSE);
      WriteFileData(hWnd);
      return(TRUE);
}

/* DELETE ADDRESS NUMBER */
BOOL PASCAL DelAddressNo(hWnd)
HWND hWnd;
{
HANDLE    hDataFile;
FARPROC   lpprocAddress;
int       RetVal, flag;
long      header_no, address_no;
   lpprocAddress = MakeProcInstance(AddressDialogBoxProc, hInst);
   RetVal = DialogBox(hInst, "ADDRESSNOBOX", hWnd, lpprocAddress);
   FreeProcInstance((FARPROC)lpprocAddress);
   if (!RetVal)
      return(FALSE);
   hDataFile = OpenFile(szFileName,
                       &ofDataFile,
                       OF_READWRITE);
   InvalidateRect(hWnd, (LPRECT)NULL, TRUE);   /* force repaint */
   read(hDataFile, szHeader, sizeof(szHeader));
   header_no = atol(szHeader);
   address_no = atol(szAddressNo);
   if (header_no >= address_no)
      {
      lseek(hDataFile, (long) address_no * sizeof(szRecord), 0);
      read(hDataFile, szRecord, sizeof(szRecord));
      recfield(szFlag, szRecord, 7);
      if (0 != strncmp("T", szFlag, 1))
         {
         MessageBox(hWnd,
                    "Address Not on File",
                    "MAILOUT DELETION",
                    MB_OK);
         close (hDataFile);
         return(FALSE);
         }
      }
   else
      {
      MessageBox(hWnd,
                    "Address Number is too Large",
                    "ADDRESS DELETION",
                    MB_OK);
         close (hDataFile);
         return(FALSE);
         }
      close(hDataFile);
      GetData(hWnd);
      lpprocAddress = MakeProcInstance(DelBoxProc, hInst);
      RetVal = DialogBox(hInst, (LPSTR)"DELETEBOX", hWnd, lpprocAddress);
      FreeProcInstance((FARPROC)lpprocAddress);
      if (!RetVal)
         return(FALSE);
      ClearFields();
      WriteFileData(hWnd);
      return(TRUE);
}

/* ADDRESS NO DIALOG BOX PROCEDURE */
BOOL FAR PASCAL AddressDialogBoxProc(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hCtl;
switch (message)
   {
      case WM_INITDIALOG:
         SetDlgItemText(hDlg, ID_ADDRESSNO, szAddressNo);
         hCtl = GetDlgItem(hDlg, ID_ADDRESSNO);
         SetFocus(hCtl);
         return(FALSE);
         break;
      case WM_COMMAND:
         switch (wParam)
            {
            case ID_OK:
               GetDlgItemText(hDlg, ID_ADDRESSNO, (LPSTR) szAddressNo, 4);
               EndDialog(hDlg, TRUE);
               return(TRUE);
               break;
            case ID_CANCEL:
               EndDialog(hDlg, 0);
               return(TRUE);
            default:
               return(FALSE);
            }
         break;
      default:
         return(FALSE);
         break;
      }
}

/* DELETE DIALOG BOX PROCEDURE */
BOOL FAR PASCAL DelBoxProc(hDlg, message, wParam, lParam)
HWND hDlg;
unsigned message;
WORD wParam;
LONG lParam;
{
HWND hCtl;
switch (message)
   {
      case WM_INITDIALOG:
         SetDlgItemText(hDlg, ID_FIRST, szFirst);
         SetDlgItemText(hDlg, ID_LAST, szLast);
         SetDlgItemText(hDlg, ID_ADDRESS, szAddress);
         SetDlgItemText(hDlg, ID_CITY, szCity);
         SetDlgItemText(hDlg, ID_STATE, szState);
         SetDlgItemText(hDlg, ID_ZIP, szZip);
         hCtl = GetDlgItem(hDlg, ID_CANCEL);
         SetFocus(hCtl);
         return(FALSE);
         break;
      case WM_COMMAND:
         switch (wParam)
            {
            case ID_OK:
               EndDialog(hDlg, TRUE);
               return(TRUE);
               break;
            case ID_CANCEL:
               EndDialog(hDlg, FALSE);
               return(TRUE);
            default:
               return(FALSE);
            }
         break;
      default:
         return(FALSE);
         break;
      }
}
 
/* PRINT ALL ADDRESSES */
PrintAll(hWnd)
HWND hWnd;
{
HDC     hDC;
char    szDevice[BUFFER_SIZE];
PSTR    spDeviceName, spFileName, spPort, strtok();
int     Length, PageCnt, Pages;
HANDLE  hDataFile;
int     address_no, header;
   /* Get default printer info from WIN.INI file */
   Length = GetProfileString("windows",
                             "device",
                             "",
                             szDevice,
                             BUFFER_SIZE);
   if (Length ==0)  /* no default printer - abort */
      {
      MessageBox(hWnd, "No Default Printer Found", 0, MB_OK);
      return(0);
      }
   spDeviceName = strtok(szDevice, ",");   /* Get default device */
   spFileName   = strtok(NULL, ", ");      /* Get device driver file name */
   spPort       = strtok(NULL, ", ");      /* Get port */
   /* create display context */
   hDC = CreateDC(spFileName, szDevice, spPort, 0);
   if (hDC == 0)   /* check for error in creating DC */
      {
      MessageBox(hWnd, "Cannot Write To Printer", 0, MB_OK);
      return(0);
      }
   InitPrinterDC(hDC);       /* Set up DC for printing */
   /* set to a known high value for starting to force reset without paging */
   szPagePtr = 10000;
   Escape(hDC,               /* Send STARTDOC escape code to printer */
         STARTDOC,
         strlen("MAILOUT"),  /* Length of input argument */
         (LPSTR) "MAILOUT",  /* Document name */
         0);
   /* Open file */
   hDataFile = OpenFile(szFileName,
                       &ofDataFile,
                       OF_READ);
   if (hDataFile == -1)
      {
      MessageBox(hWnd,
                "Cannot Open File",
                szFileName,
                MB_OK);
      return(0);
      }
   /* get header info */
   lseek(hDataFile, (long) 0, 0);
   read(hDataFile, szHeader, sizeof(szHeader));
   header = atoi(szHeader);
   close(hDataFile);
   /* file is closed */
   /* start read loop here */
   for (address_no=0; address_no < header; address_no++)
      {
      /* open file again */
      hDataFile = OpenFile(szFileName,
                          &ofDataFile,
                          OF_READ);
      if (hDataFile == -1)
         {
         MessageBox(hWnd,
                   "Cannot Open File",
                   szFileName,
                   MB_OK);
         return(0);
         }
      /* find record */
      lseek(hDataFile, (long) (address_no+1) * sizeof(szRecord), 0);
      read(hDataFile, szRecord, sizeof(szRecord));
      close(hDataFile);
      /* close for now */
      recfield(szFlag, szRecord, 7);
      /* deleted */
      if (0 == strncmp("T", szFlag, 1))
         {
         /* get record fields */
         recfield(szFirst, szRecord, 1);
         recfield(szLast, szRecord, 2); 
         recfield(szAddress, szRecord, 3);
         recfield(szCity, szRecord, 4);
         recfield(szState, szRecord, 5);
         recfield(szZip, szRecord, 6);
         itoa(address_no+1, szAddressNo, 10);
         /* print address */
         PrintAddress(hDC);
         }
      }
   /* page and clean up */
   Escape(hDC, NEWFRAME, 0, 0, 0);      /* page printer */
   Escape(hDC, ENDDOC, 0, 0, 0);        /* End of printing */
   DeleteDC(hDC);                       /* Remove DC */
}

InitPrinterDC(hDC)
HDC hDC;
{
POINT ptPageSize;
TEXTMETRIC  tmFontInfo;
int  X, Y, X1;
   GetTextMetrics(hDC, (LPTEXTMETRIC) &tmFontInfo);
   szLineHeight = tmFontInfo.tmExternalLeading + tmFontInfo.tmHeight;
   szCharWidth  = tmFontInfo.tmAveCharWidth;
   /* get page info about device */
   Escape(hDC,
         GETPHYSPAGESIZE,
         0,
         0,
         (LPSTR)&ptPageSize);
   szPageHeight = ptPageSize.y;
   szPageWidth  = ptPageSize.x;
}

/* PRINT SINGLE PAGE */
PrintAddress(hDC)
HDC hDC;
{
int X, X1;
X = 10 * szCharWidth;               /* Ten spaces in */
   /* check for paging */
   if (szPagePtr>(szPageHeight - (10 * szLineHeight)))
     {
     if (szPagePtr != 10000)
        Escape(hDC, NEWFRAME, 0, 0, 0);      /* Page printer */
     szPagePtr = 4 * szLineHeight;
     }
   /* now write */
   TextOut(hDC,
          X,
          szPagePtr,
          (LPSTR)szAddressNo,
          strlen(szAddressNo));
   szPagePtr += szLineHeight;
   TextOut(hDC,
          X,
          szPagePtr,
          (LPSTR)szFirst,
          strlen(szFirst));
   X1 = X + (strlen(szFirst) * szCharWidth) + szCharWidth;
   TextOut(hDC,
          X1,
          szPagePtr,
          (LPSTR)szLast,
          strlen(szLast));
   szPagePtr += szLineHeight;
   TextOut(hDC,
        X,
        szPagePtr,
        (LPSTR)szAddress,
        strlen(szAddress));
   szPagePtr += szLineHeight;
   TextOut(hDC,
          X,
          szPagePtr,
          (LPSTR)szCity,
          strlen(szCity));
   X1 = X + (strlen(szCity) * szCharWidth) + (2 * szCharWidth);
   TextOut(hDC,
          X1,
          szPagePtr,
          (LPSTR)szState,
          strlen(szState));
   X1 = X1 + (strlen(szState) * szCharWidth) + (2 * szCharWidth);
   TextOut(hDC,
          X1,
          szPagePtr,
          (LPSTR)szZip,
          strlen(szZip));
   szPagePtr = szPagePtr + (2 * szLineHeight);
   return(TRUE);
}
  


          