File:  [OS/2 SDKs] / pmsdk / samples / shapes / shapes.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:28:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: pmsdk-1988, HEAD
Microsoft OS/2 SDK PM 08-08-1988

/*--------------------------------------------------------*\
    SHAPES.C - displays rotating, variable size 3D shapes
\*--------------------------------------------------------*/

#include <stddef.h>
#include <stdlib.h>
#include <os2.h>
#include "shapes.h"
#include "sstruct.h"

#define WM_END_CHILD	    (WM_USER + 0)

VOID CreateParent ();
VOID CreateChild ();

INT iNextValidWindow (INT);
INT iQueryChild (HWND);
INT iNextFreeChild ();

MRESULT EXPENTRY ParentWndProc (HWND, USHORT, MPARAM, MPARAM);
MRESULT EXPENTRY ChildWndProc  (HWND, USHORT, MPARAM, MPARAM);

extern VOID ChangeScale (PSV);
extern VOID ChangeShapePosition (PSV);
extern VOID DrawAndFill (PSV);

extern SHAPE rgshape [];	    /* table of shape definitions */
extern INT shapeMax;		    /* max number of different shapes */

INT ishapeParent = 0;		    /* current shape in parent window */

/*
   "rgpsv" is a table of pointers to shape variables.  For each open
   window there is one instance of these variables. (see SHAPEVARS structure)
 */

PSV rgpsv [MAX_WINDOWS];

INT iMaxChild = 0;		    /* max child index */
INT iChildCreate;		    /* index of child being created */

BOOL fCloseParent = FALSE;	    /* true when parent window is closed */

extern INT yPelAdjust = 1024;	    /* adjustment for varying pixel shape */

LONG cxScreen, cyScreen;	    /* size of full screen */

HAB hab;
HWND hwndMenu;
CHAR szClassNameParent[] = "Shapes";
CHAR szClassNameChild[] = "Child";


/*
 *  Main:
 *	- main loop which receives/sends messages for the parent and child
 *	  windows
 *	- when no messages are waiting in the queue, the next shape is redrawn
 */

main()
    {
    HMQ hmq;
    QMSG qmsg;
    BOOL fNotDone = TRUE;
    INT iWindow = 0;

    hab = WinInitialize (NULL);
    hmq = WinCreateMsgQueue (hab, 0);

    WinRegisterClass (hab, szClassNameParent, ParentWndProc,
		    CS_SIZEREDRAW,
		    0 );

    WinRegisterClass (hab, szClassNameChild, ChildWndProc,
		    CS_SIZEREDRAW,
		    0 );

    CreateParent ();

    /* receive/send messages until parent window is closed */

    while (fNotDone)
	{
	if (WinPeekMsg (hab, &qmsg, NULL, 0, 0, PM_REMOVE) )

	    if (qmsg.msg == WM_QUIT && fCloseParent)
		fNotDone = FALSE;
	    else
		WinDispatchMsg (hab, &qmsg);
	else
	    {
	    /* get next window and redraw its shape */

	    iWindow = iNextValidWindow (iWindow);
	    if (!rgpsv [iWindow]->fShaded)
		ChangeShapePosition (rgpsv [iWindow]);
	    }
	}

    /* destroy remaining open windows */

    iWindow = 0;
    do
	{
	iWindow = iNextValidWindow (iWindow);
	GpiDestroyPS (rgpsv [iWindow]->hpsClient);
	WinDestroyWindow (rgpsv [iWindow]->hwndFrame);
	}
    while (iWindow != 0);

    WinDestroyMsgQueue (hmq);
    WinTerminate (hab);

    return 0;
    }


/*
 *  CreateParent:
 *	- allocate storage for shape variables
 *	- create the parent window
 */

