
/*------------------------------------------------------------------*
 *                                                                  *
 *  Video Toolkit For OS/2 Version 2.0                              *
 *  Example PM Application No. 5.                                   *
 *  Date : 13/07/95.                                                *
 *  Copyright (c) Abbotsbury Software Ltd., United Kingdom. 1995-99 *
 *                                                                  *
 *  Filename : ex5.c                                                *
 *                                                                  *
 *------------------------------------------------------------------*/

#define     INCL_PM
#define     INCL_OS2MM
#define     INCL_DOS
#define     INCL_SW

#include    <os2.h>
#include    <os2me.h>
#include    <stdlib.h>
#include    <stdio.h>
#include    <string.h>
#include    <vcadd.h>
#include    <vcai.h>
#include    "ex5.h"
#include    "ex5cap.h"
#include    "helpfunc.h"
#include    "pmtv2rem.h"
#include    "region.h"

extern  BOOL    RemOpen;
extern  MRESULT EXPENTRY TuneDlgProc (HWND hwnd, ULONG msg,
                                      MPARAM mp1, MPARAM mp2);

DRIVERHANDLE    DevHandle;
USHORT  DevInstance;
CHAR    DevType[20];
HAB     Hab;
HWND    HwndFrame, HwndClient;
BOOL    CaptureOpen, ConvertASM;
LONG    Width, Height, X, Y;
LONG    NumColours;
LONG    Colours[256];
LONG    ColourKey;

static  HWND    HwndRemote, HwndMenu;
static  HWND    HwndNotebook, HwndNBFrame, HwndCapture;
static  USHORT  Connector;
static  CHAR    txt[256];
static  VCADEVINFO  DevInfo;
static  BOOL    NotebookOpen;
static  PSZ     InsertName = "InsertPage";
static  PFN     InsertAddr;
static  HMODULE HmodInsert;
static  PSZ     RemoteName = "RemoteDlgProc";
static  PFN     RemoteAddr;
static  HMODULE HmodRemote;

#define VCADEV_SETPRIVATECLIPLIST 0x48f33329
typedef struct {
   unsigned short left, top, width, height;
} ClipRect;

typedef struct _VCASETPRIVATECLIPLIST {
   ULONG     ulLength;             /* length of the structure             */
   ULONG     ulFlags;              /* Reserved and set to Zero            */
   ULONG     ulNum_Rects;          /* Number of rectanlges in array below */
   RECTL     VisRect[256];         /* Array of n Visible Retangle         */
} VCASETPRIVATECLIPLIST;
typedef VCASETPRIVATECLIPLIST FAR* PVCASETPRIVATECLIPLIST;

int     main (int argc, char **argv);
void    err_msg (UCHAR *mess);
void    msg_box (UCHAR *txt, UCHAR *title, ULONG options);
LONG    get_colour (HPS hps);
MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2,
                                      PCHAR  pchAlias,
                                      LONG   lOffSet );
// MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
MRESULT EXPENTRY NotebookDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
MRESULT EXPENTRY QuitDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
MRESULT EXPENTRY AboutDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);

static  void    init_colour (void);
static  void    map_pallete (HPS hps);
static  void    size_notebook (void);
static  BOOL    init_window (void);
static  void    check_menu_item (short item_id, short state);
static  void    enable_menu_item (short item_id, short state);

