/*****************************************************************************/
/*                                                                           */
/*  File Name   : APPLIC.C                                                   */
/*                                                                           */
/*  Description : Example Sketch/Handwriting Controls in Pen for OS/2        */
/*                                                                           */
/*  This program demonstrates how to create Handwriting and Sketch Controls  */
/*  by defining them as part of a dialog template in a resource definition   */
/*  file.  The name, address, city, state, and zip code fields are           */
/*  Handwriting Controls and the signature field is a Sketch Control.        */
/*                                                                           */
/*  This application also shows how to use the following SKETCH Control      */
/*  Messages in order to save/restore a sketch to/from disk.                 */
/*    SKM_QUERY_CTL_STROKE_COUNT - Returns the number of strokes in          */
/*                                 the stroke database.                      */
/*    SKM_QUERY_STROKE_LENGTH    - Returns the length of stroke [1..n].      */
/*    SKM_QUERY_STROKE_DATA      - Queries stroke data for stroke [1..n].    */
/*    SKM_ADD_STROKE             - Adds a stroke into the stroke database.   */
/*                                                                           */
/*   Other Sketch Control Messages used:                                     */
/*    SKM_SET_CTL_DRAW_POINTER   - Sets the drawing pointer.                 */
/*    SKM_SET_CTL_INK_COLOR      - Sets the Control's ink color.             */
/*    SKM_DELETE_ALL_STROKES     - Deletes all strokes from the database.    */
/*                                                                           */
/*  Copyright (C) 1993 IBM Corporation                                       */
/*                                                                           */
/*      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is          */
/*      sample code created by IBM Corporation. This sample code is not      */
/*      part of any standard or IBM product and is provided to you solely    */
/*      for  the purpose of assisting you in the development of your         */
/*      applications.  The code is provided "AS IS", without                 */
/*      warranty of any kind.  IBM shall not be liable for any damages       */
/*      arising out of your use of the sample code, even if they have been   */
/*      advised of the possibility of such damages.                          */
/*                                                                           */
/*****************************************************************************/

#define INCL_GPI
#define INCL_DOS
#define INCL_WIN
#define INCL_PM
#define INCL_DOSMEMMGR
#define INCL_WINERRORS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <os2.h>
#include <penpm.h>

#include "applic.h"

int main()
{

  HMQ     hmq;
  QMSG    qmsg;
  HWND    hwndClient;

  CHAR      szClientClass[50];
  ULONG     flFrameFlags = FCF_TITLEBAR | FCF_TASKLIST | FCF_SIZEBORDER |
                           FCF_SYSMENU  | FCF_MINMAX   | FCF_MENU       |
                           FCF_SHELLPOSITION | FCF_ICON;


  /*************************************************************************/
  /* Initialize PM for this program and create its PM message queue.       */
  /*************************************************************************/
  hab = WinInitialize( (ULONG)NULL );
  hmq = WinCreateMsgQueue( hab, 0L );

  /*************************************************************************/
  /* Register "ClientWndProc" as the handling procedure for the            */
  /* "ApplicationDemo" class window.                                       */
  /*************************************************************************/
  WinLoadString( hab
               , (HMODULE) 0L
               , APPLIC_CLASSNAME
               , sizeof(szClientClass)
               , szClientClass);

  WinRegisterClass( hab,
                    szClientClass,
                    (PFNWP)ClientWndProc,
                    0L,
                    0UL );

  /*************************************************************************/
  /* Tell PM that we want the standard frame window.  This frame window    */
  /* will surround a "ApplicationDemo" class client window.                */
  /*************************************************************************/
  hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
                                  WS_VISIBLE,
                                  (PULONG)&flFrameFlags,
                                  szClientClass,
                                  szClientClass,
                                  0L,
                                  (HMODULE)NULL,
                                  ID_MAIN,
                                  (PHWND)&hwndClient );


  /*************************************************************************/
  /* This while loop waits for messages from PM.  If not a WM_CLOSE msg,   */
  /* then we dispatch the message to our client window procedure.          */
  /*************************************************************************/
  while( WinGetMsg( hab, &qmsg, (HWND) NULL, 0, 0 ) )
  {
    WinDispatchMsg( hab, &qmsg );
  }

  /*************************************************************************/
  /* We will drop out of the while loop if the program receives a WM_CLOSE */
  /* message.  We must destroy our PM resources and return to the          */
  /* invoking procedure.                                                   */
  /*************************************************************************/
  WinDestroyWindow( hwndFrame );
  WinDestroyMsgQueue( hmq );
  WinTerminate( hab );
  return( 0 );
}