VOID CreateParent()
    {
    PSV psv;
    SHAPE *pshape;
    ULONG CtlData;

    psv = (PSV) malloc (sizeof (SHAPEVARS));
    rgpsv [0] = psv;
    pshape = &rgshape [ishapeParent];

    psv->iShape  = ishapeParent;
    psv->rgptOld = (POINTL *) malloc ( MAX_POINTS * sizeof (POINTL) );
    psv->rgptNew = (POINTL *) malloc ( MAX_POINTS * sizeof (POINTL) );
    psv->fShaded      = FALSE;
    psv->fErased      = TRUE;
    psv->fClipping    = (pshape->pobject->rgface != NULL);
    psv->fVarySize    = FALSE;
    psv->fPerspective = TRUE;
    psv->pt2LightAng.x = 0;
    psv->pt2LightAng.y = 0;
    psv->pt3Angle     = pshape->pinit->pt3Angle;
    psv->pt3AngVel    = pshape->pinit->pt3AngVel;
    psv->pt3SizeAng   = pshape->pinit->pt3SizeAng;

    CtlData = FCF_TITLEBAR
		  | FCF_SIZEBORDER | FCF_MINMAX
		  | FCF_SYSMENU | FCF_MENU;
    psv->hwndFrame = WinCreateStdWindow(
		     HWND_DESKTOP,
		     WS_VISIBLE | FS_ICON | FS_ACCELTABLE,
		     &CtlData,
		     szClassNameParent,
		     szClassNameParent,
		     0L,
		     NULL,
		     ID_RESOURCE,
		     &psv->hwndClient );

    hwndMenu = WinWindowFromID (psv->hwndFrame, FID_MENU);
    }


/*
 *  CreateChild:
 *	- allocate storage for shape variables
 *	- initialize variables using the parents variables
 *	- create a child window
 */

VOID CreateChild(
    INT iNewChild )
    {
    PSV psv;
    SHAPE *pshape;
    ULONG CtlData;

    psv = (PSV) malloc (sizeof (SHAPEVARS));
    rgpsv [iNewChild] = psv;
    pshape = &rgshape [ishapeParent];

    psv->iShape  = ishapeParent;
    psv->rgptOld = (POINTL *) malloc (
			    pshape->pobject->cPoints * sizeof (POINTL) );
    psv->rgptNew = (POINTL *) malloc (
			    pshape->pobject->cPoints * sizeof (POINTL) );
    psv->fShaded      = rgpsv[0]->fShaded;
    psv->fErased      = TRUE;
    psv->fClipping    = rgpsv[0]->fClipping;
    psv->fVarySize    = rgpsv[0]->fVarySize;
    psv->fPerspective = rgpsv[0]->fPerspective;
    psv->pt2LightAng  = rgpsv[0]->pt2LightAng;
    psv->pt3Angle     = rgpsv[0]->pt3Angle;
    psv->pt3AngVel    = rgpsv[0]->pt3AngVel;
    psv->pt3SizeAng   = rgpsv[0]->pt3SizeAng;

    iChildCreate = iNewChild;
    CtlData = FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_SYSMENU;
    psv->hwndFrame = WinCreateStdWindow(
		    HWND_DESKTOP,
		    WS_VISIBLE,
		    &CtlData,
		    szClassNameChild,
		    pshape->szName,
		    0L,
		    NULL,
		    0,
		    &psv->hwndClient );
    }


/*
 *  iNextValidWindow:
 *	- get the window index which is greater than a given index
 *	- if no indexes are greater then return the index for
 *	  the parent (first) window
 */

INT iNextValidWindow (
    INT iWindow )
    {
    INT i;

    for (i = iWindow + 1; i <= iMaxChild; i++)
	if (rgpsv [i] != NULL)
	    return i;
    return 0;
    }


/*
 *  iQueryChild:
 *	- get the window index associated with a window handle
 *	- return 0 if window handle not found
 */

INT iQueryChild (
    HWND hwnd )
    {
    INT i;

    for (i = 1; i <= iMaxChild; i++)
	if (rgpsv [i] != NULL && rgpsv [i]->hwndClient == hwnd)
	    return i;
    return 0;
    }


/*
 *  iNextFreeChild:
 *	- get a window index which is free (not currently used)
 *	- return 0 if no indexes are free
 */

INT iNextFreeChild ()
    {
    INT i;

    for (i = 1; i < MAX_WINDOWS; i++)
	if (rgpsv [i] == NULL)
	    return i;
    return 0;
    }


/*
 *  ArrangeWindows:
 *	- change position and size of windows so that they fill the screen
 */