int main (int argc, char **argv)
{
    HMQ     hmq;
    QMSG    qmsg;
    CHAR    mod_txt[256];
    PSZ     pmmbase, env = "MMBASE";
    LONG    len;
    APIRET  rc;

        if (argc < 3)
            DosExit (EXIT_PROCESS, 1);

        Hab = WinInitialize (0);
        if (!Hab)
            DosExit (EXIT_PROCESS, 1);

        hmq = WinCreateMsgQueue (Hab, 0);
        if (!hmq)
            DosExit (EXIT_PROCESS, 1);

        strcpy (DevType, argv[1]);
        DevInstance = (USHORT)atoi (argv[2]);
        DevHandle = VcaiDeviceOpen (DevType, DevInstance);
        if (DevHandle < 0)
        {
            sprintf (txt, "Cannot Open Device %u !", atoi(argv[2]));
            msg_box (txt, "Error", MB_OK | MB_ERROR);
            DosExit (EXIT_PROCESS, 1);
        }
        Connector = (USHORT)atoi (argv[2]);

        rc = DosScanEnv (env, &pmmbase);
        if (rc != 0)
            DosExit (EXIT_PROCESS, 1);
        len = strlen (pmmbase);
        if (pmmbase[len-1] == ';')
            pmmbase[len-1] = '\0';
        sprintf (mod_txt, "%s\\DLL\\%5.5sNB.DLL", pmmbase, argv[1]);
        rc = DosLoadModule (txt, sizeof (txt), mod_txt, &HmodInsert);
        if (rc != 0)
        {
            sprintf (txt, "DosLoadModule <%s> - %ld", mod_txt, rc);
            msg_box (txt, "Error", MB_OK | MB_ERROR);
            DosExit (EXIT_PROCESS, 1);
        }
        rc = DosQueryProcAddr (HmodInsert, 0L, InsertName, &InsertAddr);
        if (rc != 0)
        {
            sprintf (txt, "DosQueryProcAddr (InsertPage) - %ld", rc);
            msg_box (txt, "Error", MB_OK | MB_ERROR);
            DosExit (EXIT_PROCESS, 1);
        }
        sprintf (mod_txt, "%s\\DLL\\PMTV2REM.DLL", pmmbase);
        rc = DosLoadModule (txt, sizeof (txt), mod_txt, &HmodRemote);
        if (rc != 0)
        {
            sprintf (txt, "DosLoadModule (PMTV2REM.DLL) - %ld", rc);
            msg_box (txt, "Error", MB_OK | MB_ERROR);
            DosExit (EXIT_PROCESS, 1);
        }
        rc = DosQueryProcAddr (HmodRemote, 0L, RemoteName, &RemoteAddr);
        if (rc != 0)
        {
            sprintf (txt, "DosQueryProcAddr (RemoteDlgProc) - %ld", rc);
            msg_box (txt, "Error", MB_OK | MB_ERROR);
            DosExit (EXIT_PROCESS, 1);
        }

        if (!init_window ())
            DosExit (EXIT_PROCESS, 1);

        while (WinGetMsg (Hab, &qmsg, NULLHANDLE, 0, 0))
            WinDispatchMsg (Hab, &qmsg);

        DestroyHelpInstance ();
        WinDestroyWindow (HwndFrame);
        WinDestroyMsgQueue (hmq);
        WinTerminate (Hab);
        DosExit (EXIT_PROCESS, 0);
}

void err_msg (UCHAR *mess)
{
    CHAR    txt[256];
    ERRORID err;

        err = WinGetLastError (Hab);
        sprintf (txt, "%s - %lx", mess,  err & 0xffff);
        msg_box (txt, "Error", MB_OK | MB_ERROR);
}

void msg_box (UCHAR *txt, UCHAR *title, ULONG options)
{
        WinMessageBox (HWND_DESKTOP,
                       HWND_DESKTOP,
                       txt,
                       title,
                       IDD_MSG,
                       options);
}

                        // The colour value for the Video Colour Key
                        // is a physical palette value.
                        // For systems with 256 or less colours in the
                        // palette, you MUST map the physical palette
                        // to PM logical palette first.
                        // If there are more than 256 colours this
                        // step should be ignored.
LONG get_colour (HPS hps)
{
    LONG index;

        map_pallete (hps);

        index = VcaiColourkeyGet();
        if (index > (ULONG)NumColours)
        {
            index = COLOUR_KEY_DEFAULT;
            VcaiColourkeySet (index);
        }
        return (LONG)index;
}

MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2,
                                      PCHAR  pchAlias,
                                      LONG   lOffSet )
{
    static  HPOINTER    hptr_rem;
    static  BOOL        minimize, dbl;
    HPS     hps;
    RECTL   rcl;
    LONG    bx, by, cy;
    VCADEVAUDIO ad;
    MOUSEPOS mousepos;
    PSWP    pswp;

        switch (msg)
        {
            case WM_CREATE :
                RemOpen = NotebookOpen = CaptureOpen = FALSE;
                minimize = dbl = FALSE;
//                VcaiOverlay (TRUE);
                VcaiOverlay (FALSE);
                VcaiFreeze (FALSE);
                HwndMenu = WinLoadMenu (hwnd, NULLHANDLE, IDR_MAIN);
                hptr_rem = WinLoadPointer (HWND_DESKTOP, NULLHANDLE,
                                           PTR_REMOTE);
                init_colour ();
                ConvertASM = TRUE;
                check_menu_item (IDM_CAPTURE_ASM, CHECK);
                break;
            case WM_PAINT :
                hps = WinBeginPaint (hwnd, NULLHANDLE, &rcl);
                WinQueryWindowRect (hwnd, &rcl);
                ColourKey = get_colour (hps);
                if ((ULONG)NumColours <= 256)
                    WinFillRect (hps, &rcl, Colours[ColourKey]);
                else
                    WinFillRect (hps, &rcl, ColourKey);
                WinEndPaint (hps);

                VcaiOverlay (TRUE);
                VcaiVideoRectValidate (0, 0, 0, 0, (USHORT) X, (USHORT) Y,
                                       (USHORT) Width, (USHORT) Height);
                break;
            case MSG_SIZE_TV :
            case WM_SIZE :
            case WM_MOVE :
            case WM_WINDOWPOSCHANGED :
                if (minimize)
                    break;
                if (!WinQueryWindowRect (hwnd, &rcl))
                    return 0;

                VcaiVideoRectValidate (0, 0, 0, 0, 0, 0, 0, 0);
                VcaiOverlay (FALSE);

                WinMapWindowPoints (hwnd, HWND_DESKTOP, (PPOINTL) &rcl, 2);
                bx = WinQuerySysValue (HWND_DESKTOP, SV_CXSIZEBORDER);
                by = WinQuerySysValue (HWND_DESKTOP, SV_CYSIZEBORDER);
                cy = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
                X      = rcl.xLeft + bx;
                Y      = cy - rcl.yTop - by;
                Width  = rcl.xRight - rcl.xLeft;
                Height = rcl.yTop - rcl.yBottom;

//                VcaiVideoRectValidate (0, 0, 0, 0, 0, 0, 0, 0);
//                VcaiOverlay (FALSE);

                VcaiOverlay (TRUE);
                VcaiVideoRectValidate (0, 0, 0, 0, (USHORT) X, (USHORT) Y,
                                       (USHORT) Width, (USHORT) Height);

                if (RemOpen)
                    WinSetActiveWindow (HWND_DESKTOP, HwndRemote);
                break;
            case WM_MINMAXFRAME :
                pswp = (PSWP) PVOIDFROMMP (mp1);
                if (!(pswp->fl & SWP_MINIMIZE))
                {
                    minimize = FALSE;
                    break;
                }
                minimize = TRUE;
                VcaiVideoRectValidate (0, 0, 0, 0, 0, 0, 0, 0);
                break;
            case WM_BUTTON1DOWN :
                if ((WinGetKeyState (HWND_DESKTOP, VK_BUTTON2) & 0x8000))
                    dbl = TRUE;
                else
                    dbl = FALSE;
                return 0;
            case WM_BUTTON2DOWN :
                if ((WinGetKeyState (HWND_DESKTOP, VK_BUTTON1) & 0x8000))
                    dbl = TRUE;
                else
                    dbl = FALSE;
                return 0;
            case WM_BUTTON1UP :
                if (dbl)
                {
                    dbl = FALSE;
                    if (CaptureOpen)
                    {
                        WinSendMsg (HwndCapture, MSG_CAPTURE, NULL, NULL);
                        return 0;
                    }
                    HwndCapture = WinLoadDlg (HWND_DESKTOP,
                                              HWND_OBJECT,
                                              (PFNWP)CaptureDlgProc,
                                              (HMODULE)NULLHANDLE,
                                              IDD_CAPTURE,
                                              NULL);
                }
                return 0;
            case WM_BUTTON1CLICK :
                if (RemOpen)
                    return 0;
                WinQueryWindowRect (hwnd, & rcl);
                WinMapWindowPoints (hwnd, HWND_DESKTOP, (PPOINTL) &rcl, 2);
                mousepos.mp_x = MOUSEMSG (&msg)->x + rcl.xLeft;
                mousepos.mp_y = MOUSEMSG (&msg)->y + rcl.yBottom;
                init_audio ();
                init_video ();
                HwndRemote = WinLoadDlg (HWND_DESKTOP,
                                         HWND_DESKTOP,
                                         (PFNWP) RemoteAddr,
                                         HmodRemote,
                                         IDD_REM,
                                         (PVOID) &mousepos);
                return 0;
            case WM_BUTTON2CLICK :
                WinPopupMenu (hwnd, hwnd, HwndMenu,
                              MOUSEMSG (&msg)->x, MOUSEMSG (&msg)->y, 0L,
                              PU_HCONSTRAIN | PU_VCONSTRAIN |
                              PU_NONE | PU_MOUSEBUTTON1 |
                              PU_KEYBOARD);
                return 0;
            case WM_MOUSEMOVE :
                WinSetPointer (HWND_DESKTOP, hptr_rem);
                return MRFROMSHORT (1);

            case WM_CLOSE :
                VcaiDeviceClose (DevHandle);
                break;

            case WM_COMMAND :
                switch (SHORT1FROMMP (mp1))
                {
                    case IDM_FILE_QUIT :
                        WinDlgBox (HWND_DESKTOP,
                                   HwndFrame,
                                   (PFNWP) QuitDlgProc,
                                   (HMODULE) NULLHANDLE,
                                   IDD_QUIT,
                                   NULL);
                        WinInvalidateRegion (HwndFrame, NULLHANDLE, FALSE);
                        break;
                    case IDM_CAPTURE_C :
                        if ((ULONG)NumColours != 256)
                        {
                            sprintf (txt, "Conversion using C code will only work\n");
                            strcat (txt, "in resolutions with 256 colours !");
                            msg_box (txt, "Information",
                                     MB_OK | MB_INFORMATION);
                            ConvertASM = TRUE;
                            return 0;
                        }
                        ConvertASM = FALSE;
                        check_menu_item (SHORT1FROMMP (mp1), CHECK);
                        check_menu_item (IDM_CAPTURE_ASM, UNCHECK);
                        break;
                    case IDM_CAPTURE_ASM :
                        ConvertASM = TRUE;
                        check_menu_item (SHORT1FROMMP (mp1), CHECK);
                        check_menu_item (IDM_CAPTURE_C, UNCHECK);
                        break;
                    case IDM_CAPTURE_CAPTURE :
                        if (CaptureOpen)
                        {
                            WinSendMsg (HwndCapture, MSG_CAPTURE, NULL, NULL);
                            return 0;
                        }
                        HwndCapture = WinLoadDlg (HWND_DESKTOP,
                                                  HWND_OBJECT,
                                                  (PFNWP)CaptureDlgProc,
                                                  (HMODULE)NULLHANDLE,
                                                  IDD_CAPTURE,
                                                  NULL);
                        break;
                    case IDM_TUNE :
                        WinDlgBox  (HWND_DESKTOP,
                                    HWND_DESKTOP,
                                    (PFNWP) TuneDlgProc,
                                    (HMODULE) NULLHANDLE,
                                    IDD_TUNE,
                                    NULL);
                        break;
                    case IDM_TV_SETUP :
                        if (NotebookOpen)
                                return 0;
                        HwndNBFrame = WinLoadSecondaryWindow
                                               (HWND_DESKTOP,
                                                HWND_DESKTOP,
                                                (PFNWP) NotebookDlgProc,
                                                (HMODULE) NULLHANDLE,
                                                IDD_NOTE,
                                                NULL);
                        break;
                    case IDM_HELPCONTENTS :
                        HelpContents ();
                        break;
                    case IDM_HELPINDEX :
                        HelpIndex ();
                        break;
                    case IDM_KEYSHELP :
                        HelpKeys ();
                        break;
                    case IDM_GENERALHELP :
                        HelpHelpForHelp ();
                        break;
                    case IDM_HELPPRODUCTINFO :
                        HelpAbout ();
                        break;
                    default :
                        break;
                }
                break;
            case HM_QUERY_KEYS_HELP :
                return ((MRESULT)PANEL_KEYSHELP);
            case MSG_UPDATE_WINDOW :
                WinQueryWindowRect (hwnd, &rcl);
                WinInvalidateRect (hwnd, &rcl, TRUE);
                WinPostMsg (hwnd, MSG_SIZE_TV, NULL, NULL);

        case WM_VRNDISABLED:
           return 0;                 /* hide this message from MMPM */

        case WM_VRNENABLED:
           /*
            * DJL 09/06/97 - Debug
            */
//         if (mp1)
           {                /* yes, visible region has changed */


              HRGN visRegion=0;
              ULONG retCode;
              HPS winPS;
              RECTL r[256];
              RGNRECT rectControl={0, 256, 0, RECTDIR_LFRT_BOTTOP};
              VCASETCLIPLIST vClip;
              int l;
              USHORT mciDevId;

//      DosBeep(200, 200);
//      DosBeep(200, 100);
//      DosBeep(200, 200);

              /* first get visible regions */
              winPS=WinGetPS(hwnd);
              visRegion=GpiCreateRegion(winPS, 0, NULL);
              retCode=WinQueryVisibleRegion(hwnd, visRegion);
              /* enumerate them, store all rectangles in 'r' */
              GpiQueryRegionRects(winPS, visRegion, NULL, &rectControl, r);

              /* now build the cliplist for the device driver */
              for (l=0; l<rectControl.crcReturned; l++)
              {
                  vClip.VisRect[l].X_Left=r[l].xLeft;
                  vClip.VisRect[l].X_Width=r[l].xRight-r[l].xLeft;
                  vClip.VisRect[l].Y_Top=r[l].yTop;
                  vClip.VisRect[l].Y_Height=r[l].yTop-r[l].yBottom;
              }
              vClip.ulNum_Rects=rectControl.crcReturned;
              vClip.ulFlags=0;
              vClip.ulLength=sizeof vClip;

#undef MCI
#ifdef MCI
              mciDevId=mciGetDeviceID( pchAlias );
              /* and send the CLIPLIST command to the device */
              retCode=mciSendCommand(mciDevId, MCI_ESCAPE, MCI_WAIT, &vClip, 0);
#else
              VcaiClipList (vClip);
#endif


              /* now clean up */
              GpiDestroyRegion(winPS, visRegion);
              WinReleasePS(winPS);
              /* that is all */
           }

           return 0; /* hide this message from MMPM as well */

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

MRESULT EXPENTRY NotebookDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    static  BOOL    start;
    HPS     hps;
    RECTL   rcl;
    ULONG   id, result;
    MCI_DEVICESETTINGS_PARMS   mci;
    HWND    hwndPage;
    LONG    bx, by, cx, cy, ty, x, y;
    SWP     swp;

        switch (msg)
        {
            case WM_INITDLG :
                HwndNotebook = WinWindowFromID (hwnd, IDD_NOTE_BOOK);
                WinSendMsg (HwndNotebook,
                            BKM_SETNOTEBOOKCOLORS, MPFROMLONG (CLR_PALEGRAY),
                            MPFROMSHORT (BKA_BACKGROUNDPAGECOLORINDEX));
                WinSendMsg (HwndNotebook,
                            BKM_SETNOTEBOOKCOLORS, MPFROMLONG (CLR_PALEGRAY),
                            MPFROMSHORT (BKA_BACKGROUNDMAJORCOLORINDEX));
                WinSendMsg (HwndNotebook,
                            BKM_SETNOTEBOOKCOLORS, MPFROMLONG (CLR_PALEGRAY),
                            MPFROMSHORT (BKA_BACKGROUNDMINORCOLORINDEX));
                cy = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
                if (cy <= 480)
                {
                    WinSendMsg (HwndNotebook, BKM_SETDIMENSIONS,
                                MPFROM2SHORT (100, 24),
                                MPFROMSHORT (BKA_MAJORTAB));
                    WinSendMsg (HwndNotebook, BKM_SETDIMENSIONS,
                                MPFROM2SHORT (75, 24),
                                MPFROMSHORT (BKA_MINORTAB));
                }
                else
                {
                    WinSendMsg (HwndNotebook, BKM_SETDIMENSIONS,
                                MPFROM2SHORT (150, 24),
                                MPFROMSHORT (BKA_MAJORTAB));
                    WinSendMsg (HwndNotebook, BKM_SETDIMENSIONS,
                                MPFROM2SHORT (100, 24),
                                MPFROMSHORT (BKA_MINORTAB));
                }
                mci.hwndCallback = HwndNBFrame;
                mci.hwndNotebook = HwndNotebook;
                mci.usDeviceType = 12;
                sprintf (txt, "TV0%ld", Connector);
                mci.pszDeviceName = txt;
                hwndPage = (HWND) InsertAddr (&mci);
                if (!hwndPage)
                {
                    msg_box ("Error Loading Pages", "Error",
                             MB_OK | MB_ERROR);
                    return 0;
                }
                NotebookOpen = TRUE;
                start = TRUE;
                WinPostMsg (hwnd, WM_PAINT, NULL, NULL);
                break;
            case WM_PAINT :
                if (start)
                {
                    size_notebook ();
                    start = FALSE;
                }
                hps = WinBeginPaint (hwnd, NULLHANDLE, &rcl);
                WinQueryWindowRect (hwnd, &rcl);
                WinFillRect (hps, &rcl, CLR_PALEGRAY);
                WinEndPaint (hps);
                break;
            case WM_ADJUSTWINDOWPOS :
            case WM_MOVE :
            case WM_SIZE :
            case WM_WINDOWPOSCHANGED :
                WinQueryWindowRect (HwndNBFrame, &rcl);
                bx = WinQuerySysValue (HWND_DESKTOP, SV_CXSIZEBORDER);
                by = WinQuerySysValue (HWND_DESKTOP, SV_CYSIZEBORDER);
                ty = WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR);
                WinSetWindowPos (HwndNotebook, HWND_TOP,
                                 bx, by, rcl.xRight - (bx * 2),
                                 rcl.yTop - ty - (by * 2),
                                 SWP_SIZE | SWP_MOVE | SWP_SHOW);
                break;
            case WM_COMMAND :
                return ((MRESULT) FALSE);
            case WM_CLOSE :
                WinDestroySecondaryWindow (HwndNBFrame);
                return ((MRESULT) FALSE);
            case WM_DESTROY :
                WinPostMsg (HwndFrame, WM_SIZE, NULL, NULL);
                NotebookOpen = FALSE;
                break;
            default :
                break;
        }
        return WinDefSecondaryWindowProc (hwnd, msg, mp1, mp2);
}