MRESULT EXPENTRY ClientWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
  HPS       hpsClient;
  RECTL     rclClient;
  USHORT    rc;                    /* is 1st app read successfully           */
  CHAR cbuffer[100];
  HWND      hwndFillDlg;

  switch( msg )
  {

    case WM_CREATE:
     /***********************************************************************/
     /*  Check to make sure Pen for OS/2 is up before we do anything else.  */
     /***********************************************************************/
     if( WrtWaitActive( WRT_IMMEDIATE_RETURN ) )
     {
       /******************************************************************/
       /* If Pen for OS/2 is NOT active then put up a message box and    */
       /* terminate the program.                                         */
       /******************************************************************/
       ShowMessageBox(hwnd, IDMSG_NO_PEN_RUNNING);
       WinSendMsg( hwnd, WM_CLOSE, NULL, NULL );
       return( 0 );
     }

     /******************************************/
     /*  Load the colored pen pointers.        */
     /******************************************/
     BlackPen = WinLoadPointer(HWND_DESKTOP, 0L, BLACK_PEN);
     BluePen  = WinLoadPointer(HWND_DESKTOP, 0L, BLUE_PEN);
     RedPen   = WinLoadPointer(HWND_DESKTOP, 0L, RED_PEN);

     break;

    case WM_PAINT:
    {
      /*********************************************************************/
      /* If we get a paint message then just clear the client window.      */
      /*********************************************************************/
      hpsClient = WinBeginPaint( hwnd, (HPS)NULL, &rclClient );
      WinFillRect( hpsClient, &rclClient, CLR_BACKGROUND );
      WinEndPaint( hpsClient );
      return( (MRESULT)FALSE );
    }

    case WM_COMMAND:
    {
      switch(SHORT1FROMMP(mp1))
      {
        case IDM_FILL_APP:
          /******************************************************************/
          /* The user has selected option to fill out an application.       */
          /* Call dialog to save application to disk.                       */
          /******************************************************************/
          hwndFillDlg = WinLoadDlg ( HWND_DESKTOP, hwnd,  (PFNWP) FillDlgProc,
                                    0L, IDD_FILL, NULL);
          if ( hwndFillDlg )
          {
            WinShowWindow ( hwndFillDlg, TRUE );
  
            /******************************************************************/
            /* The following lines are done to make sure that the handwriting */
            /* has the number of boxes that you need.                         */
            /* When using the program in different display adapters           */
            /* (XGA, SVGA, VGA the window may not be big enough to            */
            /* have the correct number of boxes.                              */
            /* you can either change the size here or choose the correct size */
            /* using the dialog editor.                                       */
            /******************************************************************/
            CombSizing ( hwndFillDlg, IDC_DATA_LASTNAME, 17 );
            CombSizing ( hwndFillDlg, IDC_DATA_FIRSTNAME, 17 );
            CombSizing ( hwndFillDlg, IDC_DATA_ADDRESS, 17 );
            CombSizing ( hwndFillDlg, IDC_DATA_CITY, 17 );
            CombSizing ( hwndFillDlg, IDC_DATA_STATE, 2 );
            CombSizing ( hwndFillDlg, IDC_DATA_ZIP, 5 );
          } else
          {
            sprintf(cbuffer, "WinLodDlg Failed HwndFillDlg= %ld", hwndFillDlg );
            WinMessageBox( HWND_DESKTOP,
                       hwnd,
                       cbuffer,
                       NULL, 1, MB_OK );
          } /* endif */
          break;

        case IDM_DISPLAY_APP:
          /***********************************************************/
          /* The user has selected option to display an Application. */
          /* Call dialog to restore sketch to Sketch Control.        */
          /***********************************************************/
           rc = OpenFile();             /* Open the File  APPLIC.DAT         */
           if (!rc)
             /*********************************************************/
             /* Applic.dat file will be created or appeneded to when  */
             /* "Fill Out Application" is selected from Options Menu. */
             /*********************************************************/
             ShowMessageBox(hwnd, IDMSG_MISSING_FILE);
           else
              /************************************************/
              /* Display the Application to the screen,       */
              /* by restoring the signature to the Sketch     */
              /* Control and the Handwriting fields to the    */
              /* HWX Control.                                 */
              /************************************************/
              hwndFillDlg = WinLoadDlg ( HWND_DESKTOP, hwnd,  (PFNWP) DisplayDlgProc,
                                        0L, IDD_FILL, NULL);
              if ( hwndFillDlg ) 
              {
                WinShowWindow ( hwndFillDlg, TRUE );
      
                /******************************************************************/
                /* The following lines are done to make sure that the handwriting */
                /* has the number of boxes that you need.                         */
                /* When using the program in different display adapters           */
                /* (XGA, SVGA, VGA the window may not be big enough to            */
                /* have the correct number of boxes.                              */
                /* you can either change the size here or choose the correct size */
                /* using the dialog editor.                                       */
                /******************************************************************/
                CombSizing ( hwndFillDlg, IDC_DATA_LASTNAME, 17 );
                CombSizing ( hwndFillDlg, IDC_DATA_FIRSTNAME, 17 );
                CombSizing ( hwndFillDlg, IDC_DATA_ADDRESS, 17 );
                CombSizing ( hwndFillDlg, IDC_DATA_CITY, 17 );
                CombSizing ( hwndFillDlg, IDC_DATA_STATE, 2 );
                CombSizing ( hwndFillDlg, IDC_DATA_ZIP, 5 );
              } else 
              {
                sprintf(cbuffer, "WinLodDlg Failed HwndFillDlg= %ld", hwndFillDlg );
                WinMessageBox( HWND_DESKTOP,
                           hwnd,
                           cbuffer,
                           NULL, 1, MB_OK );
              } /* endif */
          break;


        case IDM_EXIT:
          WinSendMsg(hwnd, WM_CLOSE, NULL, NULL);
          break;
      }
      break;
    }

    default:
      return( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
  }
  return((MRESULT) FALSE);
}