void ArrangeWindows ()
    {
    static SWP rgswp [MAX_WINDOWS];
    INT cWnd = 0;
    INT iWindow = 0;
    static INT rgcWndsWide [MAX_WINDOWS] =
	{ 1,2,2,2,3,3,3,3 };
    static INT rgcWndsHigh [3 * MAX_WINDOWS] =
	{ 1,0,0, 1,1,0, 2,1,0, 2,2,0, 2,1,2, 2,2,2, 2,3,2, 3,2,3 };
    INT i;
    INT xWndPos, yWndPos;
    INT iWide, iHigh;

    /* initialize each SWP entry - one entry per window */

    do
	{
	iWindow = iNextValidWindow (iWindow);
	rgswp [cWnd].fs = SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_ACTIVATE;
	rgswp [cWnd].hwndInsertBehind = HWND_TOP;
	rgswp [cWnd].hwnd = rgpsv [iWindow]->hwndFrame;
	cWnd++;
	}
    while (iWindow != 0);

    /* calculate each window size and position */

    iWide = cWnd - 1;
    iHigh = (cWnd - 1) * 3;
    xWndPos = 0;
    yWndPos = rgcWndsHigh [iHigh] - 1;

    for (i = 0; i < cWnd; i++)
	{
	rgswp [i].cx = (INT) (cxScreen / rgcWndsWide [iWide]);
	rgswp [i].cy = (INT) (cyScreen / rgcWndsHigh [iHigh + xWndPos]);
	rgswp [i].x  = rgswp [i].cx * xWndPos;
	rgswp [i].y  = rgswp [i].cy * yWndPos;

	if (yWndPos--  == 0)
	    {
	    xWndPos++;
	    yWndPos = rgcWndsHigh [iHigh + xWndPos] - 1;
	    }
	}

    /* reposition all windows */

    WinSetMultWindowPos (hab, rgswp, cWnd);
    }


/*
 *  AboutDlgProc:
 *	- simple 'About' dialog box
 */

MRESULT EXPENTRY AboutDlgProc(
    HWND hwnd,
    USHORT msg,
    MPARAM mp1,
    MPARAM mp2 )
    {
    switch (msg)
	{
	case WM_COMMAND:
	    switch (SHORT1FROMMP (mp1) )
		{
		case DID_OK:
		case DID_CANCEL:
		    WinDismissDlg (hwnd, TRUE);
		    break;

		default:
		    break;
		}
	    break;

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


/*
 *  LightSourceDlgProc:
 *	- allows the user to change the angle of the light source
 */

MRESULT EXPENTRY LightSourceDlgProc(
    HWND hwnd,
    USHORT msg,
    MPARAM mp1,
    MPARAM mp2 )
    {
    PSV psv;
    INT iNewPosition;
    INT cAddToPos;

    switch (msg)
	{
	case WM_INITDLG:
	    psv = rgpsv [0];

	    /* Set angle ranges from 0 to 180 */

	    WinSendDlgItemMsg (hwnd, IDD_LIGHTANG_X, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt2LightAng.x + 90),
			    MPFROM2SHORT (0, 180) );
	    WinSendDlgItemMsg (hwnd, IDD_LIGHTANG_Y, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt2LightAng.y + 90),
			    MPFROM2SHORT (0, 180) );
	    break;

	case WM_HSCROLL:
	    switch (SHORT2FROMMP (mp2) )
		{
		case SB_LINELEFT:
		    cAddToPos = -5;
		    break;
		case SB_LINERIGHT:
		    cAddToPos =  5;
		    break;
		case SB_PAGELEFT:
		    cAddToPos = -30;
		    break;
		case SB_PAGERIGHT:
		    cAddToPos =  30;
		    break;
		default:
		    cAddToPos =  0;
		    break;
		}
	    if (SHORT2FROMMP (mp2) == SB_SLIDERPOSITION)
		iNewPosition = SHORT1FROMMP (mp2);
	    else
		iNewPosition =
		    (INT) WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1),
					     SBM_QUERYPOS, 0L, 0L)
		    + cAddToPos;

	    /* Update slider position */

	    WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1), SBM_SETPOS,
			       MPFROMP (iNewPosition), NULL);
	    break;

	case WM_COMMAND:
	    switch (SHORT1FROMMP (mp1) )
		{
		case DID_OK:
		    psv = rgpsv [0];

		    /* Accept new angles (range -90 to 90) */

		    psv->pt2LightAng.x = (INT) WinSendDlgItemMsg (hwnd,
				IDD_LIGHTANG_X, SBM_QUERYPOS, 0L, 0L);
		    psv->pt2LightAng.x -= 90;

		    psv->pt2LightAng.y = (INT) WinSendDlgItemMsg (hwnd,
				IDD_LIGHTANG_Y, SBM_QUERYPOS, 0L, 0L);
		    psv->pt2LightAng.y -= 90;

		    WinDismissDlg (hwnd, TRUE);
		    break;

		case DID_CANCEL:
		    WinDismissDlg (hwnd, FALSE);
		    break;

		default:
		    break;
		}
	    break;

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


