/******************************************************************************
*                                                                             *
*   Name:  WMRECO.C                                                           *
*                                                                             *
*   Copyright : COPYRIGHT IBM CORPORATION, 1992                               *
*               LICENSED MATERIAL - PROGRAM PROPERTY OF IBM                   *
*                                                                             *
*   Description: This program receives the WM_RECO message from the           *
*                Reco system and retrieves the RECODATA.                      *
*                                                                             *
*                The MP1 of the client window procedure and contents of       *
*                RECODATA are given in a dialog box.                          *
*                                                                             *
*   Execution Instruction: WMRECO                                             *
*                                                                             *
*   Hardware Requirement: At least one PenPM Reco subsystem, for Ex. gesture  *
*                                                                             *
*   Software Requirement: OS/2 2.1, PenPM system.                             *
*                                                                             *
*   Subroutine Names and their function:                                      *
*                                                                             *
*      main : main drive routine                                              *
*                                                                             *
*      ClientWindowProc : Client window procedure. Main testing is done by    *
*                         the WM_COMMAND message.                             *
*                                                                             *
*      GetString: Get string from string table in resource file.              *
*                                                                             *
*  NOTE:                                                                      *
*      Please check the important comment given in the WM_RECO message.       *
*                                                                             *
*  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_32
#define INCL_DOS
#define INCL_PM
#define INCL_GPI

#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>

#define OS2_2
#include <penpm.h>
#include "wmreco.h"

/******************************************************************************
*                                                                             *
* Function Name: main                                                         *
*                                                                             *
* Description :                                                               *
*                                                                             *
*   This is the main drive routine                                            *
*                                                                             *
* Input: argc, argv                                                           *
*                                                                             *
* Note:                                                                       *
*                                                                             *
******************************************************************************/
VOID main(VOID)
{
static CHAR      szClientClass[] = "WMRECO";
static ULONG     flCreate = FCF_STANDARD & ~FCF_ACCELTABLE;
HMQ       hmq;
QMSG      qmsg;
HWND      hwndClient;

   hab = WinInitialize(0UL);
   hmq = WinCreateMsgQueue(hab, 0L);

   WinRegisterClass(hab,
                    szClientClass,
                    ClientWindowProc,
                    CS_SIZEREDRAW,
                    0UL);

   hwndFrame = WinCreateStdWindow(HWND_DESKTOP,
                                  WS_VISIBLE,
                                  &flCreate,
                                  szClientClass,
                                  NULL,
                                  0UL,
                                  0UL,
                                  ID_RESOURCE,
                                  &hwndClient );


   while(WinGetMsg(hab, &qmsg, 0UL, 0UL, 0UL))
      WinDispatchMsg(hab, &qmsg);

   WinDestroyWindow(hwndFrame);
   WinDestroyMsgQueue(hmq);
   WinTerminate(hab);
}