/****************************************************************************/
/*  Name : FillDlgProc                                                      */
/*                                                                          */
/*  Description : Process to Fill out an Application and save to disk.      */
/*                                                                          */
/* Parameters   : hwnd - Window handle to which message is addressed        */
/*                msg - Message type                                        */
/*                mp1 - First message parameter                             */
/*                mp2 - Second message parameter                            */
/*                                                                          */
/****************************************************************************/
MRESULT EXPENTRY FillDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{


ULONG     ulToolBarItem;
USHORT    usToolNum;

USHORT    usSaveOK;              /* true if save successfully                */

  switch ( msg )
  {
    case WM_INITDLG:

       /**************************************/
       /* Set the Dialog Title.              */
       /**************************************/
       WinSetWindowText(hwndDlg, "Fill Out Application");

       /**********************************************/
       /* Set Drawing pointer to Black pen.          */
       /**********************************************/
       WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                   SKM_SET_CTL_DRAW_POINTER,
                   MPFROMLONG(BlackPen), NULL);


       /**********************************************/
       /* Set INK to black.                          */
       /**********************************************/
       WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                  SKM_SET_CTL_INK_COLOR,
                  MPFROMLONG(CLR_BLACK), NULL);

       /**************************************/
       /* Set the "SAVE" pushbutton text.    */
       /**************************************/
       WinSetDlgItemText(hwndDlg, IDC_SAVE_OR_NEXT, "SAVE");

       /**************************************/
       /* Set the "CLEAR" pushbutton text.   */
       /**************************************/
       WinSetDlgItemText(hwndDlg, IDC_CLEAR_OR_TOP, "CLEAR");

       FillToolBar(hwndDlg);

       break;


    case WM_CONTROL:
      switch (SHORT2FROMMP(mp1))   /* Event notification code.      */
        {
        case VN_SELECT:
          {
          switch (SHORT1FROMMP(mp1))
            {
              case IDC_PEN_COLORS:
                ulToolBarItem = (ULONG) WinSendMsg( WinWindowFromID( hwndDlg, IDC_PEN_COLORS),
                                                    VM_QUERYSELECTEDITEM,
                                                    NULL, NULL);
                usToolNum = SHORT2FROMMR(ulToolBarItem);
                switch (usToolNum)
                  {
                  case ID_BLACK:
                    WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                                SKM_SET_CTL_DRAW_POINTER,
                                MPFROMLONG(BlackPen), NULL);

                    WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                               SKM_SET_CTL_INK_COLOR,
                               MPFROMLONG(CLR_BLACK), NULL);
                    break;

                  case ID_BLUE:
                    WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                                SKM_SET_CTL_DRAW_POINTER,
                                MPFROMLONG(BluePen), NULL);

                    WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                               SKM_SET_CTL_INK_COLOR,
                               MPFROMLONG(CLR_BLUE), NULL);
                    break;

                  case ID_RED:
                    WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                                SKM_SET_CTL_DRAW_POINTER,
                                MPFROMLONG(RedPen), NULL);

                    WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                               SKM_SET_CTL_INK_COLOR,
                               MPFROMLONG(CLR_RED), NULL);
                    break;

                  }
                break;
            }
            break;
          }

        case HXN_STROKE_ADDED:
          /**********************************************************/
          /* Notification message from hwx control -                */
          /* Control has just received a pen stroke to be recoed.   */
          /* Disable the save and clear buttons.                    */
          /**********************************************************/
          WinEnableWindow( (WinWindowFromID(hwndDlg, IDC_CLEAR_OR_TOP)), FALSE);
          WinEnableWindow( (WinWindowFromID(hwndDlg, IDC_SAVE_OR_NEXT)), FALSE);
          break;

        case HXN_CONTENTS_CHANGED:
          /**********************************************************/
          /* Notification message from hwx control -                */
          /* Control has just completed stroke reco.                */
          /* Ok to enable the save and clear buttons.               */
          /**********************************************************/
          WinEnableWindow( (WinWindowFromID(hwndDlg, IDC_CLEAR_OR_TOP)), TRUE);
          WinEnableWindow( (WinWindowFromID(hwndDlg, IDC_SAVE_OR_NEXT)), TRUE);
          break;

        default:
          return WinDefWindowProc(hwndDlg, msg, mp1, mp2);
        }
      break;

    case WM_COMMAND:                    /* Posted by pushbutton or key       */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value         */
      {
        case DID_CANCEL:         /* The Cancel pushbutton or Escape key      */
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
          return (MRESULT) FALSE;


        case IDC_CLEAR_OR_TOP:       /* CLEAR */
          ClearFields(hwndDlg);
          break;

        case IDC_SAVE_OR_NEXT:       /* SAVE */
            /********************************************************/
            /* Save the Application, including the signature.       */
            /********************************************************/
            usSaveOK = SaveApp(hwndDlg);
            if (usSaveOK)
                ClearFields(hwndDlg);
          break;

      }
      break;
    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}


/*********************************************************************/
/*  Name : ClearFields                                               */
/*                                                                   */
/*  Description : Clear the Application Fields.                      */
/*                                                                   */
/* Parameters   : hwnd - Window handle to which message is addressed */
/*                                                                   */
/*********************************************************************/
void ClearFields(HWND hwndDlg)
{

    WinSetDlgItemText(hwndDlg, IDC_DATA_LASTNAME, "");
    WinSetDlgItemText(hwndDlg, IDC_DATA_FIRSTNAME, "");
    WinSetDlgItemText(hwndDlg, IDC_DATA_ADDRESS, "");
    WinSetDlgItemText(hwndDlg, IDC_DATA_CITY, "");
    WinSetDlgItemText(hwndDlg, IDC_DATA_STATE, "");
    WinSetDlgItemText(hwndDlg, IDC_DATA_ZIP, "");

    WinSendMsg(WinWindowFromID(hwndDlg, IDC_SIGNATURE),
               SKM_DELETE_ALL_STROKES,
               NULL, NULL);

} /* end ClearFields function */