/*
 *  RotationDlgProc:
 *	- allows the user to change the angle and angular velocity of
 *	  a shape in the parent window
 */

MRESULT EXPENTRY RotationDlgProc(
    HWND hwnd,
    USHORT msg,
    MPARAM mp1,
    MPARAM mp2 )
    {
    PSV psv;
    INT iNewPosition;
    INT cAddToPos;
    INT cLineSize, cPageSize;

    switch (msg)
	{
	case WM_INITDLG:
	    psv = rgpsv [0];

	    /* Set angle ranges from 0 to 359 */

	    WinSendDlgItemMsg (hwnd, IDD_ANGLE_X, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt3Angle.x),
			    MPFROM2SHORT (0, 359) );
	    WinSendDlgItemMsg (hwnd, IDD_ANGLE_Y, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt3Angle.y),
			    MPFROM2SHORT (0, 359) );
	    WinSendDlgItemMsg (hwnd, IDD_ANGLE_Z, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt3Angle.z),
			    MPFROM2SHORT (0, 359) );

	    /* Set angular velocity ranges from 0 to 30 */

	    WinSendDlgItemMsg (hwnd, IDD_ANGVEL_X, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt3AngVel.x),
			    MPFROM2SHORT (0, 30) );
	    WinSendDlgItemMsg (hwnd, IDD_ANGVEL_Y, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt3AngVel.y),
			    MPFROM2SHORT (0, 30) );
	    WinSendDlgItemMsg (hwnd, IDD_ANGVEL_Z, SBM_SETSCROLLBAR,
			    MPFROMP (psv->pt3AngVel.z),
			    MPFROM2SHORT (0, 30) );
	    break;

	case WM_HSCROLL:
	    switch (SHORT1FROMMP (mp1) )
		{
		case IDD_ANGLE_X:
		case IDD_ANGLE_Y:
		case IDD_ANGLE_Z:
		    cLineSize = 1;
		    cPageSize = 30;
		    break;
		case IDD_ANGVEL_X:
		case IDD_ANGVEL_Y:
		case IDD_ANGVEL_Z:
		    cLineSize = 1;
		    cPageSize = 6;
		    break;
		}

	    switch (SHORT2FROMMP (mp2) )
		{
		case SB_LINELEFT:
		    cAddToPos = -cLineSize;
		    break;
		case SB_LINERIGHT:
		    cAddToPos =  cLineSize;
		    break;
		case SB_PAGELEFT:
		    cAddToPos = -cPageSize;
		    break;
		case SB_PAGERIGHT:
		    cAddToPos =  cPageSize;
		    break;
		default:
		    cAddToPos = 0;
		    break;
		}
	    if (SHORT2FROMMP (mp2) == SB_SLIDERPOSITION)
		iNewPosition = SHORT1FROMMP (mp2);
	    else
		iNewPosition =
		    (INT) WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1),
					     SBM_QUERYPOS, 0L, 0L)
		    + cAddToPos;

	    /* Update slider position */

	    WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1), SBM_SETPOS,
			       MPFROMP (iNewPosition), NULL);
	    break;

	case WM_COMMAND:
	    switch (SHORT1FROMMP (mp1) )
		{
		case DID_OK:
		    psv = rgpsv [0];

		    /* Accept new angles */

		    psv->pt3Angle.x = (INT) WinSendDlgItemMsg (hwnd,
				IDD_ANGLE_X, SBM_QUERYPOS, 0L, 0L);
		    psv->pt3Angle.y = (INT) WinSendDlgItemMsg (hwnd,
				IDD_ANGLE_Y, SBM_QUERYPOS, 0L, 0L);
		    psv->pt3Angle.z = (INT) WinSendDlgItemMsg (hwnd,
				IDD_ANGLE_Z, SBM_QUERYPOS, 0L, 0L);

		    /* Accept new angular velocities */

		    psv->pt3AngVel.x = (INT) WinSendDlgItemMsg (hwnd,
				IDD_ANGVEL_X, SBM_QUERYPOS, 0L, 0L);
		    psv->pt3AngVel.y = (INT) WinSendDlgItemMsg (hwnd,
				IDD_ANGVEL_Y, SBM_QUERYPOS, 0L, 0L);
		    psv->pt3AngVel.z = (INT) WinSendDlgItemMsg (hwnd,
				IDD_ANGVEL_Z, SBM_QUERYPOS, 0L, 0L);

		    WinDismissDlg (hwnd, TRUE);
		    break;

		case DID_CANCEL:
		    WinDismissDlg (hwnd, FALSE);
		    break;

		default:
		    break;
		}
	    break;

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