MRESULT EXPENTRY QuitDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
        switch (msg)
        {
            case WM_COMMAND :
                switch (SHORT1FROMMP (mp1))
                {
                    case DID_OK :
                        WinPostMsg (HwndFrame, WM_CLOSE, NULL, NULL);
                        WinDismissDlg (hwnd, TRUE);
                        break;
                    case DID_CANCEL :
                        WinDismissDlg (hwnd, TRUE);
                        break;
                    default :
                        break;
                }
                break;
            default :
                break;
        }
        return WinDefDlgProc (hwnd, msg, mp1, mp2);
}

MRESULT EXPENTRY AboutDlgProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
    HPS     hps;
    RECTL   rcl;
    LONG    x, y;
    CHAR    txt[80];

        switch (msg)
        {
            case WM_PAINT :
                hps = WinBeginPaint (hwnd, NULLHANDLE, &rcl);
                WinQueryWindowRect (hwnd, &rcl);
                WinFillRect (hps, &rcl, CLR_PALEGRAY);
                sprintf (txt, "%30.30s", DevInfo.ProdInfo);
                WinSetDlgItemText (hwnd, IDD_ABOUT_PROD_INFO, txt);
                sprintf (txt, "%30.30s", DevInfo.ManInfo);
                WinSetDlgItemText (hwnd, IDD_ABOUT_MAN_INFO, txt);
                sprintf (txt, "%10.10s", DevInfo.Version);
                WinSetDlgItemText (hwnd, IDD_ABOUT_VERSION, txt);
                WinDrawBorder (hps, &rcl, x, y, 0L, 0L, DB_AREAATTRS |
                               DB_DLGBORDER);
                WinEndPaint (hps);
                break;
            case WM_COMMAND :
                switch (SHORT1FROMMP (mp1))
                {
                    case DID_OK :
                        WinDismissDlg (hwnd, TRUE);
                        break;
                    default :
                        break;
                }
                break;
            default :
                break;
        }
        return WinDefDlgProc (hwnd, msg, mp1, mp2);
}