/*****************************************************************************/
/*  Name:   ShowMessageBox                                                   */
/*                                                                           */
/*  Description : Displays Messages                                          */
/*                                                                           */
/*  Concepts : Displays the Info/warning/error message box with the message  */
/*             given in idMsg retrived from the message table                */
/*             Called whever a Info/warning/error occurs and a message wishes*/
/*             to be displayed to the user.                                  */
/*                                                                           */
/*  Parameters :  hwnd      - window handle of the owner of the              */
/*                            message box                                    */
/*                idMsg     - id of message to be retrieved from             */
/*                            resource file                                  */
/*                                                                           */
/*  Returns: USHORT                                                          */
/*                                                                           */
/*****************************************************************************/
USHORT ShowMessageBox(HWND hwnd, USHORT idMsg)
{
  CHAR    szText[MAXTEXTLEN];
  CHAR    szTitle[MAXTEXTLEN];
  USHORT  ulAlarm;
  USHORT  ulStyle;

  if (idMsg > IDMSG_ERROR)
    {
    WinLoadMessage(hab, 0L, IDMSG_ERROR, MAXTEXTLEN, (PSZ) szTitle);
    ulAlarm = WA_ERROR;
    ulStyle = MB_OK | MB_ERROR | MB_MOVEABLE;
    }
  else
  if (idMsg > IDMSG_WARNING)
    {
    WinLoadMessage(hab, 0L, IDMSG_WARNING, MAXTEXTLEN, (PSZ) szTitle);
    ulAlarm = WA_WARNING;
    ulStyle = MB_OKCANCEL | MB_ICONEXCLAMATION | MB_MOVEABLE;
    }
  else
    {  /* Information message */
    WinLoadMessage(hab, 0L, IDMSG_INFO, MAXTEXTLEN, (PSZ) szTitle);
    ulAlarm = WA_NOTE;
    ulStyle = MB_OK | MB_INFORMATION | MB_MOVEABLE;
    }

  WinLoadMessage(hab, 0L, idMsg, MAXTEXTLEN, (PSZ) szText);
  WinAlarm(HWND_DESKTOP, ulAlarm);

  return(WinMessageBox(HWND_DESKTOP,
                       hwnd,
                       szText,
                       szTitle,
                       IDD_MSGBOX,
                       ulStyle));
}

/*****************************************************************************/
/*  Name:   CreateToolBar(HWND hwnd)                                         */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/
VOID FillToolBar(HWND hwndDlg)
{


  WinSendMsg( WinWindowFromID( hwndDlg, IDC_PEN_COLORS),
                               VM_SETITEM,
                               MPFROM2SHORT(1, 1),
                               MPFROMLONG(BlackPen) );

  WinSendMsg( WinWindowFromID( hwndDlg, IDC_PEN_COLORS),
                               VM_SETITEM,
                               MPFROM2SHORT(1, 2),
                               MPFROMLONG(BluePen) );

  WinSendMsg( WinWindowFromID( hwndDlg, IDC_PEN_COLORS),
                               VM_SETITEM,
                               MPFROM2SHORT(1, 3),
                               MPFROMLONG(RedPen) );


}


/*****************************************************************************/
/*  Name : DisplayDlgProc                                                    */
/*                                                                           */
/*  Description : Process to display one or all Applications.                */
/*                                                                           */
/*  Parameters   : hwnd - Window handle to which message is addressed        */
/*                 msg - Message type                                        */
/*                 mp1 - First message parameter                             */
/*                 mp2 - Second message parameter                            */
/*                                                                           */
/*****************************************************************************/
MRESULT EXPENTRY DisplayDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

  switch ( msg )
  {
    case WM_INITDLG:
       /**************************************/
       /* Set the Dialog Title.              */
       /**************************************/
       WinSetWindowText(hwndDlg, "Application Display");

       /******************************************/
       /*  Set all HWX ENTRY fields to read only */
       /******************************************/
       WinEnableWindow( WinWindowFromID( hwndDlg, IDC_DATA_LASTNAME), FALSE);
       WinEnableWindow( WinWindowFromID( hwndDlg, IDC_DATA_FIRSTNAME), FALSE);
       WinEnableWindow( WinWindowFromID( hwndDlg, IDC_DATA_ADDRESS), FALSE);
       WinEnableWindow( WinWindowFromID( hwndDlg, IDC_DATA_CITY), FALSE);
       WinEnableWindow( WinWindowFromID( hwndDlg, IDC_DATA_STATE), FALSE);
       WinEnableWindow( WinWindowFromID( hwndDlg, IDC_DATA_ZIP), FALSE);


       /**************************************/
       /* Disable the SKETCH window.         */
       /**************************************/
       WinEnableWindow( (WinWindowFromID(hwndDlg, IDC_SIGNATURE)), FALSE);

       /**************************************/
       /* Set the "NEXT" pushbutton text.    */
       /**************************************/
       WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwndDlg, IDC_SAVE_OR_NEXT) );
       WinSetDlgItemText(hwndDlg, IDC_SAVE_OR_NEXT, "NEXT");

       /**************************************/
       /* Set the "TOP"  pushbutton text.    */
       /**************************************/
       WinSetDlgItemText(hwndDlg, IDC_CLEAR_OR_TOP, "TOP");

       /**************************************/
       /* Show the "SEARCH" pushbutton       */
       /**************************************/
       WinShowWindow(WinWindowFromID(hwndDlg, IDC_SEARCH), TRUE);

       /******************************************/
       /* Hide the Pen Colors Selection ToolBar. */
       /******************************************/
       WinShowWindow(WinWindowFromID(hwndDlg, IDC_PEN_COLORS), FALSE);

       /**************************************************/
       /* Initialize the Search Dialog Box.              */
       /**************************************************/
       hwndSearchDlg = WinLoadDlg( HWND_DESKTOP, hwndDlg,  (PFNWP) SearchDlgProc,
                       0L, IDD_SEARCH, NULL);

       /*******************************************************************/
       /* Display the first Application in file APPLIC.DAT to the screen. */
       /*******************************************************************/
       WinSendMsg( WinWindowFromID( hwndDlg, IDC_CLEAR_OR_TOP),
                   BM_CLICK, 0L, 0L);             /* send TOP */
       break;


    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_CANCEL:              /* The Cancel pushbutton or Escape key */
          WinDestroyWindow( hwndSearchDlg);
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
          DosClose(hf);
          return (MRESULT) FALSE;

        case IDC_SAVE_OR_NEXT:    /* NEXT BUTTON */
           /******************************************************************/
           /* Display the next Application in file APPLIC.DAT to the screen. */
           /******************************************************************/
           if ( !ReadHeader() )
             ShowMessageBox(hwndDlg, IDMSG_FILE_END);
           else
             {
               SetRecord(hwndDlg);
               if (App.ulSignatureSize != 0)
                 {
                   if ( !ReadAndDisplaySignature(hwndDlg) )
                     {
                       ShowMessageBox(hwndDlg, IDMSG_SIGNATURE_READ_ERROR);
                       WinSendMsg( WinWindowFromID( hwndDlg, DID_CANCEL),
                                    BM_CLICK, 0L, 0L);           /* send CANCEL */
                     }
                 }  /* No Signature to display */
               else
                 {
                   /**************************************/
                   /* Clear last record's signature.     */
                   /**************************************/
                   WinSendMsg(WinWindowFromID(hwndDlg, IDC_SIGNATURE),
                              SKM_DELETE_ALL_STROKES,
                              NULL, NULL);
                 }
             }
           break;

        case IDC_CLEAR_OR_TOP:          /* Top button */
           /******************************************/
           /* Go to beginning of file APPLIC.DAT and */
           /* display the first application.         */
           /******************************************/
           DosSetFilePtr(hf, 0, FILE_BEGIN, &ulNewPtr);
           WinSendMsg( WinWindowFromID( hwndDlg, IDC_SAVE_OR_NEXT),
                         BM_CLICK, 0L, 0L);             /* send NEXT */
           break;

        case IDC_SEARCH:
          /****************************************/
          /* Search Dialog visible.               */
          /* Choose application to display.       */
          /****************************************/
          WinSetWindowPos(hwndSearchDlg,
                          HWND_TOP,
                          100,
                          250,
                          0,
                          0,
                          SWP_MOVE | SWP_SHOW | SWP_ACTIVATE);
          break;

      }
      break;
    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}