/*
 *  ListDlgProc:
 *	- allows the user to switch to a new shape in the parent window
 */

MRESULT EXPENTRY ListDlgProc(
    HWND hwnd,
    USHORT msg,
    MPARAM mp1,
    MPARAM mp2 )
    {
    PSV psv;
    INT iShape;
    INT iItem;
    SHAPE *pshape;

    switch (msg)
	{
	case WM_INITDLG:
	    WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE, LM_DELETEALL, NULL, NULL);

	    /* Fill list box with shape names */

	    for (iShape = 0; iShape < shapeMax; iShape++)
		{
		iItem = (USHORT) WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE,
				   LM_INSERTITEM,
				   MPFROM2SHORT (LIT_SORTASCENDING, 0),
				   MPFROMP (rgshape [iShape].szName));
		WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE, LM_SETITEMHANDLE,
				   MPFROMP (iItem),
				   MPFROMP (iShape));
		}
	    break ;

	case WM_COMMAND:
	    switch (SHORT1FROMMP (mp1) )
		{
		case DID_OK:
		    iShape = (USHORT) WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE,
						LM_QUERYSELECTION, 0L, 0L);

		    if (iShape >= 0 && iShape <= shapeMax)
			{
			/* set parent window to display chosen shape */

			ishapeParent = (USHORT) WinSendDlgItemMsg (hwnd,
						    IDD_NEWSHAPE,
						    LM_QUERYITEMHANDLE,
						    MPFROMP (iShape), NULL);
			psv = rgpsv [0];
			pshape = &rgshape [ishapeParent];
			psv->iShape = ishapeParent;
			psv->fShaded	  = FALSE;
			psv->fClipping	  = (pshape->pobject->rgface != NULL);
			psv->fVarySize	  = FALSE;
			psv->fPerspective = TRUE;
			psv->pt2LightAng.x = 0;
			psv->pt2LightAng.y = 0;
			psv->pt3Angle	= pshape->pinit->pt3Angle;
			psv->pt3AngVel	= pshape->pinit->pt3AngVel;
			psv->pt3SizeAng = pshape->pinit->pt3SizeAng;

			/* set scale of shape for size of parent window */

			ChangeScale (psv);
			WinDismissDlg (hwnd, TRUE);
			}
		    else
			WinDismissDlg (hwnd, FALSE);
		    break;

		case DID_CANCEL:
		    WinDismissDlg (hwnd, FALSE);
		    break;

		default:
		    break;
		}
	    break;

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


/*
 *  ParentWndProc:
 *	- process menu requests
 *	- start and terminate child windows
 *	- handle painting and size changes
 */