static void size_notebook ()
{
    LONG    bx, by, cx, cy, ty, x, y;
    RECTL   rcl;

        cx = WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
        cy = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
        x = cx / 8L;
        y = 0L;
        if (cy <= 480)
        {
            cx = 480;
            cy = 480;
        }
        else
        {
            cx = 640;
            cy = 600;
        }
        WinSetWindowPos (HwndNBFrame, HWND_TOP,
                         x, y, cx, cy,
                         SWP_SIZE | SWP_MOVE | SWP_SHOW);
        WinQueryWindowRect (HwndNBFrame, &rcl);
        bx = WinQuerySysValue (HWND_DESKTOP,
                               SV_CXSIZEBORDER);
        by = WinQuerySysValue (HWND_DESKTOP,
                               SV_CYSIZEBORDER);
        ty = WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR);
        WinSetWindowPos (HwndNotebook, HWND_TOP,
                         bx, by, rcl.xRight - (bx * 2),
                         rcl.yTop - ty - (by * 2),
                         SWP_SIZE | SWP_MOVE | SWP_SHOW);
}

static BOOL init_window ()
{
    CHAR    szClient[] = "Client";
    ULONG   flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_ICON |
                           FCF_SIZEBORDER | FCF_MINMAX | FCF_ACCELTABLE |
                           FCF_SHELLPOSITION | FCF_TASKLIST;

        DevInfo.Length = sizeof (VCADEVINFO);
        VcaiDeviceInfoGet (&DevInfo);
        sprintf (txt, "Example 5 - %s %u", DevType, DevInstance);


        if (!WinRegisterClass (Hab, szClient, ClientWndProc,
                               CS_SIZEREDRAW | CS_MOVENOTIFY, 0))
            return (FALSE);

        if (!WinRegisterGraphicButton ())
            return (FALSE);

        HwndFrame = WinCreateStdWindow (HWND_DESKTOP,
                                        WS_VISIBLE,
                                        &flFrameFlags,
                                        szClient,
                                        txt,
//                                        WS_SYNCPAINT | WS_VISIBLE,
                                        0,
                                        (HMODULE) NULLHANDLE,
                                        IDR_MAIN,
                                        &HwndClient);
        if (!HwndFrame)
            return (FALSE);

    // Turn on visible region notification.
        WinSetVisibleRegionNotify (HwndClient, TRUE);

        WinPostMsg (HwndFrame, WM_VRNENABLED, 0L, 0L);

        HelpInit (HwndFrame);

        if (!init_video ())
            return (FALSE);

        if (!init_audio ())
            return (FALSE);

        return (TRUE);
}

