/*************************************************************************
*
*  File Name   : Dialog.c
*
*  Description : This program demonstrates how to associate a pop-up
*		 window with a standard window.	 The pop-up window
*		 is defined as a dialog template in a resource file.
*
*  Concepts    : This program displays a standard window.  The action bar
*		 contains a single choice:  Options.  The Options
*		 pull-down contains a choice that displays a pop-up
*		 window which contains an entry field, and OK and Cancel
*		 pushbuttons.  When the user types a place name in the
*		 entry field and selects OK, the pop-up window
*		 disappears, and the place name is displayed at the end
*		 of the text "You live in".
*
*  API's       :
*  -------------
*  GpiCharStringAt	 WinDestroyWindow    WinInvalidateRegion
*  GpiSetColor		 WinDismissDlg	     WinLoadString
*  WinBeginPaint	 WinDispatchMsg	     WinPostMsg
*  WinCreateMsgQueue	 WinDlgBox	     WinQueryWindowText
*  WinCreateStdWindow	 WinEndPaint	     WinRegisterClass
*  WinDefDlgProc	 WinFillRect	     WinSendMsg
*  WinDefWindowProc	 WinGetMsg	     WinTerminate
*  WinDestroyMsgQueue	 WinInitialize	     WinWindowFromID
*
*  Copyright (C) 1992 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_WINSYS			/* Selectively include		*/
#define INCL_WINFRAMEMGR		/* relevant parts of		*/
#define INCL_WINMENUS			/* the PM header file		*/
#define INCL_WINDIALOGS
#define INCL_GPI

#include <os2.h>
#include <string.h>
#include <stdlib.h>
#include "dialog.h"			/* Resource symbolic identifiers*/

#define LENGTH_STRING  33		/* Length of string		*/
#define RETURN_ERROR	1		/* return value for exit	*/
#define BEEP_WARN_FREQ	    60		/* frequency of warning beep	*/
#define BEEP_WARN_DUR	   100		/* duration of warning beep	*/

/* Function prototypes							*/
int main(VOID);
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
MRESULT EXPENTRY MyDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
MRESULT EXPENTRY ProdInfoDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
VOID DisplayMessage( PCH str );
VOID SetSysMenu(HWND hwnd);
					/* Define parameters by type	*/
HAB   hab;				/* Anchor block handle		*/
HMQ   hmq;				/* Message queue handle		*/
HWND  hwndClient;			/* Client window handle		*/
ULONG flCreate = FCF_STANDARD;		/* Frame control flag		*/
BOOL  bComplete = FALSE;		/* Switch for first time through*/
HWND  hwndFrame;			/* Frame window handle		*/
CHAR  szLocation[LENGTH_STRING] = "";	/* To hold text entered by user */
CHAR  szResponse[LENGTH_STRING] = "";	/* To hold "You live in"	*/