/****************************************************************************/
/* SaveApp - Returns TRUE if saved successfully.                            */
/*                                                                          */
/*  Parameters:                                                             */
/*                                                                          */
/*  Return Value:                                                           */
/*                                                                          */
/****************************************************************************/
USHORT SaveApp(HWND hwndDlg)
{
  APIRET rc;                                  /* return code                */

  ULONG             ulStrokeCount;              /* Total Strokes in signat  */
  ULONG             ulSaveIndex;


  /***************************************************************************/
  /* First, Copy all handwriting fields to structure.                        */
  /***************************************************************************/
  WinQueryDlgItemText(hwndDlg, IDC_DATA_LASTNAME, LASTNAME_MAX, App.szLastName);
  if ( (strlen(App.szLastName) ) == 0)
    {
      ShowMessageBox(hwndDlg, IDMSG_MISSING_LASTNAME);
      return(FALSE);
    }

  WinQueryDlgItemText(hwndDlg, IDC_DATA_FIRSTNAME, FIRSTNAME_MAX, App.szFirstName);
  WinQueryDlgItemText(hwndDlg, IDC_DATA_ADDRESS, ADDRESS_MAX, App.szAddress);
  WinQueryDlgItemText(hwndDlg, IDC_DATA_CITY, CITY_MAX, App.szCity);
  WinQueryDlgItemText(hwndDlg, IDC_DATA_STATE, STATE_MAX, App.szState);
  WinQueryDlgItemText(hwndDlg, IDC_DATA_ZIP, ZIP_MAX, App.szZip);

  /**************************************************************************/
  /* Next, Open file to save Application Record, if first time - create it. */
  /**************************************************************************/
  rc =  DosOpen("APPLIC.DAT",
              &hf,
              &ulAction,
              0,
              FILE_NORMAL,
                       FILE_OPEN | FILE_CREATE,
                       (ULONG)OPEN_ACCESS_READWRITE |
                       OPEN_SHARE_DENYREADWRITE |
                       OPEN_FLAGS_FAIL_ON_ERROR,
                       (PEAOP2)NULL);

  if (rc)         /* Error opening the file                                  */
    {
       ShowMessageBox(hwndDlg, IDMSG_FILE_OPEN_ERROR);
       return FALSE;
    }

  /*****************************************/
  /* Move to end of file.                  */
  /*****************************************/
  DosSetFilePtr(hf, 0, FILE_END, &ulNewPtr);

  /***************************************************************************/
  /* Next, Save the Signature Field and write the Application record to end  */
  /* of the file.                                                            */
  /***************************************************************************/

  /****************************************************/
  /* Get the total count of strokes in the signature. */
  /****************************************************/
  ulStrokeCount =
  (ULONG) WinSendMsg(WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                     SKM_QUERY_CTL_STROKE_COUNT,
                     NULL, NULL);

  App.ulStrokeTotal = ulStrokeCount;

  App.ulSignatureSize = ulStrokeCount * sizeof(ULONG);  /* bytes in file     */

  /*******************************************************/
  /* Malloc enough to save the lengths of each stroke.   */
  /*******************************************************/
  ulEachStrokeLength = (ULONG *) calloc(App.ulStrokeTotal, sizeof(ULONG) );


  /*************************************************************/
  /* First stroke to the last stroke -                         */
  /* Save each strokes' length in the array which was malloced */
  /*************************************************************/
  for (ulSaveIndex = 0; ulSaveIndex < ulStrokeCount; ulSaveIndex++)
    {

      ulEachStrokeLength[ulSaveIndex] =
      (ULONG) WinSendMsg(WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                         SKM_QUERY_STROKE_LENGTH,
                         MPFROMLONG(ulSaveIndex + 1), /* actual stroke number */
                         NULL);
      App.ulSignatureSize += ulEachStrokeLength[ulSaveIndex];
    }


  /************************************************************************/
  /* Write HEADER containing HWX fields, Stroke count and Signature size. */
  /************************************************************************/
  DosWrite(hf,
           &App,
           sizeof(APPLICATION),
           &ulBytesWritten);

  if ( ulBytesWritten != (sizeof(APPLICATION)) )
    {
      ShowMessageBox(hwndDlg, IDMSG_FILE_WRITE_ERROR);
      free(ulEachStrokeLength);
      DosClose(hf);
      return(FALSE);
    }


  /*******************************************************/
  /* Write ALL of the stroke's lengths to the file.      */
  /*******************************************************/
  DosWrite(hf,
           ulEachStrokeLength,
           sizeof(ULONG) * App.ulStrokeTotal,
           &ulBytesWritten);

  if ( ulBytesWritten != ( sizeof(ULONG) * App.ulStrokeTotal) )
    {

      ShowMessageBox(hwndDlg, IDMSG_FILE_WRITE_ERROR);
      free(ulEachStrokeLength);
      DosClose(hf);
      return(FALSE);
    }



  /**************************************/
  /* First stroke to the last stroke -  */
  /* Write each stroke to the file.     */
  /**************************************/
  for (ulSaveIndex = 0; ulSaveIndex < ulStrokeCount; ulSaveIndex++)
    {
      /*******************************************************/
      /* Allocate a buffer (non-shared) based on that size.  */
      /*******************************************************/
      pStrokeData = malloc(ulEachStrokeLength[ulSaveIndex]);
      if (!pStrokeData)
        {
         ShowMessageBox(hwndDlg, IDMSG_MEMORY_ERROR);
         free(ulEachStrokeLength);
         DosClose(hf);
         return(FALSE);
        }

      /*******************************/
      /* Get the Stroke information. */
      /*******************************/
      WinSendMsg(WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                 SKM_QUERY_STROKE_DATA,
                 MPFROMLONG(ulSaveIndex + 1), /* actual stroke number */
                 MPFROMP(pStrokeData) );

      /**********************************/
      /* Write the Stroke to file.      */
      /**********************************/
      DosWrite(hf,
               pStrokeData,
               ulEachStrokeLength[ulSaveIndex],
               &ulBytesWritten);

      if ( ulBytesWritten != ulEachStrokeLength[ulSaveIndex])
        {

          ShowMessageBox(hwndDlg, IDMSG_FILE_WRITE_ERROR);
          free(ulEachStrokeLength);
          free(pStrokeData);
          DosClose(hf);
          return(FALSE);
        }

      free(pStrokeData);

    }
    DosClose(hf);
    free(ulEachStrokeLength);


  return TRUE;
} /* SaveApp */