MRESULT EXPENTRY ParentWndProc(
    HWND hwnd,
    USHORT msg,
    MPARAM mp1,
    MPARAM mp2 )
    {
    HPS hps;
    HDC hdc;
    PSV psv = rgpsv [0];
    SIZEL sizel;
    LONG xPelsPerMeter, yPelsPerMeter;
    INT iChild;
    static BOOL fChildDisabled = FALSE;
    SHAPE *pshape;
    BOOL enClipping, enVarySize, enLightSource, enShaded;
	/* enable flags for menu items */

    switch (msg)
	{
	case WM_CREATE:
	    hdc = WinOpenWindowDC (hwnd);

	    DevQueryCaps (hdc, CAPS_WIDTH, 1L, &cxScreen);
	    DevQueryCaps (hdc, CAPS_HEIGHT, 1L, &cyScreen);

	    DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xPelsPerMeter);
	    DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yPelsPerMeter);
	    yPelAdjust = (INT) ((yPelsPerMeter << 10) / xPelsPerMeter);

	    sizel.cx = sizel.cy = 0;
	    psv->hpsClient = GpiCreatePS (hab, hdc, &sizel,
					PU_PELS | GPIT_MICRO | GPIA_ASSOC );

	    GpiSetBackMix (psv->hpsClient, BM_OVERPAINT);
	    GpiSetMix	  (psv->hpsClient, FM_OVERPAINT);
	    GpiSetBackColor (psv->hpsClient, CLR_WHITE);
	    break;

	case WM_INITMENU:
	    switch (SHORT1FROMMP (mp1))
		{
		case IDM_OPTIONS:
		    pshape = &rgshape [ishapeParent];

		    /* disable/enable menu items */

		    enShaded = pshape->pobject->rgface != NULL;
		    enClipping = enShaded
				&& (pshape->pobject->rgline != NULL)
				&& !psv->fShaded;
		    enLightSource = psv->fShaded;
		    enVarySize = !psv->fShaded;

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_CLIPPING, TRUE),
			MPFROM2SHORT (MIA_DISABLED, enClipping ?
				  0 : MIA_DISABLED) );

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_VARYSIZE, TRUE),
			MPFROM2SHORT (MIA_DISABLED, enVarySize ?
				  0 : MIA_DISABLED) );

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_LIGHTSOURCE, TRUE),
			MPFROM2SHORT (MIA_DISABLED, enLightSource ?
				  0 : MIA_DISABLED) );

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_SHADED, TRUE),
			MPFROM2SHORT (MIA_DISABLED, enShaded ?
				  0 : MIA_DISABLED) );

		    /* display check marks */

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_SHADED, TRUE),
			MPFROM2SHORT (MIA_CHECKED,
			    psv->fShaded ? MIA_CHECKED : 0) );

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_CLIPPING, TRUE),
			MPFROM2SHORT (MIA_CHECKED,
			    psv->fClipping ? MIA_CHECKED : 0) );

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_VARYSIZE, TRUE),
			MPFROM2SHORT (MIA_CHECKED,
			    psv->fVarySize ? MIA_CHECKED : 0) );

		    WinSendMsg(hwndMenu, MM_SETITEMATTR,
			MPFROM2SHORT (IDM_PERSPECTIVE, TRUE),
			MPFROM2SHORT (MIA_CHECKED,
			    psv->fPerspective ? MIA_CHECKED : 0) );
		    break;

		default:
		    break;
		}
	    break;

	case WM_COMMAND:
	    switch (SHORT1FROMMP (mp1))
		{
		case IDM_LIST:
		    /* display list dialog box */

		    WinDlgBox (HWND_DESKTOP, hwnd, ListDlgProc,
			NULL, IDD_LIST, NULL);
		    break;

		case IDM_ROTATION:
		    /* display rotation dialog box */

		    WinDlgBox (HWND_DESKTOP, hwnd, RotationDlgProc,
			NULL, IDD_ROTATION, NULL);
		    break;

		case IDM_LIGHTSOURCE:
		    /* display light source dialog box */

		    WinDlgBox (HWND_DESKTOP, hwnd, LightSourceDlgProc,
			NULL, IDD_LIGHTSOURCE, NULL);
		    break;

		case IDM_SHADED:
		    /* toggle shaded */

		    psv->fShaded = !psv->fShaded;
		    break;

		case IDM_CLIPPING:
		    /* toggle clipping */

		    psv->fClipping = !psv->fClipping;
		    break;

		case IDM_VARYSIZE:
		    /* toggle vary size */

		    psv->fVarySize = !psv->fVarySize;
		    break;

		case IDM_PERSPECTIVE:
		    /* toggle perspective */

		    psv->fPerspective = !psv->fPerspective;
		    break;

		case IDM_ABOUT:
		    /* display about dialog box */

		    WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
			NULL, IDD_ABOUT, NULL);
		    break;

		case IDM_CHILD:
		    /* create child window when space exists */

		    iChild = iNextFreeChild ();
		    if (iChild != 0)
			{
			if (iChild > iMaxChild)
			    iMaxChild = iChild;
			CreateChild (iChild);
			}

		    if (iNextFreeChild () == 0)
			{
			fChildDisabled = TRUE;
			WinSendMsg(hwndMenu, MM_SETITEMATTR,
			    MPFROM2SHORT (IDM_CHILD, TRUE),
			    MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED) );
			}
		    break;

		case IDM_ARRANGE:
		    /* arrange the windows to fill the screen */

		    ArrangeWindows ();
		    break;
		}
	    /* window is now invalid */

	    WinInvalidateRect (hwnd, NULL, FALSE);
	    break;

	case WM_END_CHILD:
	    /* destroy child window and associated variables */

	    iChild = SHORT1FROMMP (mp1);
	    psv = rgpsv [iChild];

	    if (iChild == iMaxChild)
		iMaxChild--;
	    rgpsv [iChild] = NULL;

	    GpiDestroyPS (psv->hpsClient);
	    WinDestroyWindow (psv->hwndFrame);
	    free (psv);

	    if (fChildDisabled)
		{
		fChildDisabled = FALSE;
		WinSendMsg(hwndMenu, MM_SETITEMATTR,
		    MPFROM2SHORT (IDM_CHILD, TRUE),
		    MPFROM2SHORT (MIA_DISABLED, 0) );
		}
	    break;

	case WM_SIZE:
	    /* change the centre and scale of shape for new window size */

	    psv->ptCentre.x = SHORT1FROMMP (mp2) / 2;
	    psv->ptCentre.y = SHORT2FROMMP (mp2) / 2;

	    ChangeScale (psv);
	    break;

	case WM_PAINT:
	    hps = WinBeginPaint (psv->hwndClient, NULL, NULL);
	    GpiErase (hps);
	    if (psv->fShaded)
		DrawAndFill (psv);
	    WinEndPaint (hps);

	    psv->fErased = TRUE;
	    break;

	case WM_CLOSE:
	    /* set flag so that main loop is terminated */

	    fCloseParent = TRUE;
	    return WinDefWindowProc (hwnd, msg, mp1, mp2);

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