/****************************************************************
 *  Name:   main()
 *
 *  Description: Entry point of program.
 *
 *  Concepts: Obtains anchor block handle and creates message
 *	      queue.  Calls the initialization routine.
 *	      Creates the main frame window which creates the
 *	      main client window.  Polls the message queue
 *	      via Get/Dispatch Msg loop.  Upon exiting the
 *	      loop, exits.
 *
 *  API's   :  WinInitilize
 *	       DosBeep
 *	       WinCreateMsgQueue
 *	       WinTerminate
 *	       WinRegisterClass
 *	       WinCreateStdWindow
 *	       WinSetWindowText
 *	       WinGetMsg
 *	       WinDispatchMsg
 *	       WinDestroyWindow
 *	       WinDestroyMsgQueue
 *
 *  Parameters: None
 *
 *  Returns:
 *	    1 - if sucessful execution completed
 *	    0 - if error
\****************************************************************/
int main(VOID)
{
  QMSG	qmsg;
  BOOL success;

  hab = WinInitialize( 0 );
  if(!hab)
  {
    DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
    exit(RETURN_ERROR);
  }

  hmq = WinCreateMsgQueue( hab, 0 );
  if(!hmq)
  {
    DosBeep(BEEP_WARN_FREQ, BEEP_WARN_DUR);
    WinTerminate(hab);
    exit(RETURN_ERROR);
  }

  success = WinDlgBox( HWND_DESKTOP,	/* Place anywhere on desktop	*/
		       HWND_DESKTOP,	/* Owned by desk top		*/
		       (PFNWP)ProdInfoDlgProc,	 /* Addr. of procedure	*/
		       (HMODULE)0,	/* Module handle		*/
		       ID_PRODINFO,	/* Dialog identifier in resource*/
		       NULL);		/* Initialization data		*/
  if (!success)
  {
    DisplayMessage("Could Not Register Class");
    exit(RETURN_ERROR);
  }

  success = WinRegisterClass(		/* Register window class	*/
       hab,				/* Anchor block handle		*/
       "MyWindow",			/* Window class name		*/
       MyWindowProc,			/* Address of window procedure	*/
       CS_SIZEREDRAW,			/* Class style			*/
       0				/* No extra window words	*/
       );
  if (!success)
  {
    DisplayMessage("Could Not Register Class");
    exit(RETURN_ERROR);
  }

  hwndFrame = WinCreateStdWindow(
	HWND_DESKTOP,			/* Desktop window is parent	*/
	WS_VISIBLE,			/* Frame style			*/
	&flCreate,			/* Frame control flag		*/
	"MyWindow",			/* Window class name		*/
	"",				/* Window title			*/
	0L,				/* Client style of VISIBLE	*/
	(HMODULE)NULL,			/* Resource is in .EXE file	*/
	ID_MAINWND,			/* Frame window identifier	*/
	&hwndClient);			/* Client window handle		*/

  if (!hwndFrame)
  {
    DisplayMessage("Could Not Create Main Window");
    exit(RETURN_ERROR);
  }

  WinSetWindowText(hwndFrame, "Dialog - Sample Program");

/*
 * Get and dispatch messages from the application message queue
 * until WinGetMsg returns FALSE, indicating a WM_QUIT message.
 */
  while( WinGetMsg( hab, &qmsg, (HWND)NULL, 0, 0 ) )
    WinDispatchMsg( hab, &qmsg );

  WinDestroyWindow( hwndFrame );	/* Tidy up...			*/
  WinDestroyMsgQueue( hmq );		/* and				*/
  WinTerminate( hab );			/* terminate the application	*/
  return(0);
}
/***********************  End of main procedure	 ************************/

/****************************************************************
 *  Name:   MyWndProc
 *
 *  Description : Window procedure for the main clent window.
 *
 *  Concepts : Processes the messages sent to the main client
 *	       window.
 *
 *  API's : WinLoadString
 *	    WinDlgBox
 *	    WinInvalidateRegion
 *	    WinPostMsg
 *	    WinDefDlgProc
 *	    WinBeginPaint
 *	    WinFillRect
 *	    GpiCharStringAt
 *	    GpiSetColor
 *	    WinEndPaint
 *
 * Parameters	: hwnd - Window handle to which message is addressed
 *		  msg - Message type
 *		  mp1 - First message parameter
 *		  mp2 - Second message parameter
 *
 *  Returns:  Return values are determined by each message
 *
 ****************************************************************/
