ShowPop2.mod: Translation to Stony Brook Modula-2

Last updated: 15. 1.1998, 21:42

<*/NOWARN:F*>
MODULE ShowPop2;
(*------------------------------------------
   SHOWPOP2.C      --- DDEML Client using DDEPOP2
                   (c) Charles Petzold, 1996
   ShowPop2.mod    --- Translation to Stony Brook Modula-2
                   (c) Peter Stadler,   1998
  ------------------------------------------*)
IMPORT Helper;
IMPORT WINUSER;
IMPORT WINGDI;
IMPORT WIN32;
IMPORT WINX;
IMPORT SYSTEM;
IMPORT DDEML;
IMPORT h2d_showpop;
IMPORT Str;

CONST WM_USER_INITIATE = WINUSER.WM_USER + 1;
CONST DDE_TIMEOUT      = 3000;
      szAppName        = "ShowPop2";
CONST
     szService = "DdePop2";
     szTopic   = "US_Population";
VAR
  cxChar     :   WIN32.LONG;
  cyChar     :   WIN32.LONG;
VAR
  idInst  :  WIN32.DWORD;
  hConv   :  DDEML.HCONV;
  hwnd    :  WIN32.HWND;
  wc      :  WINUSER.WNDCLASSEX;
  msg     :  WINUSER.MSG;
  ok      :  BOOLEAN;
<*/PUSH*>
%IF WIN32 %THEN
    <*/CALLS:WIN32SYSTEM*>
%ELSE
    <*/CALLS:WINSYSTEM*>
%END
(*++++*****************************************************************)
PROCEDURE DdeCallback (iType       : WIN32.UINT;
(**********************************************************************)
                       iFmt        : WIN32.UINT;
                       hConv       : DDEML.HCONV;
                       hsz1        : WIN32.WPARAM;
                       hsz2        : WIN32.WPARAM;
                       hData       : WIN32.WPARAM;
                       dwData1     : WIN32.DWORD;
                       dwData2     : WIN32.DWORD) : DDEML.HDDEDATA [EXPORT];
VAR
  szPopulation :  ARRAY[0..15] OF CHAR;
  szItem       :  ARRAY[0..15] OF CHAR;
  i        :  INTEGER;