/****************************************************************************/
/* OpenFile       - Returns TRUE  if successfully open the file.            */
/*                                                                          */
/*  Parameters:                                                             */
/*                                                                          */
/*  Return Value:                                                           */
/*                                                                          */
/****************************************************************************/
USHORT OpenFile(void)
{
  APIRET rc;                                  /* return code                */

  /*****************************************/
  /* Open file, READ ONLY                  */
  /*****************************************/
  rc =  DosOpen("APPLIC.DAT",
              &hf,
              &ulAction,
              0,
              FILE_NORMAL,
                       FILE_OPEN,
                       (ULONG)OPEN_ACCESS_READONLY |
                       OPEN_SHARE_DENYREADWRITE |
                       OPEN_FLAGS_FAIL_ON_ERROR,
                       (PEAOP2)NULL);

  if (rc)                               /* error opening the file            */
       return FALSE;

  return TRUE;

} /* OpenFile */

/****************************************************************************/
/* ReadHeader     - Returns TRUE  if successfully can read hwx fields and   */
/*                  number of strokes element from file.                    */
/*  Parameters:                                                             */
/*                                                                          */
/*  Return Value:                                                           */
/*                                                                          */
/****************************************************************************/
USHORT ReadHeader()
{

  /********************************************/
  /* Read one header record.                  */
  /********************************************/
  DosRead(hf, (VOID *) &App, sizeof(APPLICATION), &ulBytesRead);
  if (ulBytesRead != sizeof(APPLICATION) )
    return FALSE;

  return TRUE;

} /* ReadHeader */