/*
 *  ChildWndProc:
 *	- generic child procedure (used for all child windows)
 *	- send message to parent upon termination
 *	- handle painting and size changes
 */

MRESULT EXPENTRY ChildWndProc(
    HWND hwnd,
    USHORT msg,
    MPARAM mp1,
    MPARAM mp2 )
    {
    HPS hps;
    HDC hdc;
    PSV psv;
    SIZEL sizel;
    INT iChild;

    switch (msg)
	{
	case WM_CREATE:
	    psv = rgpsv [iChildCreate];

	    hdc = WinOpenWindowDC (hwnd);

	    sizel.cx = sizel.cy = 0;
	    psv->hpsClient = GpiCreatePS (hab, hdc, &sizel,
					PU_PELS | GPIT_MICRO | GPIA_ASSOC );

	    GpiSetBackMix (psv->hpsClient, BM_OVERPAINT);
	    GpiSetMix	  (psv->hpsClient, FM_OVERPAINT);
	    GpiSetBackColor (psv->hpsClient, CLR_WHITE);
	    break;

	case WM_SIZE:
	    /* change the centre and scale of shape for new window size */

	    iChild = iQueryChild (hwnd);
	    psv = rgpsv [iChild];

	    psv->ptCentre.x = SHORT1FROMMP (mp2) / 2;
	    psv->ptCentre.y = SHORT2FROMMP (mp2) / 2;

	    ChangeScale (psv);
	    break;

	case WM_PAINT:
	    iChild = iQueryChild (hwnd);
	    psv = rgpsv [iChild];

	    hps = WinBeginPaint (psv->hwndClient, NULL, NULL);
	    GpiErase (hps);
	    if (psv->fShaded)
		DrawAndFill (psv);
	    WinEndPaint (hps);

	    psv->fErased = TRUE;
	    break;

	case WM_CLOSE:
	    iChild = iQueryChild (hwnd);

	    /* send termination message to parent */

	    WinPostMsg (rgpsv [0]->hwndClient, WM_END_CHILD,
		MPFROMSHORT (iChild), 0L);
	    break;

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.