/******************************************************************************
*                                                                             *
* Function Name: ClientWindowProc                                             *
*                                                                             *
* Description :                                                               *
*                                                                             *
*   This is the client window procedure which receives the window messages    *
*   and any gesture information. If you want to write a pen aware application,*
*   replace the WM_RECO message handling codes by yours.                      *
*                                                                             *
* Input: MP1, MP2                                                             *
*                                                                             *
* Output:                                                                     *
*                                                                             *
* Note:  Check the *IMPORTANT* comment given at the WM_RECO message handling. *
*                                                                             *
******************************************************************************/
MRESULT EXPENTRY ClientWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
   HPS          hps;
   FONTMETRICS  fm;
   POINTL       ptl;
   static int   cyChar, cxChar, cxClient, cyClient;
   INT          rc, i, j;
   static RECODATA     rcData;
   static CHAR  achNULL[1];
   HRECO        hReco;
   RECOID       rID;
   CHAR         achRecoSubsys[15], achRecoEvent[15];
   CHAR         achMsg[80];
   USHORT       usXPos, usYPos;
   ULONG        ulEventCnt;
   RECTL        rcl;

   switch( msg )
   {
      case WM_CREATE:
         /********************************************************************
         *  The APIs being used in this procedure depend on the PenPM sub-   *
         *  system being correctly initialized.  Thus we check to make sure  *
         *  PenPM is up before we do anything else.                          *
         ********************************************************************/
         if( WrtWaitActive( WRT_IMMEDIATE_RETURN ) )
         {
            /*************************************************************
            *  If PenPM is NOT active then put up a message box and      *
            *  terminate the program.                                    *
            *************************************************************/
            GetString(STR_1, sizeof(achMsg), achMsg);
            WinMessageBox( HWND_DESKTOP,
                           hwnd,
                           achMsg,
                           NULL, 1, MB_OK );

            WinSendMsg( hwnd, WM_CLOSE, NULL, NULL );
            return(FALSE);
         }

         /***********************************************************
         *  Get font information from presentation space            *
         ***********************************************************/
         hps = WinGetPS(hwnd);
         GpiQueryFontMetrics(hps, (LONG) sizeof(fm), &fm);
         cxChar = fm.lEmInc;
         cyChar = fm.lMaxBaselineExt + fm.lMaxDescender;
         WinReleasePS(hps);
         achNULL[0] = '\0';
         return(FALSE);

      case WM_SIZE:
         /***********************************************************
         *  Get the size of the client window                       *
         ***********************************************************/
         cxClient = SHORT1FROMMP(mp2);
         cyClient = SHORT2FROMMP(mp2);
         return(FALSE);

      case WM_PAINT:
         /***********************************************************
         *  Give initial information in window                      *
         ***********************************************************/
         hps = WinBeginPaint(hwnd, (HPS) NULL, NULL);
         GpiErase(hps);  /* Clean up the client window */

         /* skip 1 line from top and put 3 blank from left */
         ptl.x = cxChar * 3;
         for (i = 0; i < 3; i++)
         {
            ptl.y = cyClient - cyChar * (i + 1);
            GpiCharStringAt(hps,
                            &ptl,
                            (LONG) strlen(achInit[i]),
                            achInit[i]);
         }
         WinEndPaint(hps);
         break;

      case WM_RECO:
         /****************************************************************
         *  When a gesture event is given in this window, the Pen system *
         *  sends the WM_RECO message. If you are writing a Pen aware    *
         *  application, you can get the RECODATA and then, check the    *
         *  command and arguments field. You can do whatever you would   *
         *  like to do with the command and argument.                    *
         ****************************************************************/

         /****************************************************************
         *  The MP1 has hot spot coordinate in Window coordinate, NOT    *
         *  screen coordinate. The coordinate of hot spot in RECODATA    *
         *  is given in screen coordinate.                               *
         ****************************************************************/
         usXPos = SHORT1FROMMP(mp1);
         usYPos = SHORT2FROMMP(mp1);

         /****************************************************************
         *   The MP2 has pointer to RECODATA and copy it to local memory *
         *   because it is good only during the WM_RECO message.         *
         ****************************************************************/
         rcData = * (RECODATA *) PVOIDFROMMP(mp2);

         /****************************************************************
         *   Give the hot spot coordinate from MP1.                      *
         ****************************************************************/
         GetString(STR_11, sizeof(achMsg), achMsg);
         sprintf(achLine2, achMsg, usXPos, usYPos);

         /****************************************************************
         *   Give the client and frame window handle.                    *
         ****************************************************************/
         GetString(STR_15, sizeof(achMsg), achMsg);
         sprintf(achLine3, achMsg, hwnd, hwndFrame);

         /****************************************************************
         *   Get the reco ID and reco handle from RECODATA.              *
         *   These will give event and subsystem names.                  *
         ****************************************************************/
         rID = rcData.id;
         hReco = rcData.hReco;

         /****************************************************************
         *  Get the Reco Subsystem name and Number of Events from handle.*
         *  If you have the subsystem name, then the RedQueryRecoHandle  *
         *  API can be used to get the reco handle.                      *
         ****************************************************************/
         rc = RedQueryRecoSubsystem(hReco, achRecoSubsys, &ulEventCnt);
         if (rc)
         {
            return((MRESULT) RECO_PROCESSED);
         }

         /****************************************************************
         *   Give subsysten name and number of events of the subsystem   *
         ****************************************************************/
         GetString(STR_13, sizeof(achMsg), achMsg);
         sprintf(achLine5, achMsg, achRecoSubsys, ulEventCnt);

         /****************************************************************
         *  Get the Event Name.                                          *
         *  If the event name is available, then the event ID can be     *
         *  retrieved by RedRecoIDFromName.                              *
         ****************************************************************/
         RedRecoNameFromID(hReco, rID, achRecoEvent);

         /****************************************************************
         *  Give virtual ID and character code.                          *
         ****************************************************************/
         GetString(STR_14, sizeof(achMsg), achMsg);
         sprintf(achLine4, achMsg, rcData.virtual_id, rcData.char_code,
                 achRecoEvent);

         /****************************************************************
         *  Give reco handle and hot spot in screen coordinate           *
         ****************************************************************/
         GetString(STR_16, sizeof(achMsg), achMsg);
         sprintf(achLine6, achMsg,
                 rcData.id, rcData.hReco, rcData.ptlHotSpot.x,
                 rcData.ptlHotSpot.y);

         /****************************************************************
         *  Give coordinate of rectangle of the gesture.                 *
         ****************************************************************/
         GetString(STR_17, sizeof(achMsg), achMsg);
         sprintf(achLine7, achMsg,
                 rcData.bound_box.xLeft,  rcData.bound_box.yBottom,
                 rcData.bound_box.xRight, rcData.bound_box.yTop);

         /****************************************************************
         *  Give window handles of Hot spot, Active, and Input Focus     *
         *  window.                                                      *
         ****************************************************************/
         GetString(STR_18, sizeof(achMsg), achMsg);
         sprintf(achLine8, achMsg,
                 rcData.hwnd, rcData.hwndActive, rcData.hwndFocus);

         /****************************************************************
         *  Give the command and arguments from RECODATA.                *
         *  The command and argument can be NULL, and NULL pointer can   *
         *  NOT be used in sprintf.                                      *
         ****************************************************************/
         GetString(STR_19, sizeof(achMsg), achMsg);
         sprintf(achLine9, achMsg,
             rcData.pszCommand ? rcData.pszCommand : achNULL,
             rcData.pszCmdArgs ? rcData.pszCmdArgs : achNULL);

         /* *IMPORTANT* *IMPORTANT* *IMPORTANT* *IMPORTANT* *IMPORTANT* *****
         *  If the dialog box of the RECODATA is given here, this will make *
         *  deadlock due to the WM_LIFTOFF message processing.              *
         *  So, Post a message to process the dialog box.                   *
         *  (Do NOT Send the message).                                      *
         *******************************************************************/
         WinPostMsg(hwnd, RECO_MSG, mp1, mp2);

         /*******************************************************************
         *  There are 3 possible values returned from the WM_RECO message.  *
         *  They are RECO_PROCESSED, RECO_MAP, and RECO_NOMAP.              *
         *  Let's pretend that the gesture event is done.                   *
         *******************************************************************/
         return((MRESULT) RECO_PROCESSED);

      case RECO_MSG:
         rc = WinDlgBox(HWND_DESKTOP,
                        hwnd,
                        TestDlgProc,
                        0UL,
                        IDD_DLG,
                        0UL);
         return(FALSE);

      case WM_COMMAND:
         switch (SHORT1FROMMP(mp1))
         {
            case IDM_EXIT:
            default:
               WinPostMsg(hwnd, WM_CLOSE, NULL, NULL);
               break;
         }
         break;

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

/******************************************************************************
*                                                                             *
* Function Name: TestDlgProc                                                  *
*                                                                             *
* Description :                                                               *
*                                                                             *
*   All MP1, MP2 and the RECODATA contents are given in this dialog box.      *
*                                                                             *
* Input: MP1, MP2                                                             *
*                                                                             *
* Output:                                                                     *
*                                                                             *
******************************************************************************/
MRESULT EXPENTRY TestDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
CHAR  achMsg[80];

   switch(msg)
   {
      case WM_INITDLG:

        GetString(STR_A, sizeof(achMsg), achMsg);
        WinSetDlgItemText(hwnd, IDD_ML1, achMsg);
        GetString(STR_B, sizeof(achMsg), achMsg);
        WinSetDlgItemText(hwnd, IDD_MLA, achMsg);
        WinSetDlgItemText(hwnd, IDD_ML2, achLine2);
        WinSetDlgItemText(hwnd, IDD_ML3, achLine3);
        WinSetDlgItemText(hwnd, IDD_ML4, achLine4);
        WinSetDlgItemText(hwnd, IDD_ML5, achLine5);
        WinSetDlgItemText(hwnd, IDD_ML6, achLine6);
        WinSetDlgItemText(hwnd, IDD_ML7, achLine7);
        WinSetDlgItemText(hwnd, IDD_ML8, achLine8);
        WinSetDlgItemText(hwnd, IDD_ML9, achLine9);

        return(FALSE);

      case WM_COMMAND:
        WinDismissDlg(hwnd, FALSE);
        return(FALSE);
   }
   return(WinDefDlgProc(hwnd, msg, mp1, mp2));
}

/******************************************************************************
*                                                                             *
* Function Name: GetString                                                    *
*                                                                             *
* Description :                                                               *
*                                                                             *
*   Load string by WinLoadString.                                             *
*                                                                             *
* Input: nStr_ID : String ID                                                  *
*        nLength : Length of buffer                                           *
*        pBuf    : Pointer to buffer                                          *
*                                                                             *
* Output:                                                                     *
*                                                                             *
******************************************************************************/
VOID  GetString(ULONG nStr_ID, LONG nLength, PSZ pBuf)
{
    WinLoadString(hab, 0UL, nStr_ID, nLength, pBuf);
}