/****************************************************************************/
/* ReadAndDisplaySignature  - Returns TRUE if successfully can read strokes */
/*                            from file and put them in the SKETCH Control. */
/*  Parameters:                                                             */
/*                                                                          */
/*  Return Value:                                                           */
/*                                                                          */
/****************************************************************************/
USHORT ReadAndDisplaySignature(HWND hwndDlg)
{

  ULONG        ulStrokeIndex;             /* stroke indexer                  */
  BOOL         rc;

  /**************************************/
  /* Clear the Sketch window.           */
  /**************************************/
  WinSendMsg(WinWindowFromID(hwndDlg, IDC_SIGNATURE),
             SKM_DELETE_ALL_STROKES,
             NULL, NULL);


  /*********************************************************/
  /* Malloc enough to retrieve the lengths of each stroke. */
  /*********************************************************/
  ulEachStrokeLength = (ULONG *) calloc(App.ulStrokeTotal, sizeof(ULONG) );


  /**************************************************/
  /* Read All stroke lengths into array of lengths. */
  /**************************************************/
  DosRead(hf, (VOID *) ulEachStrokeLength, (sizeof(ULONG) * App.ulStrokeTotal), &ulBytesRead);
  if ( ulBytesRead != (sizeof(ULONG) * App.ulStrokeTotal) )
    {
      free(ulEachStrokeLength);
      return(FALSE);
    }


  /**************************************/
  /* First stroke to the last stroke -  */
  /* Read each stroke from the file.    */
  /**************************************/
  for (ulStrokeIndex = 0; ulStrokeIndex < App.ulStrokeTotal; ulStrokeIndex++)
    {

      /*******************************************************/
      /* Allocate a buffer (non-shared) based on that size.  */
      /*******************************************************/
      pStrokeData = malloc(ulEachStrokeLength[ulStrokeIndex]);
      if (!pStrokeData)
        {
          free(ulEachStrokeLength);
          return(FALSE);
        }

      memset(pStrokeData , '\0',ulEachStrokeLength[ulStrokeIndex]); /* Zap, Zap, Zap */
      /**************************************************/
      /* Read the stroke from the file into the buffer. */
      /**************************************************/
      DosRead(hf,
              pStrokeData,
              ulEachStrokeLength[ulStrokeIndex],
              &ulBytesRead);

      /**********************************************/
      /* The following code is necessary for Stroke */
      /* Data pointer fix ups after each read.      */
      /**********************************************/
      pStrokeData->pStroke = (PSTROKEDATA)    ( (PBYTE) pStrokeData + sizeof( SKETCHSTROKEDEF ));
      pStrokeData->pStroke->pXY  = (PPOINTL)  ( (PBYTE) pStrokeData + sizeof( SKETCHSTROKEDEF ) + sizeof( STROKEDATA ));


      if (pStrokeData->pStroke->pAuxInfo)
        {
          pStrokeData->pStroke->pAuxInfo = (PAUXDATAINFO)
              ( (PBYTE)  pStrokeData->pStroke->pXY
              + pStrokeData->pStroke->ulNumPoints * sizeof( POINTL ));
        }


      if (pStrokeData->pStroke->pAuxData)
        {
          pStrokeData->pStroke->pAuxData = (PAUXSTROKEDATA)

          ( (PBYTE)  pStrokeData->pStroke->pAuxInfo
            + sizeof( AUXDATAINFO )
            + sizeof( AUXDATADESC )
            * ( pStrokeData->pStroke->pAuxInfo->ulNumElements - 1 )
            + pStrokeData->pStroke->ulNumPoints
            * pStrokeData->pStroke->pAuxInfo->ulAuxSize);
        }



      if ( ulBytesRead != ulEachStrokeLength[ulStrokeIndex])
        {
          free(ulEachStrokeLength);
          free(pStrokeData);
          return(FALSE);
        }

      /*******************************************/
      /* Put the Stroke into the Sketch Control. */
      /*******************************************/
      rc = (BOOL)WinSendMsg( WinWindowFromID( hwndDlg, IDC_SIGNATURE),
                             SKM_ADD_STROKE,
                             NULL,
                             MPFROMP(pStrokeData) );


      if (rc == FALSE)
        {
          free(ulEachStrokeLength);
          free(pStrokeData);
          return(FALSE);
        }



      free(pStrokeData);
    } /* end for loop - completed reading all strokes */

  /**************************************************/
  /* Free the array of stroke lengths.              */
  /**************************************************/
  free(ulEachStrokeLength);

  return TRUE;

} /* ReadandDisplaySignature */


/****************************************************************************/
/* SetRecord      - Sets the Application HWX information into the screen   .*/
/*                  handwriting fields.                                     */
/* Parameters:                                                              */
/*                                                                          */
/* Return Value:                                                            */
/*                                                                          */
/****************************************************************************/
VOID SetRecord( HWND hwndDlg)
{


  /****************************/
  /* Set Field Information.   */
  /****************************/
  WinSetDlgItemText(hwndDlg, IDC_DATA_LASTNAME, App.szLastName);
  WinSetDlgItemText(hwndDlg, IDC_DATA_FIRSTNAME, App.szFirstName);
  WinSetDlgItemText(hwndDlg, IDC_DATA_ADDRESS, App.szAddress);
  WinSetDlgItemText(hwndDlg, IDC_DATA_CITY, App.szCity);
  WinSetDlgItemText(hwndDlg, IDC_DATA_STATE, App.szState);
  WinSetDlgItemText(hwndDlg, IDC_DATA_ZIP, App.szZip);



} /* end SetRecord() */
 /* SetRecord */