BEGIN
     CASE (iType) OF
          | DDEML.XTYP_ADVDATA :    (* hsz1  := topic                           *)
                                    (* hsz2  := item                            *)
                                    (* hData := data                            *)

                    (* Check for matching format and data item          *)

               IF (iFmt # WINUSER.CF_TEXT) THEN
                    RETURN DDEML.DDE_FNOTPROCESSED;
               END;

               DDEML.DdeQueryString (idInst, hsz2, szItem, SIZE (szItem), 0);

               i := 0;
               LOOP
                    IF (Str.Compare(szItem, h2d_showpop.pop[i].szAbb^) = 0) THEN
                         EXIT;
                    END;
                    INC(i);
                    IF(i>=h2d_showpop.NUM_STATES) THEN
                      EXIT;
                    END;
               END;
               IF (i >= h2d_showpop.NUM_STATES) THEN
                    RETURN DDEML.DDE_FNOTPROCESSED;
               END;

                    (* Store the data and invalidate the window                *)

               DDEML.DdeGetData (hData, SYSTEM.ADR(szPopulation),
                           SIZE (szPopulation), 0);

               h2d_showpop.pop[i].lPop := Str.StrToInt(szPopulation,10,ok);

               WINUSER.InvalidateRect (hwnd, WINX.NIL_RECT, FALSE);

               RETURN SYSTEM.CAST(DDEML.HDDEDATA, DDEML.DDE_FACK);

          | DDEML.XTYP_DISCONNECT :
               hConv := 0;

               WINUSER.MessageBox (hwnd, "The server has disconnected.",
                           szAppName, WINUSER.MB_ICONASTERISK BOR WINUSER.MB_OK);

               RETURN 0;
     ELSE

               RETURN 0;
     END;
END DdeCallback;
<*/POP*>

<*/PUSH*>
%IF WIN32 %THEN
    <*/CALLS:WIN32SYSTEM*>
%ELSE
    <*/CALLS:WINSYSTEM*>
%END
(*++++*****************************************************************)
PROCEDURE WndProc      (hwnd        : WIN32.HWND;
(**********************************************************************)
                       iMsg        : WIN32.UINT;
                       wParam      : WIN32.WPARAM;
                       lParam      : WIN32.LPARAM) : WIN32.LRESULT [EXPORT];
VAR
  hszItem         :  DDEML.HSZ;
  hszService      :  DDEML.HSZ;
  hszTopic        :  DDEML.HSZ;
  i               :  INTEGER;
  szBuffer        :  ARRAY[0..23] OF CHAR;
  hdc             :  WIN32.HDC;
  ps              :  WINUSER.PAINTSTRUCT;
  x               :  WIN32.LONG;
  y               :  WIN32.LONG;
  tm              :  WINGDI.TEXTMETRIC;
BEGIN

     CASE (iMsg) OF
          | WINUSER.WM_CREATE :
               hdc := WINUSER.GetDC (hwnd);
               WINGDI.GetTextMetrics (hdc, tm);
               cxChar := tm.tmAveCharWidth;
               cyChar := tm.tmHeight + tm.tmExternalLeading;
               WINUSER.ReleaseDC (hwnd, hdc);

               RETURN 0;

          | WM_USER_INITIATE :

                         (* Try connecting                                     *)

               hszService := DDEML.DdeCreateStringHandle (idInst, szService, 0);
               hszTopic   := DDEML.DdeCreateStringHandle (idInst, szTopic,   0);

               hConv := DDEML.DdeConnect (idInst, hszService, hszTopic, NIL);

                         (* If that doesn't work, load server                  *)

               IF (hConv = 0) THEN
                    WIN32.WinExec (szService, WINUSER.SW_SHOWMINNOACTIVE);

                    hConv := DDEML.DdeConnect (idInst, hszService, hszTopic, NIL);
               END;

                         (* Free the string handles                            *)

               DDEML.DdeFreeStringHandle (idInst, hszService);
               DDEML.DdeFreeStringHandle (idInst, hszTopic);

                         (* If still not connected, display message box        *)

               IF (hConv = 0) THEN
                    WINUSER.MessageBox (hwnd, "Cannot connect with DDEPOP2.EXE!",
                                szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK);

                    RETURN 0;
               END;

                         (* Request notification                               *)

               FOR i := 0 TO h2d_showpop.NUM_STATES-1 DO
                    hszItem := DDEML.DdeCreateStringHandle (idInst, h2d_showpop.pop[i].szAbb^, 0);

                    DDEML.DdeClientTransaction (NIL, 0, hConv, hszItem, WINUSER.CF_TEXT,
                                          DDEML.XTYP_ADVSTART BOR DDEML.XTYPF_ACKREQ,
                                          DDE_TIMEOUT, WINX.NIL_DWORD);

                    DDEML.DdeFreeStringHandle (idInst, hszItem);
               END;

               IF (i < h2d_showpop.NUM_STATES) THEN
                    WINUSER.MessageBox (hwnd, "Failure on WM_DDE_ADVISE!",
                                szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK);
               END;

               RETURN 0;

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

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

                    WINGDI.TextOut (hdc, x, y, szBuffer,
                             WINUSER.wsprintf (szBuffer, "%-20s",
                                       SYSTEM.CAST(WIN32.PSTR,h2d_showpop.pop[i].szState)));

                    x := x + 36 * cxChar;

                    WINGDI.SetTextAlign (hdc, WINGDI.TA_RIGHT BOR WINGDI.TA_TOP);

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

                    WINGDI.SetTextAlign (hdc, WINGDI.TA_LEFT BOR WINGDI.TA_TOP);
               END;

               WINUSER.EndPaint (hwnd, ps);
               RETURN 0;

          | WINUSER.WM_CLOSE :
               IF (hConv # 0) THEN

                         (* Stop the advises                                   *)

                 FOR i := 0 TO h2d_showpop.NUM_STATES-1 DO
                      hszItem := DDEML.DdeCreateStringHandle (idInst, h2d_showpop.pop[i].szAbb^, 0);

                      DDEML.DdeClientTransaction (NIL, 0, hConv, hszItem, WINUSER.CF_TEXT,
                                            DDEML.XTYP_ADVSTOP, DDE_TIMEOUT, WINX.NIL_DWORD);

                      DDEML.DdeFreeStringHandle (idInst, hszItem);
                 END;

                           (* Disconnect the conversation                        *)

                 DDEML.DdeDisconnect (hConv);

               END;
	                          (* for default processing DO            *)

          | WINUSER.WM_DESTROY :
               WINUSER.PostQuitMessage (0);
               RETURN 0;
     ELSE
               RETURN WINUSER.DefWindowProc (hwnd, iMsg, wParam, lParam);
     END;
END WndProc;
<*/POP*>

(*++++*****************************************************************)
PROCEDURE InitApplication () : BOOLEAN;
(**********************************************************************)
VAR
  rc    :  CARDINAL;

BEGIN
  wc.cbSize        := SIZE(wc);
  wc.style         := WINUSER.CS_HREDRAW BOR WINUSER.CS_VREDRAW;
  wc.style         := 0;
  wc.lpfnWndProc   := WndProc;
  wc.cbClsExtra    := 0;
  wc.cbWndExtra    := 0;
  wc.hInstance     := WINX.Instance;
  wc.hIcon         := WINUSER.LoadIcon (WINX.Instance,szAppName);
  wc.hCursor       := WINUSER.LoadCursor (NIL, WINUSER.IDC_ARROW^);
  wc.hbrBackground := SYSTEM.CAST(WIN32.HBRUSH, WINGDI.GetStockObject (WINGDI.WHITE_BRUSH));
  wc.lpszMenuName  := NIL;
  wc.lpszClassName := SYSTEM.ADR(szAppName);
  wc.hIconSm       := WINUSER.LoadIcon (WINX.Instance,szAppName);
  rc := WINUSER.RegisterClassEx(wc);
  RETURN rc#0;
END InitApplication;

(*++++*****************************************************************)
PROCEDURE InitMainWindow () : BOOLEAN;
(**********************************************************************)
BEGIN
  hwnd := WINUSER.CreateWindow (szAppName,
                        "DDEML Client - US Population: Translation to Stony Brook Modula-2",
                        WINUSER.WS_OVERLAPPEDWINDOW,
                        WINUSER.CW_USEDEFAULT,
                        WINUSER.CW_USEDEFAULT,
                        WINUSER.CW_USEDEFAULT,
                        WINUSER.CW_USEDEFAULT,
                        NIL,
                        NIL,
                        WINX.Instance,
                        NIL);
   WINUSER.ShowWindow (hwnd, WINUSER.SW_SHOWMINNOACTIVE);
   WINUSER.UpdateWindow (hwnd);
               (* Initialize for using DDEML                            *)

     IF (DDEML.DdeInitialize (idInst, SYSTEM.CAST(DDEML.PFNCALLBACK,SYSTEM.ADR(DdeCallback)),
                        DDEML.APPCLASS_STANDARD BOR DDEML.APPCMD_CLIENTONLY, 0h)=1) THEN
          WINUSER.MessageBox (hwnd, "Could not initialize server!",
                      szAppName, WINUSER.MB_ICONEXCLAMATION BOR WINUSER.MB_OK);
          WINUSER.DestroyWindow (hwnd);
          RETURN FALSE;
     END;

               (* Start things going                                           *)

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

END InitMainWindow;


BEGIN
  IF InitApplication()  AND  InitMainWindow() THEN
    WHILE (WINUSER.GetMessage(msg,NIL,0,0)) DO
      WINUSER.TranslateMessage(msg);
      WINUSER.DispatchMessage(msg);
    END;
               (* Uninitialize DDEML                                           *)

    DDEML.DdeUninitialize (idInst);
  END;
END ShowPop2.