static void init_colour ()
{
    HDC     hdc;
    DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL,
                        NULL};

        hdc = DevOpenDC (Hab, OD_INFO, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE);
        DevQueryCaps (hdc, CAPS_COLORS, 1L, &NumColours);
        DevCloseDC (hdc);
}

static void map_pallete (HPS hps)
{
    LONG    rc;
    VCASCREENINFO vs;
    USHORT cx, cy, i;

        if ((NumColours <= 256) && (NumColours > 0))
        {
            rc = GpiQueryRealColors (hps, 0L, 0L, NumColours, Colours);
            if (rc == GPI_ALTERROR)
            {
                err_msg ("GpiQueryRealColors");
                return;
            }
        }
        cx = WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
        cy = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
        vs.ulLength = sizeof (VCASCREENINFO);
        vs.ul_RESV01 = 0L;
        vs.ulWidth = (ULONG) cx;
        vs.ulHeight = (ULONG) cy;
        vs.ulNumColours = (ULONG) NumColours;
        vs.ulHFreq = 0L;
        vs.ulVFreq = 0L;
        if ((ULONG)NumColours <= 256)
        {
            for (i = 0; i < NumColours; i++)
                vs.ulRGB[i] = (ULONG) Colours[i];
        }
        else
        {
            for (i = 0; i < 256; i++)
                vs.ulRGB[i] = 0L;
        }
        VcaiScreenInfoSet (&vs);
        rc = GpiCreateLogColorTable (hps, LCOL_RESET, LCOLF_RGB,
                                     0L, 0L, (PLONG)0L);
        if (!rc)
        {
            err_msg ("GpiCreateLogColorTable");
            return;
        }
}

static void check_menu_item (short item_id, short state)
{
        WinPostMsg (HwndMenu, MM_SETITEMATTR,
                    MPFROM2SHORT (item_id, TRUE),
                    MPFROM2SHORT (MIA_CHECKED, state));
}

static void enable_menu_item (short item_id, short state)
{
        WinPostMsg (HwndMenu, MM_SETITEMATTR,
                    MPFROM2SHORT (item_id, TRUE),
                    MPFROM2SHORT (MIA_DISABLED, state));
}