/*************************************************************************/
/*  Name : SearchDlgProc                                                 */
/*                                                                       */
/*  Description : List Box to select Application to be displayed.        */
/*                                                                       */
/* Parameters   : hwnd - Window handle to which message is addressed     */
/*                msg - Message type                                     */
/*                mp1 - First message parameter                          */
/*                mp2 - Second message parameter                         */
/*                                                                       */
/*************************************************************************/
MRESULT EXPENTRY SearchDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{

BOOL      bFill;        /* fill the listbox with names from applic.dat file  */
SHORT     sSelection;   /* Desired Application to display from listbox       */
BOOL      bFound;

HWND      hwndOwner;            /* debug */

  switch ( msg )
  {
    case WM_INITDLG:
       /****************************/
       /* Go to beginning of file. */
       /****************************/
       DosSetFilePtr(hf, 0, FILE_BEGIN, &ulNewPtr);
       bFill = TRUE;
       while (bFill)
         {
           DosRead(hf, (VOID *) &App, sizeof(APPLICATION), &ulBytesRead);
           if (ulBytesRead == sizeof(APPLICATION) )
             {
               WinSendMsg( WinWindowFromID( hwndDlg, IDC_SEARCHBOX),
                              LM_INSERTITEM,          /* insert an item */
                              MPFROMSHORT(LIT_SORTASCENDING),
                              MPFROMP(App.szLastName) ); /* item to insert */

               /************************************************/
               /* Advance the file pointer past the signature. */
               /************************************************/
               DosSetFilePtr(hf, App.ulSignatureSize, FILE_CURRENT, &ulNewPtr);
             }
           else /* EOF reached */
             bFill = FALSE;
         } /* List box is filled when end of file is reached. */
       break;


    case WM_COMMAND:                    /* Posted by pushbutton or key  */
      switch( SHORT1FROMMP( mp1 ) )     /* Extract the command value    */
      {
        case DID_CANCEL:         /* The Cancel pushbutton or Escape key */
          /**************************************/
          /* Hide the Search Dialog.            */
          /**************************************/
          WinDismissDlg( hwndDlg, DID_CANCEL);  /* Removes the dialog box    */
          return (MRESULT) FALSE;

        case DID_OK:
           /***********************************/
           /*  Get Owner of Display Dialog    */
           /***********************************/
           hwndOwner = WinQueryWindow(hwndDlg, QW_OWNER);

           /***********************************/
           /*  Get app selected from list box */
           /***********************************/
           sSelection = (SHORT)WinSendMsg(WinWindowFromID( hwndDlg, IDC_SEARCHBOX),
                            LM_QUERYSELECTION, 0, 0);
           /***********************************/
           /*  If slection was made set text  */
           /***********************************/
           if (sSelection != LIT_NONE)
             {
               WinSendMsg(WinWindowFromID( hwndDlg, IDC_SEARCHBOX),
                          LM_QUERYITEMTEXT,
                          MPFROM2SHORT(sSelection, LASTNAME_MAX),
                          MPFROMP(szSelectedName) );
               szSelectedName[LASTNAME_MAX] = '\0';


               /*********************************************/
               /*  Find and Display requested application.  */
               /*********************************************/
                DosSetFilePtr(hf, 0, FILE_BEGIN, &ulNewPtr);   /* beginning of file */
                bFound = FALSE;
                while( !bFound)
                  {
                    if ( !ReadHeader() )
                      {
                        ShowMessageBox(hwndDlg, IDMSG_FILE_READ_ERROR);
                        WinSendMsg( WinWindowFromID( hwndOwner, DID_CANCEL),
                                    BM_CLICK, 0L, 0L);           /* Cancel Display */
                      }
                    else
                      {
                        if ( (strcmp(App.szLastName, szSelectedName) ) == 0)
                          bFound = TRUE;
                        else
                          {
                            /************************************************/
                            /* Advance the file pointer past the signature. */
                            /************************************************/
                            DosSetFilePtr(hf, App.ulSignatureSize, FILE_CURRENT, &ulNewPtr);
                          }
                      }
                  } /* end while */

                WinDismissDlg( hwndDlg, DID_OK);  /* Removes the dialog box    */
                SetRecord(hwndOwner);
                if (App.ulSignatureSize != 0)
                  {
                    if ( !ReadAndDisplaySignature(hwndOwner) )
                      {
                        ShowMessageBox(hwndDlg, IDMSG_SIGNATURE_READ_ERROR);
                        WinSendMsg( WinWindowFromID( hwndOwner, DID_CANCEL),
                                    BM_CLICK, 0L, 0L);           /* Cancel Display */
                      }
                  }
                else
                  /**************************************/
                  /* Clear last record's signature.     */
                  /**************************************/
                    {

                      WinSendMsg(WinWindowFromID(hwndOwner, IDC_SIGNATURE),
                                 SKM_DELETE_ALL_STROKES,
                                 NULL, NULL);
                    }

             }
          return (MRESULT) FALSE;
      }
      break;
    default:
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}


/******************************************************************************
* SIZING OF A CONTROL TO A SPECIFIC NUMBER OF COLUMNS.                        *
* The control uses the PPMSV_CHARACTER_BOX_DX system value to size the        *
* control within the window.                                                  *
*                                                                             *
*     columns   = 5                                                           *
*     charboxdx = WrtQuerySysValue ( HWND_DESKTOP, PPMSV_CHARACTER_BOX_DX )   *
*     controlcx = (columns * charboxdx ) + (charboxdx / 2)                    *
*                                                                             *
* If you want to see how to size using the row and culumns look in the        *
* HWX_SAMP code for sizing sample                                             *
******************************************************************************/
BOOL CombSizing ( HWND hWnd,
                  USHORT usField,
                  USHORT Columns )
{
   HWND     hwndComb;
   LONG     CharBoxDX;
   LONG     BorderCX;
   SWP      SWPwindow;
   BOOL     fSuccess;
   ULONG    ControlDX;

   fSuccess = TRUE;

   /* Get the size of the X border */
   BorderCX = WinQuerySysValue ( HWND_DESKTOP, SV_CXBORDER );

   /* get the X size of the HandWriting box */
   CharBoxDX  = WrtQuerySysValue ( HWND_DESKTOP, PPMSV_CHARACTER_BOX_DX );

   /* calculate the size the window need to be so it will have the */
   /* specified number of columns                                  */
   ControlDX  = ( ( Columns * CharBoxDX ) + ( CharBoxDX / 2 ) + ( 2 * BorderCX ) ) ;


   if ( ( hwndComb = WinWindowFromID ( hWnd, usField ) ) != NULLHANDLE )
      {
        WinQueryWindowPos ( hwndComb, (PSWP)&SWPwindow );
        fSuccess = WinSetWindowPos  ( hwndComb,
                                    HWND_TOP,
                                    SWPwindow.x,
                                    SWPwindow.y,
                                    ControlDX,
                                    SWPwindow.cy,
                                    SWP_MOVE   |
                                      SWP_SIZE   |
                                      SWP_SHOW );

      }
   else
      fSuccess = FALSE;

   return ( fSuccess );
}