MRESULT EXPENTRY MyWindowProc ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
  switch( msg )
  {
    case WM_CREATE:
      /*
       * Window initialization - load "You live in" string from resource
       */
      WinLoadString( hab,
		     (HMODULE)NULL,	   /* Resource is in .EXE file	*/
		     ID_RESPONSE,	   /* String identifier		*/
		     sizeof( szResponse ), /* Size of buffer		*/
		     (PSZ)szResponse);	   /* Buffer			*/
      break;
    case WM_COMMAND:
      /*
       * When the user chooses "Where..." from the Options pull-down,
       * the application displays a dialog box. WinDlgBox calls the
       * dialog procedure below. WinDlgBox does not return until the
       * dialog procedure returns.
       * WinInvalidateRegion sends a WM_PAINT message.
       */
      switch ( SHORT1FROMMP( mp1 ) )
      {
	case ID_WHERE:

	 WinDlgBox( HWND_DESKTOP,	/* Place anywhere on desktop	*/
		     hwndFrame,		/* Owned by frame		*/
		     MyDlgProc,		/* Address of dialog procedure	*/
		     (HMODULE)0,	/* Module handle		*/
		     ID_MYDIALOG,	/* Dialog identifier in resource*/
		     NULL);		/* Initialization data		*/

	  WinInvalidateRegion( hwnd, NULLHANDLE, FALSE ); /* Force a repaint */

	  break;
	case ID_EXITPROGRAM:

	  WinPostMsg( hwnd, WM_CLOSE, NULL, NULL);

	  break;
	default:
      return WinDefWindowProc( hwnd, msg, mp1, mp2 );
      }
      break;
    case WM_PAINT:
      /*
       * Window contents are drawn here. First time through, bComplete
       * is FALSE, so window is simply filled with SYSCLR_WINDOW.
       * On subsequent passes, if bComplete has been set to TRUE in the
       * dialog procedure, GpiCharStringAt draws the text.
       */
      {
       HPS    hps;			/* Presentation space handle	*/
       POINTL pt;			/* String screen coordinates	*/
       RECTL  rc;			/* Window rectangle		*/

	hps = WinBeginPaint( hwnd, (HPS)NULL, &rc );
	WinFillRect( hps, &rc, SYSCLR_WINDOW );
	if( bComplete)
	{
	  GpiSetColor( hps, CLR_NEUTRAL ); /* Text color same as PM	  */
	  pt.x = 50L; pt.y = 50L;	  /* Coordinates of "You live in" */
	  GpiCharStringAt( hps, &pt, (LONG)strlen( szResponse ), szResponse );
	  pt.x = 50L; pt.y = 30L;	  /* Coordinates of location	  */
	  GpiCharStringAt( hps, &pt, (LONG)strlen( szLocation ), szLocation );
	}
	WinEndPaint( hps );		  /* Drawing is complete	  */
      }
      break;
    case WM_CLOSE:
      WinPostMsg( hwnd, WM_QUIT, NULL, NULL);	  /* Cause termination	  */
      break;
    default:
      /*
       * Must have WinDefWindowProc in your window procedure
       */
      return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}
/*********************** End of window procedure  ***********************/

/*********************************************************************
 *  Name : MyDlgProc
 *
 *  Description : Processes all messages sent to the dialog.
 *
 *  Concepts : Called for each message sent to the dialog box.
 *	       A switch statement branches to the routines to be
 *	       performed for each message processed.  Any messages
 *	       not specifically process are passed to the default
 *	       window procedure WinDefDlgProc().
 *
 *  API's : WinQueryWindowText
 *	    WinDismissDlg
 *
 * Parameters	: hwnd - Window handle to which message is addressed
 *		  msg - Message type
 *		  mp1 - First message parameter
 *		  mp2 - Second message parameter
 *
 *  Returns : Dependent upon message sent
 *
 ****************************************************************/
MRESULT EXPENTRY MyDlgProc( HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
  switch ( msg )
  {
    case WM_INITDLG:
       SetSysMenu(hwndDlg);		/* remove unused sys. menu items*/
       break;

    case WM_COMMAND:			/* Posted by pushbutton or key	*/
      /*
       * PM sends a WM_COMMAND message when the user presses either
       * the Enter or Escape pushbuttons.
       */
      switch( SHORT1FROMMP( mp1 ) )	/* Extract the command value	*/
      {
	case DID_OK:			/* The Enter pushbutton or key. */
					/* WinQueryWindowText copies the*/
					/* contents of the entry field	*/
					/* into szLocation.		*/
	  WinQueryWindowText( WinWindowFromID( hwndDlg, ID_ENTRYFIELD ),
			      LENGTH_STRING,
			      szLocation );
	  bComplete = TRUE;		/* Set switch so strings are	*/
					/* drawn in WM_PAINT processing.*/
	case DID_CANCEL:	 /* The Cancel pushbutton or Escape key */
	  WinDismissDlg( hwndDlg, TRUE );  /* Removes the dialog box	*/
	  return (MRESULT) FALSE;
	default:
	  break;
      }
      break;
    default:
      /*
       * Any event messages that the dialog procedure has not processed
       * come here and are processed by WinDefDlgProc.
       * This call MUST exist in your dialog procedure.
       */
      return WinDefDlgProc( hwndDlg, msg, mp1, mp2 );
  }
  return (MRESULT) FALSE;
}
/********************** End of dialog procedure	 ************************/

