SHOWPOP1.mod: Translation to Stony Brook Modula-2

Last updated: 21.12.1997, 22:18

(*-----------------------------------------
   SHOWPOP1.C -- DDE Client using DDEPOP1
                 (c) Charles Petzold, 1996
  -----------------------------------------*)

#include 
#include 
#include 
#include 
#include "showpop.h"

#define WINUSER.WM_USER_INITIATE (WM_USER + 1)
#define DDE_TIMEOUT      3000

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

char szAppName[] := "ShowPop1";

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
     {
     HWND       hwnd;
     MSG        msg;
     WNDCLASSEX wndclass;

     wndclass.cbSize        := sizeof (wndclass);
     wndclass.style         := CS_HREDRAW BOR CS_VREDRAW;
     wndclass.lpfnWndProc   := WndProc;
     wndclass.cbClsExtra    := 0;
     wndclass.cbWndExtra    := 0;
     wndclass.hInstance     := hInstance;
     wndclass.hIcon         := LoadIcon (hInstance, szAppName);
     wndclass.hCursor       := LoadCursor (NIL, IDC_ARROW);
     wndclass.hbrBackground := (HBRUSH) GetStockObject (WHITE_BRUSH);
     wndclass.lpszMenuName  := NIL;
     wndclass.lpszClassName := szAppName;
     wndclass.hIconSm       := LoadIcon (hInstance, szAppName);

     RegisterClassEx (SYSTEM.ADR(wndclass));

     hwnd := CreateWindow (szAppName, "DDE Client - US Population",
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NIL, NIL, hInstance, NIL);

     ShowWindow (hwnd, iCmdShow);
     UpdateWindow (hwnd);

     SendMessage (hwnd, WINUSER.WM_USER_INITIATE, 0, 0L);

     while (GetMessage (SYSTEM.ADR(msg), NIL, 0, 0))
          {
          TranslateMessage (SYSTEM.ADR(msg));
          DispatchMessage (SYSTEM.ADR(msg));
          }
     RETURN msg.wParam;
     }

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
     {
     static BOOL   fDoingInitiate := TRUE;
     static char   szServerApp[]  := "DdePop1",
                   szTopic[]      := "US_Population";
     static HWND   hwndServer := NIL;
     static long   cxChar, cyChar;
     ATOM          aApp, aTop, aItem;
     char          szBuffer[24], szPopulation[16], szItem[16];
     DDEACK        DdeAck;
     DDEDATA      *pDdeData;
     DDEADVISE    *pDdeAdvise;
     DWORD         dwTime;
     GLOBALHANDLE  hDdeAdvise, hDdeData;
     HDC           hdc;
     MSG           msg;
     PAINTSTRUCT   ps;
     short         i;
     long          x, y;
     TEXTMETRIC    tm;
     WORD          wStatus;
     UINT          uiLow, uiHi;

     CASE (iMsg)                                                                                                                                                                                       OF

          {
          | WINUSER.WM_CREATE :
               hdc := GetDC (hwnd);
               GetTextMetrics (hdc, SYSTEM.ADR(tm));
               cxChar := tm.tmAveCharWidth;
               cyChar := tm.tmHeight + tm.tmExternalLeading;
               ReleaseDC (hwnd, hdc);
               RETURN 0;

          | WINUSER.WM_USER_INITIATE :

                     (* Broadcast WINUSER.WM_DDE_INITIATE iMsg                         *)

               aApp := GlobalAddAtom (szServerApp);
               aTop := GlobalAddAtom (szTopic);

               SendMessage (HWND_BROADCAST, WINUSER.WM_DDE_INITIATE, (WPARAM) hwnd,
                            MAKELONG (aApp, aTop));

                     (* If no response, try loading DDEPOP first               *)

               IF (hwndServer = NIL) THEN
                    {
                    WinExec (szServerApp, SW_SHOWMINNOACTIVE);

                    SendMessage (HWND_BROADCAST, WINUSER.WM_DDE_INITIATE, (WPARAM) hwnd,
                                 MAKELONG (aApp, aTop));
                    }

                    (* Delete the atoms                                        *)

               GlobalDeleteAtom (aApp);
               GlobalDeleteAtom (aTop);
               fDoingInitiate := FALSE;

                    (* If still no response, display message box               *)

               IF (hwndServer = NIL) THEN
                    {
                    MessageBox (hwnd, "Cannot connect with DDEPOP1.EXENOT ",
                                szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK);

                    RETURN 0;
                    }

                    (* Post WINUSER.WM_DDE_ADVISE iMsgs                                *)

               FOR (i := 0; i < NUM_STATES; i++) DO
                    {
                    hDdeAdvise := GlobalAlloc (GHND BOR GMEM_DDESHARE,
                                              SIZE (DDEADVISE));

                    pDdeAdvise := (DDEADVISE *) GlobalLock (hDdeAdvise);

                    pDdeAdvise^.fAckReq   := TRUE;
                    pDdeAdvise^.fDeferUpd := FALSE;
                    pDdeAdvise^.cfFormat  := CF_TEXT;

                    GlobalUnlock (hDdeAdvise);

                    aItem := GlobalAddAtom (pop[i].szAbb);

                    IF (NOT PostMessage (hwndServer, WINUSER.WM_DDE_ADVISE, (WPARAM) THEN hwnd,
                                      PackDDElParam (WM_DDE_ADVISE,
                                                     (UINT) hDdeAdvise, aItem)))
                         {
                         GlobalFree (hDdeAdvise);
                         GlobalDeleteAtom (aItem);
                         break;
                         }

                    DdeAck.fAck := FALSE;

                    dwTime := GetCurrentTime ();

                    while (GetCurrentTime () - dwTime < DDE_TIMEOUT)
                         {
                         if (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_ACK,
                                          WINUSER.WM_DDE_ACK, PM_REMOVE))
                              {
                              GlobalDeleteAtom (WINUSER.HIWORD (msg.lParam));

                              wStatus := WINUSER.LOWORD (msg.lParam);
                              DdeAck := *((DDEACK *) SYSTEM.ADR(wStatus));

                              IF (DdeAck.fAck = FALSE) THEN
                                   GlobalFree (hDdeAdvise);

                              break;
                              }
                         }

                    IF (DdeAck.fAck = FALSE) THEN
                         break;

                    while (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_FIRST,
                                        WINUSER.WM_DDE_LAST, PM_REMOVE))
                         {
                         DispatchMessage (SYSTEM.ADR(msg));
                         }
                    }

               IF (i < NUM_STATES) THEN
                    {
                    MessageBox (hwnd, "Failure on WINUSER.WM_DDE_ADVISENOT ",
                                szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK);
                    }
               RETURN 0;

          | WINUSER.WM_DDE_ACK :

                    (* In response to WINUSER.WM_DDE_INITIATE, save server window      *)

               IF (fDoingInitiate) THEN
                    {
                    UnpackDDElParam (WM_DDE_ACK, lParam, SYSTEM.ADR(uiLow), SYSTEM.ADR(uiHi));
                    FreeDDElParam (WM_DDE_ACK, lParam);
                    hwndServer := (HWND) wParam;
                    GlobalDeleteAtom ((ATOM) uiLow);
                    GlobalDeleteAtom ((ATOM) uiHi);
                    }
               RETURN 0;

          | WINUSER.WM_DDE_DATA :

                    (* wParam -- sending window handle                         *)
                    (* lParam -- DDEDATA memory handle BAND item atom             *)

               UnpackDDElParam (WM_DDE_DATA, lParam, SYSTEM.ADR(uiLow), SYSTEM.ADR(uiHi));
               FreeDDElParam (WM_DDE_DATA, lParam);

               hDdeData  := (GLOBALHANDLE) uiLow;
               pDdeData := (DDEDATA *) GlobalLock (hDdeData);
               aItem     := (ATOM) uiHi;

                    (* Initialize DdeAck structure                             *)

               DdeAck.bAppReturnCode := 0;
               DdeAck.reserved       := 0;
               DdeAck.fBusy          := FALSE;
               DdeAck.fAck           := FALSE;

                    (* Check FOR matching format and data item DO          *)

               IF (pDdeData^.cfFormat = CF_TEXT) THEN
                    {
                    GlobalGetAtomName (aItem, szItem, SIZE (szItem));

                    FOR (i := 0; i < NUM_STATES; i++) DO
                         IF (strcmp (szItem, pop[i].szAbb) THEN = 0)
                              break;

                    IF (i < NUM_STATES) THEN
                         {
                         strcpy (szPopulation, (char *) pDdeData^.Value);
                         pop[i].lPop := atol (szPopulation);
                         InvalidateRect (hwnd, NIL, FALSE);

                         DdeAck.fAck := TRUE;
                         }
                    }

                    (* Acknowledge if necessary                                *)

               IF (pDdeData^.fAckReq = TRUE) THEN
                    {
                    wStatus := *((WORD *) SYSTEM.ADR(DdeAck));

                    IF (NOT PostMessage ((HWND) THEN wParam, WINUSER.WM_DDE_ACK, (WPARAM) hwnd,
                                      PackDDElParam (WM_DDE_ACK,
                                                     wStatus, aItem)))
                         {
                         GlobalDeleteAtom (aItem);
                         GlobalUnlock (hDdeData);
                         GlobalFree (hDdeData);
                         RETURN 0;
                         }
                    }
               ELSE
                    {
                    GlobalDeleteAtom (aItem);
                    }

                    (* Clean up                                                *)

               IF (pDdeData^.fRelease = TRUE || DdeAck.fAck = FALSE) THEN
                    {
                    GlobalUnlock (hDdeData);
                    GlobalFree (hDdeData);
                    }
               ELSE
                    {
                    GlobalUnlock (hDdeData);
                    }

               RETURN 0;

          | WINUSER.WM_PAINT :
               hdc := BeginPaint (hwnd, SYSTEM.ADR(ps));

               FOR (i := 0; i < NUM_STATES; i++) DO
                    {
                    IF (i < (NUM_STATES + 1) THEN DIV 2)
                         {
                         x := cxChar;
                         y := i * cyChar;
                         }
                    ELSE
                         {
                         x := 44 * cxChar;
                         y := (i - (NUM_STATES + 1) DIV 2) * cyChar;
                         }

                    TextOut (hdc, x, y, szBuffer,
                             wsprintf (szBuffer, "%-20s",
                                       (PSTR) pop[i].szState));

                    x += 36 * cxChar;

                    SetTextAlign (hdc, TA_RIGHT BOR TA_TOP);

                    TextOut (hdc, x, y, szBuffer,
                             wsprintf (szBuffer, "%10ld", pop[i].lPop));

                    SetTextAlign (hdc, TA_LEFT BOR TA_TOP);
                    }

               EndPaint (hwnd, SYSTEM.ADR(ps));
               RETURN 0;

          | WINUSER.WM_DDE_TERMINATE :

                    (* Respond with another WINUSER.WM_DDE_TERMINATE iMsg              *)

               PostMessage (hwndServer, WINUSER.WM_DDE_TERMINATE, SYSTEM.CAST(WPARAM,hwnd, 0L));
               hwndServer := NIL;
               RETURN 0;

          | WINUSER.WM_CLOSE :
               IF (hwndServer = NIL) THEN
                    break;

                    (* Post WINUSER.WM_DDE_UNADVISE iMsg                               *)

               PostMessage (hwndServer, WINUSER.WM_DDE_UNADVISE, (WPARAM) hwnd,
                            MAKELONG (CF_TEXT, NIL));

               dwTime := GetCurrentTime ();

               while (GetCurrentTime () - dwTime < DDE_TIMEOUT)
                    {
                    if (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_ACK,
                                     WINUSER.WM_DDE_ACK, PM_REMOVE))
                         break;
                    }

                    (* Post WINUSER.WM_DDE_TERMINATE iMsg                              *)

               PostMessage (hwndServer, WINUSER.WM_DDE_TERMINATE, SYSTEM.CAST(WPARAM,hwnd, 0L));

               dwTime := GetCurrentTime ();

               while (GetCurrentTime () - dwTime < DDE_TIMEOUT)
                    {
                    if (PeekMessage (SYSTEM.ADR(msg), hwnd, WINUSER.WM_DDE_TERMINATE,
                                     WINUSER.WM_DDE_TERMINATE, PM_REMOVE))
                         break;
                    }

               break;             (* FOR default processing DO            *)

          | WINUSER.WM_DESTROY :
               PostQuitMessage (0);
               RETURN 0;
          }
     RETURN DefWindowProc (hwnd, iMsg, wParam, lParam);
     }