/*********************************************************************
 *  Name : ProdInfoDlgProc
 *
 *  Description : Processes all messages sent to the Product
 *		  Information dialog box.
 *
 *  Concepts : Called for each message sent to the Product
 *	       Information dialog box.	The Product
 *	       Information box only has a button control so
 *	       this routine only processes WM_COMMAND
 *	       messages.  Any WM_COMMAND posted must have come
 *	       from the Ok button so we dismiss the dialog
 *	       upon receiving it.
 *
 *  API's : WinDismissDlg
 *	    WinDefDlgProc
 *
 * Parameters	: hwnd - Window handle to which message is addressed
 *		  msg - Message type
 *		  mp1 - First message parameter
 *		  mp2 - Second message parameter
 *
 *  Returns : Dependent upon message sent
 *
 ****************************************************************/
MRESULT EXPENTRY ProdInfoDlgProc( HWND hwnd, ULONG msg, MPARAM mp1,
				  MPARAM mp2)
{
   switch(msg)
   {
      case WM_INITDLG:
	 SetSysMenu(hwnd);		/* remove unused sys. menu items*/
	 break;

      case WM_COMMAND:
	 /*
	  * No matter what the command, close the dialog
	  */
	 WinDismissDlg(hwnd, TRUE);
	 break;

      default:
	 return(WinDefDlgProc(hwnd, msg, mp1, mp2));
	 break;
   }
   return (MRESULT)0;
}
/********************** End ofProdinfo dialog procedure ****************/

/****************************************************************
 *  Name:   DisplayMessage
 *
 *  Description : Displays error messages.
 *
 *  Concepts : Displays a message box containing an error
 *	       message each time called.
 *
 *  API's : WinMessageBoxNon
 *
 * Parameters	: str - error message to display
 *
 *  Returns:  Void
 *
 ****************************************************************/
VOID DisplayMessage(PCH str)
{
  /*
   * This routine calls WinMessageBox to dsplay error messages to the
   * user.
   */

  WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (PCH) str,
     (PCH) "Error Messages For The Dialog Sample", ID_MESSAGEBOX,
     MB_OK | MB_APPLMODAL | MB_MOVEABLE | MB_ERROR);
}
/******************* End of DisplayMessage procedure ********************/
/***********************************************************
 * Name		: SetSysMenu
 *
 * Description	: Procedure to remove unselectable items from
 *		  the window system menu.
 *
 * Concepts	: This routine determines the number of items
 *		  in the system menu, loops through those
 *		  items removing disabled menu items and menu
 *		  seperators.
 *
 * API's        : WinMessageBox
 *
 * Parameters	: None
 *
 * Return	: None
 *
 **************************************************************/
VOID SetSysMenu(HWND hwndDlg)
{
  SHORT sMenuItems;
  USHORT usItemid;
  MENUITEM menuItem;
  HWND	hwndSubMenu;

  /* Determine the definition of the system menu */
  WinSendDlgItemMsg(hwndDlg,(SHORT)FID_SYSMENU, MM_QUERYITEM,
		    MPFROM2SHORT((SHORT)SC_SYSMENU,FALSE),
		    MPFROMP(&menuItem));

  hwndSubMenu = menuItem.hwndSubMenu;

  /* Find the number of items in the in the submenu */
  sMenuItems = (SHORT)WinSendMsg(hwndSubMenu,
				 MM_QUERYITEMCOUNT,NULL,NULL);
  /*
   * Loop through the submenu items and remove disabled
   * menu items and menu separators.
   */
  for (; sMenuItems >= 0 ;sMenuItems-- )
  {
    /* Find the item ID for the current position. */
    usItemid = (USHORT)WinSendMsg(hwndSubMenu,MM_ITEMIDFROMPOSITION,
			 MPFROMSHORT(sMenuItems), NULL);

    /* Query the definition of the current item*/
    WinSendMsg(hwndSubMenu, MM_QUERYITEM,
	       MPFROM2SHORT(usItemid,FALSE), MPFROMP(&menuItem));

   /*
    * If the menu item is disabled or the item has a style
    * of MIS_SEPARATOR - delete it.
    */
    if ((BOOL)(WinSendMsg(hwndSubMenu, MM_QUERYITEMATTR,
	  MPFROM2SHORT(usItemid,FALSE), (MPARAM)MIA_DISABLED)) ||
	  (menuItem.afStyle & MIS_SEPARATOR))
    {
      WinSendMsg(hwndSubMenu, MM_DELETEITEM,
		MPFROM2SHORT(usItemid,FALSE),NULL);
    }
  } /* endfor */
}
/******************* End of SetSysMenu() procedure ********************/
