home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l360 / 3.ddi / DDE.@EM / DDE.CBL next >
Encoding:
Text File  |  1991-04-08  |  52.0 KB  |  1,231 lines

  1.       $set ans85 noosvs mf
  2.  
  3.       *******************************************************************
  4.       *                                                                 *
  5.       *     DDE example using COBOL                                     *
  6.       *                                                                 *
  7.       *             by Raymond Obin                                     *
  8.       *             (C) 1990 Micro Focus Ltd.                           *
  9.       *                                                                 *
  10.       *             Written 12 June 1990                                *
  11.       *                                                                 *
  12.       *******************************************************************
  13.       *                                                                 *
  14.       *     This DDE example can be used with either Excel (with the    *
  15.       *     noted restrictions) or with DDE2, which pretends to be      *
  16.       *     Excel for the purpose of this example.                      *
  17.       *                                                                 *
  18.       *     This DDE example makes use of the DDE Manager which is      *
  19.       *     supplied with the Microsoft OS/2 1.2 Programmers Toolkit.   *
  20.       *                                                                 *
  21.       *     DDEMGR.DLL is supplied with this example, and should be     *
  22.       *     placed in a LIBPATH directory (eg C:\OS2\DLL)               *
  23.       *     The source for DDEMGR is available from Microsoft as part   *
  24.       *     of the Programmers Toolkit, and you should refer to this    *
  25.       *     source code for documentation on the DDE Manager.           *
  26.       *                                                                 *
  27.       *******************************************************************
  28.       *                                                                 *
  29.       *     Running instructions:                                       *
  30.       *         If you are using DDE and DDE2, either program can be    *
  31.       *         started first, and either can be closed down first.     *
  32.       *         If you are using DDE and Excel, you must start          *
  33.       *         Excel first, but either can be closed down fitst.       *
  34.       *                                                                 *
  35.       *     See 'About this example program' for instruction on how     *
  36.       *     to make these programs communicate.                         *
  37.       *                                                                 *
  38.       *******************************************************************
  39.       *                                                                 *
  40.       *     The use made of DDEMGR is documented in this program, and   *
  41.       *     is also used in DDE2.  Comments in DDE2 are sparse, but     *
  42.       *     the essence is the same as in this program.                 *
  43.       *                                                                 *
  44.       *******************************************************************
  45.       *                                                                 *
  46.       *     Comments which refer to DDE Manager conventions/functions   *
  47.       *     are noted with DDE in cols 1-3                              *
  48.       *                                                                 *
  49. DDE   *     A DDE Manager Comment                                       *
  50.       *                                                                 *
  51.       *******************************************************************
  52.       *                                                                 *
  53.       *     Overview of DDE                                             *
  54.       *                                                                 *
  55.       *     Dynamic Data Exchance (or DDE) is a protocol by which       *
  56.       *     applications can exchange data.  It is set up so that       *
  57.       *     an application can ask to be notified when a particular     *
  58.       *     piece of data changes.                                      *
  59.       *     A trivial example might be a spread sheet wanting to know   *
  60.       *     about stock market shifts.  The spread sheet sets itself    *
  61.       *     up as a DDE Client, and talks to a DDE Server that knows    *
  62.       *     about Stock prices.  The Client asks the Server to update   *
  63.       *     it each time certain stocks change their value, and thus    *
  64.       *     the spread sheet can be kept up to date.                    *
  65.       *                                                                 *
  66.       *******************************************************************
  67.       *                                                                 *
  68.       *     About this example program                                  *
  69.       *                                                                 *
  70.       *     DDE creates a window with a DDE Status line at the bottom   *
  71.       *     with some scroll bars on the left and a colour block on     *
  72.       *     the top right.                                              *
  73.       *                                                                 *
  74.       *     DDE automatically starts a conversation with 'Excel'        *
  75.       *     ('Excel' is the DDE Name used by Excel and DDE2) and        *
  76.       *     will set R1C1 (ie Position A1) of 'Sheet1' to contain the   *
  77.       *     word 'Red'.  This is the colour of the colour block you     *
  78.       *     will see.                                                   *
  79.       *     If Excel is not already running, DDE will notice when Excel *
  80.       *     is started, and begin the conversation then.                *
  81.       *                                                                 *
  82.       *     You can select Excel and change the colour by typing into   *
  83.       *     cell A1 any of the following values:                        *
  84.       *         Red, Yellow, Blue, Green, Black, White, Cyan, Magenta   *
  85.       *                                                                 *
  86.       *     When you do, you will notice that the colour block will     *
  87.       *     change colour to reflect the value you typed.               *
  88.       *                                                                 *
  89.       *     DDE has told Excel that it wants to know when R1C1 changes, *
  90.       *     and when it receives the new value, it adjusts the Colour   *
  91.       *     block accordingly.                                          *
  92.       *                                                                 *
  93.       *     If you are using DDE2 instead of Excel, you can select      *
  94.       *     a new colour from the list box containing the choices.      *
  95.       *                                                                 *
  96.       *     This is an example of Excel acting as a Server, and DDE     *
  97.       *     as a Client.                                                *
  98.       *                                                                 *
  99.       *     DDE and Excel can be Client and Server at the same time,    *
  100.       *     and the 3 scroll bars illustrate Excel as the Client and    *
  101.       *     DDE as the Server.                                          *
  102.       *                                                                 *
  103.       *     If you take a cell in Excel (eg A3) and enter the formula:  *
  104.       *                                                                 *
  105.       *         =COBOLDDE|TestData!Number1                              *
  106.       *         =              indicates that this is a formula         *
  107.       *          COBOLDDE      is the name of the server application    *
  108.       *                  |     (ALT+124) indicates that a remote link   *
  109.       *                        is being established                     *
  110.       *                   TestData       is the Server Topic            *
  111.       *                           !      separates the topic and the id *
  112.       *                            Number1 is the data itentifier       *
  113.       *                                                                 *
  114.       *     DDE will respond with the the setting of the lower scroll   *
  115.       *     bar.  (Lower scroll bar is 'Number1', middle is 'Number2',  *
  116.       *     upper is 'Number3')                                         *
  117.       *                                                                 *
  118.       *     There is a problem with Excel and the DDE Manager which     *
  119.       *     means that the cell will only be updated the first time     *
  120.       *     you move the scroll bar.  Attempts to isolate this problem  *
  121.       *     have so far been unsuccessful, but there appears to be      *
  122.       *     a small incompatibility between Excel and the DDEMgr.       *
  123.       *                                                                 *
  124.       *     If you use DDE2 instead of Excel, you can move the scroll   *
  125.       *     bars around and continue to see the values updated.         *
  126.       *                                                                 *
  127.       *     The 'hot link' between DDE2 and DDE is created (for all     *
  128.       *     three 'Number's by pressing the Initiate button.            *
  129.       *     Initial values are obtained from DDE for the slider         *
  130.       *     positions, and any changes are reflected.                   *
  131.       *                                                                 *
  132.       *     The 'hot link' can be terminated by pressing 'Terminate'.   *
  133.       *                                                                 *
  134.       *******************************************************************
  135.       *                                                                 *
  136.       *     There are some stability problems with this example,        *
  137.       *     in particular the machine hangs if you Terminate and        *
  138.       *     Initiate repeatedly.  These problems have not been          *
  139.       *     isolated.                                                   *
  140.       *                                                                 *
  141.       *******************************************************************
  142.       *                                                                 *
  143.       *     This example make extensive use of the Micro Focus          *
  144.       *     Systems Programming Extensions to COBOL.                    *
  145.       *     See your documentation and the other Presentation Manager   *
  146.       *     sample programs for details of these.                       *
  147.       *                                                                 *
  148.       *******************************************************************
  149.  
  150.     special-names.
  151.         call-convention 3 is OS2API.
  152.  
  153.         working-storage section.
  154.  
  155.       * PM Window Messages sent the the Client Window
  156.  
  157.         78  WM-CREATE               value   h"01".
  158.         78  WM-DESTROY              value   h"02".
  159.         78  WM-PAINT                value   h"23".
  160.         78  WM-CONTROL              value   h"30".
  161.         78  WM-HSCROLL              value   h"32".
  162.         78  WM-SIZE                 value   h"07".
  163.  
  164.       * User message for synchronizing the DDE commencement
  165.  
  166.         78  WMUSER-INITDDE          value   h"2000".
  167.         78  WMUSER-FREEHSZ          value   h"2001".
  168.  
  169.       * PM Scroll Bar messages
  170.  
  171.         78  SBM-SETSCROLLBAR        value   h"01a0".
  172.         78  SBM-SETPOS              value   h"01a1".
  173.         78  SBM-QUERYPOS            value   h"01a2".
  174.  
  175.         78  SB-LINELEFT             value   1.
  176.         78  SB-LINERIGHT            value   2.
  177.         78  SB-PAGELEFT             value   3.
  178.         78  SB-PAGERIGHT            value   4.
  179.         78  SB-SLIDERTRACK          value   5.
  180.         78  SB-SLIDERPOSITION       value   6.
  181.         78  SB-ENDSCROLL            value   7.
  182.  
  183.       * Other constants used by PM
  184.  
  185.         78  SYSCLR-WINDOW           value   -20.
  186.         78  SYSCLR-WINDOWTEXT       value   -17.
  187.  
  188.         78  SIZEMOVESHOW            value   h"0b".
  189.  
  190.         78  WC-SCROLLBAR            value   h"ffff0008".
  191.  
  192.         78  HWND-DESKTOP            value   1.
  193.         78  HWND-TOP                value   3.
  194.  
  195.       * PM Colour constants
  196.  
  197.         78  CLR-WHITE               value   -2.
  198.         78  CLR-BLACK               value   -1.
  199.         78  CLR-BLUE                value   1.
  200.         78  CLR-RED                 value   2.
  201.         78  CLR-MAGENTA             value   3.
  202.         78  CLR-GREEN               value   4.
  203.         78  CLR-CYAN                value   5.
  204.         78  CLR-YELLOW              value   6.
  205.  
  206. DDE   * DDEMGR constants
  207.  
  208. DDE   * DDE Format used by this program
  209.         78  DDEFMT-TEXT             value   1.
  210.  
  211. DDE   * DDE Acknowledgement
  212.         78  DDE-FACK                value   1.
  213.  
  214. DDE   * DDE Request identifiers
  215.         78  XTYP-INIT               VALUE H"0120".  *>  Initialize
  216.         78  XTYP-ADVDATA            VALUE H"0240".  *>  Advise Data
  217.         78  XTYP-EXEC               VALUE H"0340".  *>  Execute Command
  218.         78  XTYP-POKE               VALUE H"0440".  *>  Poke Command
  219.         78  XTYP-ADVSTART           VALUE H"0520".  *>  Start Advise
  220.         78  XTYP-TERM               VALUE H"0610".  *>  Terminate
  221.         78  XTYP-ADVSTOP            VALUE H"0710".  *>  Stop Advise
  222.         78  XTYP-REGISTER           VALUE H"0810".  *>  Register
  223.         78  XTYP-UNREGISTER         VALUE H"0910".  *>  UnRegister
  224.         78  XTYP-ADVREQ             VALUE H"0A80".  *>  Request Advise Data
  225.         78  XTYP-MONITOR            VALUE H"0B10".  *>  Monitor
  226.         78  XTYP-ACK                VALUE H"0C10".  *>  Acknowledge
  227.         78  XTYP-WILDINIT           VALUE H"0D80".  *>  Wild Initialize
  228.         78  XTYP-REQUEST            VALUE H"0E80".  *>  Request Data
  229.         78  XTYP-XFERCOMPLETE       VALUE H"0F10".  *>  Transfer Complete
  230.  
  231.     01  work-data.
  232.             03  hab                 pointer.
  233.             03  hmq                 pointer.
  234.         03    hwndClient        pic 9(9) comp-5.
  235.         03    hwndFrame        pic 9(9) comp-5.
  236.  
  237.             03  CSClass             pic 9(9) comp-5 value h"20000004".
  238.         03    WSWindow        pic 9(9) comp-5 value h"80000000".
  239.         03    ctldata         pic 9(9) comp-5 value h"00000c3b".
  240.  
  241.             03  MyClass             pic x(9) value 'MyClass' & x'00'.
  242.  
  243.         03    loop-flag        pic x value 'C'.
  244.         88  loop-end        value 'E'.
  245.         03    bool            pic 9(4) comp-5.
  246.         88  boolTRUE        value 1.
  247.         88  boolFALSE        value 0.
  248.  
  249.         03    qmsg.
  250.         05  qmsghwnd        pic 9(9) comp-5.
  251.         05  qmsgmsg        pic 9(4) comp-5.
  252.         05  qmsgmp1        pic 9(9) comp-5.
  253.         05  qmsgmp2        pic 9(9) comp-5.
  254.         05  qmsgtime        pic 9(9) comp-5.
  255.         05  qmsgptl.
  256.             07    qmsgptlx    pic 9(9) comp-5.
  257.             07    qmsgptly    pic 9(9) comp-5.
  258.  
  259.             03  WndProc     procedure-pointer.
  260.  
  261.             03  errorCode           pic 9(4) comp-5.
  262.  
  263.       * Constant names used to communicate with Excel
  264.       * TestData is the Topic supported by DDE
  265.       * Sheet1 is the Topic we use within Excel
  266.       * R1C1 is the item within the topic in Excel
  267.  
  268.         78  L-TESTDATA          value 'TestData'.
  269.         78  L-TARGETTOPIC       value 'Sheet1'.
  270.         78  L-TARGETCELL        value 'R1C1'.
  271.  
  272. DDE   * The DDE Manager provides a string handle feature.
  273. DDE   * You get a handle on a null-terminated string by calling the
  274. DDE   * DDEMgrGetHsz function.  You can then use the string handle (or hsz)
  275. DDE   * like a string.  Equal strings will have equal hszs.
  276. DDE   * Passing text data to DDEMgr functions is often done by passing
  277. DDE   * the hsz rather than a pointer to the string.
  278. DDE   * String handles have a use-count, and you should ensure that
  279. DDE   * any hsz you see actually belongs to you otherwise it may be
  280. DDE   * deallocated by someone else and reused - associated with a
  281. DDE   * different string.
  282. DDE   * If you receive a hsz from DDEMgr, and you want to keep it,
  283. DDE   * you should call DDEMgrIncHszCount to protect it.
  284.  
  285.       * As part of our initialization, we will initialize a number
  286.       * of string handles and store them here.
  287.  
  288.         01  DDEDataArea.
  289.             03  DDEName         pic x(20).
  290.             03  DDETopic        pic x(9)  value L-TESTDATA & x"00".
  291.             03  hszDDETopic     pointer.
  292.             03  DDEL-System     pic x(7)  value 'System' & x"00".
  293.             03  hszSystem       pointer.
  294.             03  DDEL-Topics     pic x(7)  value 'Topics' & x"00".
  295.             03  hszTopics       pointer.
  296.             03  DDEL-SysItems   pic x(9)  value 'SysItems' & x"00".
  297.             03  hszSysItems     pointer.
  298.             03  DDEL-Status     pic x(7)  value 'Status' & x"00".
  299.             03  hszStatus       pointer.
  300.             03  TargetApp       pic x(20).
  301.             03  hszTargetApp    pointer.
  302.             03  TargetTopic     pic x(20) value L-TARGETTOPIC & x"00".
  303.             03  hszTargetTopic  pointer.
  304.             03  Item1           pic x(20) value 'Selection' & x"00".
  305.  
  306.       * We send commands to Excel in the following format:
  307.       *     [command]       the command should be enclosed in square brackets
  308.       *     FORMULA("data","cell")
  309.       *                     any Excel function can be used as a command
  310.       *                     in this case, we are setting Sheet1!R1C1 to
  311.       *                     contain the value "Red"
  312.       *                     You really do need all the ()'s and "'s
  313.  
  314.  
  315.  
  316.             03  Data1           pic x(50) value
  317.                                             '[FORMULA'
  318.                                           & '("Red"'
  319.                                           & ','
  320.                                           & '"'
  321.                                           & L-TARGETTOPIC
  322.                                           & '!'
  323.                                           & L-TARGETCELL
  324.                                           & '")]' & x"00".
  325.             03  Item2           pic x(20) value L-TARGETCELL & x"00".
  326.             03  Data2           pic x(50) value x"00".
  327.             03  ItemXfer        pic x(20).
  328.             03  DataXfer        pic x(50).
  329.             03  XferProc        procedure-pointer.
  330.             03  xtyp            pic 9(4) comp-5.
  331.             78  DDEMsgSize      value 40.
  332.             03  DDEMsg          pic x(DDEMsgSize).
  333.             03  DDEData         pic x(256).
  334.             03  hszItemName     pointer.
  335.             03  pidXfer         pic 9(9) comp-5.
  336.             03  hConversation   pointer.
  337.             03  hDmgConvData    pointer.
  338.             03  RectColour      pic s9(9) comp-5 value CLR-RED.
  339.             03  AdviseControl   occurs 3.
  340.                 05  AdivseFlag  pic x   value 'N'.
  341.                     88  AdviseOK        value 'Y'.
  342.                     88  AdviseOff       value 'N'.
  343.                 05  AdviseHwnd      pointer.
  344.                 05  hszAdviseTopic  pointer.
  345.                 05  hszAdviseItem   pointer.
  346.  
  347.     local-storage section.
  348.         01  hps         pointer.
  349.     01  rcl.
  350.             03  xLeft   pic x(4) comp-5.
  351.             03  redefines xLeft.
  352.                 05  xLeftl pic xx comp-5.
  353.                 05  xLefth pic xx comp-5.
  354.         03    yBottom pic x(4) comp-5.
  355.             03  redefines yBottom.
  356.                 05  yBottoml pic xx comp-5.
  357.                 05  yBottomh pic xx comp-5.
  358.         03    xRight    pic x(4) comp-5.
  359.         03    yTop    pic x(4) comp-5.
  360.     01  mresult    pic x(4) comp-5.
  361.         01  DDELocalData.
  362.             03  DDEResult   pic x(4) comp-5.
  363.             03  DDEReply    pic x(40).
  364.             03  DDEReply9   pic 9(3).
  365.             03              pic x comp-5 value 0.
  366.             03  ConversationData.
  367.         78  lszTopicString          value 40.
  368.         78  lszItemString           value 40.
  369.                 05  hszTopicString      pic x(lszTopicString).
  370.                 05  hszItemString       pic x(lszItemString).
  371.  
  372.         01  ppl.
  373.             03  x               pic x(4) comp-5.
  374.             03  redefines x.
  375.                 05  xl pic xx comp-5.
  376.                 05  xh pic xx comp-5.
  377.             03  y               pic x(4) comp-5.
  378.             03  redefines y.
  379.                 05  yl pic xx comp-5.
  380.                 05  yh pic xx comp-5.
  381.         01  i                   pic 9(9) comp-5.
  382.         01  si                  pic 9(4) comp-5.
  383.  
  384.     linkage section.
  385.         01  hwnd        pic x(4) comp-5.
  386.         01  msg         pic x(2) comp-5.
  387.         01  mp1         pic x(4) comp-5.
  388.     01  redefines mp1.
  389.             03  mp1w1   pic x(2) comp-5.
  390.             03  mp1w2   pic x(2) comp-5.
  391.         01  mp2         pic x(4) comp-5.
  392.     01  redefines mp2.
  393.             03  mp2w1   pic x(2) comp-5.
  394.             03  mp2w2   pic x(2) comp-5.
  395.  
  396.         01  hConv           pointer.
  397.         01  hszTopic        pointer.
  398.         01  hszItem         pointer.
  399.         01  usFmt           pic 9(4) comp-5.
  400.         01  usType          pic 9(4) comp-5.
  401.         01  hDmgData        pointer.
  402.  
  403.     procedure division OS2API.
  404.         main section.
  405.  
  406.       * Default names for this program and the 'other' program are
  407.       *         DDEName (this program)          COBOLDDE
  408.       *         TargetApp (that program)        Excel
  409.       *
  410.       * You can override these names by starting DDE and DDE2 with a
  411.       * command lines:
  412.       *
  413.       *     DDE MyName YourName
  414.       *     DDE2 YourName MyName
  415.  
  416.             accept DDEData from command-line
  417.             unstring DDEData delimited by spaces
  418.                     into DDEName TargetApp
  419.  
  420.             if DDEName = spaces
  421.                 move 'COBOLDDE' to DDEName
  422.             end-if
  423.             if TargetApp = spaces
  424.                 move 'Excel' to TargetApp
  425.             end-if
  426.             perform varying i from length of DDEName by -1
  427.                         until DDEName(i:1) not = spaces
  428.                 move x"00" to DDEName(i:1)
  429.             end-perform
  430.             perform varying i from length of TargetApp by -1
  431.                         until TargetApp(i:1) not = spaces
  432.                 move x"00" to TargetApp(i:1)
  433.             end-perform
  434.  
  435.         call OS2API '__WinInitialize'
  436.             using    by value 0 size 2
  437.             returning hab
  438.         call OS2API '__WinCreateMsgQueue'
  439.             using by value hab
  440.                   by value 0 size 2
  441.             returning hmq
  442.  
  443.         set WndProc to ENTRY 'WndProc'
  444.         call OS2API '__WinRegisterClass'
  445.             using by value       hab
  446.                   by reference MyClass
  447.                   by value       WndProc
  448.                   by value       CSClass
  449.                   by value       0        size 2
  450.             returning bool
  451.         if boolTRUE
  452.  
  453.         call OS2API '__WinCreateStdWindow'
  454.                             using by value     HWND-DESKTOP size 4
  455.                   by value     WSWindow
  456.                   by reference ctldata
  457.                   by reference MyClass
  458.                                   by reference 'MyTitle' & x'00'
  459.                   by value     0    size 4
  460.                   by value     0    size 2
  461.                   by value     0    size 2
  462.                   by reference hwndClient
  463.                 returning hwndFrame
  464.  
  465.         if hwndFrame not = 0
  466.  
  467.       ****************************************************************
  468.       *                                  *
  469.       * This in-line PERFORM implements the message loop.         *
  470.       *                                  *
  471.       ****************************************************************
  472.             perform until loop-end
  473.             call OS2API '__WinGetMsg'
  474.                     using by value hab
  475.                       by reference qmsg
  476.                       by value 0        size 4
  477.                       by value 0        size 2
  478.                       by value 0        size 2
  479.                     returning bool
  480.  
  481.             if boolFALSE
  482.                 set loop-end to true
  483.             else
  484.                 call OS2API '__WinDispatchMsg'
  485.                     using by value hab
  486.                           by reference qmsg
  487.  
  488.             end-perform
  489.  
  490.             call OS2API '__WinDestroyWindow'
  491.                 using by value hwndFrame
  492.  
  493.         end-if
  494.  
  495.         end-if
  496.  
  497.         call OS2API '__WinDestroyMsgQueue' using by value hmq
  498.         call OS2API '__WinTerminate'       using by value hab
  499.  
  500.         stop run.
  501.  
  502.  
  503.     MyWndProc section.
  504.     entry 'WndProc' using by value hwnd
  505.                   by value msg
  506.                   by value mp1
  507.                   by value mp2.
  508.  
  509.         move 0 to mresult
  510.             evaluate msg
  511.  
  512.                 when    WM-CREATE
  513.  
  514. DDE   * DDE programs have to have a PM message loop.
  515. DDE   * You should not call DDEMgrRegister unless the calling thread
  516. DDE   * has already called WinCreateMsgQueue.
  517.  
  518. DDE   * Because DDE can call an application at any time (unless callback
  519. DDE   * is disabled, but see DDEMgr documentation for that), a callback
  520. DDE   * routine has to be defined.  This program uses the entry point:
  521. DDE   *     DDEXFER
  522. DDE   *         as the callback routine.
  523. DDE   * See comments there for how that works.
  524.  
  525. DDE   * Parameters to DDEMgrRegister are:
  526. DDE   *             null-terminated string for this applications name
  527. DDE   *             procedure pointer for the callback routine
  528. DDE   *             timeout value (in milli-seconds)
  529. DDE   *             flags (see DDEMGR documentation for details
  530. DDE   *             reserved for expansion
  531.  
  532.                     set XferProc to entry 'DDEXFER'
  533.  
  534.                     call OS2API '__DDEMgrRegister' using
  535.                                 by reference DdeName
  536.                                 by value     XferProc
  537.                                 by value     1000        size 4
  538.                                 by value     0           size 4
  539.                                 by value     0           size 4
  540.                             returning errorCode
  541.  
  542.                     if errorCode = 0
  543.                         move 'DDE Register successful' to DDEMsg
  544.                     else
  545.                         move 'DDE Register fail' to DDEMsg
  546.                     end-if
  547.  
  548.                     call OS2API '__WinPostMsg' using
  549.                                 by value hwnd
  550.                                 by value WMUSER-INITDDE
  551.                                 by value 0 size 4
  552.                                 by value 0 size 4
  553.  
  554.  
  555.                     set hConversation to NULL
  556.  
  557.                     move 0 to mp1
  558.                     move 0 to mp2w1
  559.                     move 100 to mp2w2
  560.                     perform varying si from 1 by 1 until si > 3
  561.                         call OS2API '__WinCreateWindow' using
  562.                                     by value hwnd
  563.                                     by value WC-SCROLLBAR size 4
  564.                                     by value 0 size 4
  565.                                     by value 0 size 4
  566.                                     by value 0 size 2
  567.                                     by value 0 size 2
  568.                                     by value 0 size 2
  569.                                     by value 0 size 2
  570.                                     by value hwnd
  571.                                     by value HWND-TOP size 4
  572.                                     by value si
  573.                                     by value 0 size 4
  574.                                     by value 0 size 4
  575.                                     returning AdviseHwnd(si)
  576.                         call OS2API '__WinSendMsg' using
  577.                                     by value AdviseHwnd(si)
  578.                                     by value SBM-SETSCROLLBAR size 2
  579.                                     by value mp1
  580.                                     by value mp2
  581.                     end-perform
  582.  
  583.                 when WMUSER-INITDDE
  584.  
  585.                     perform GetHszs
  586.  
  587.       * Initializing the conversation (we are client since we initiate the
  588.       * conversation
  589.  
  590.                     perform BeginConversation
  591.  
  592.                 when WMUSER-FREEHSZ
  593.  
  594.                     perform FreeHszs
  595.  
  596.                     move 'DDE Target not available' to DDEMsg
  597.                     perform Refresh
  598.  
  599.                 when    WM-DESTROY
  600.  
  601. DDE   * We do our best to terminate correctly, but we don't really look
  602. DDE   * at the error message hard enough...
  603.  
  604.                     move Data2 to DataXfer
  605.                     move Item2 to ItemXfer
  606.                     move XTYP-ADVSTOP to xtyp
  607.                     perform DDEXfer
  608.  
  609.                     perform TermConv
  610.  
  611.                     perform FreeHszs
  612.  
  613.                     call OS2API '__DDEMgrUnregister'
  614.                             returning errorCode
  615.  
  616.                 when    WM-SIZE
  617.  
  618.       * We calculate the Scroll Bar size and position based on the
  619.       * size of the Client Area
  620.  
  621.                     move mp2w1 to xl
  622.                     move mp2w2 to yl
  623.                     divide 3 into xl
  624.                     divide 15 into yl
  625.  
  626.                     perform varying si from 1 by 1 until si > 3
  627.                         compute yBottoml = yl * ( 4 * si - 1 )
  628.                         compute xLeftl = mp2w1 / 8
  629.                         call OS2API '__WinSetWindowPos' using
  630.                                     by value AdviseHwnd(si)
  631.                                     by value HWND-TOP size 4
  632.                                     by value xLeftl
  633.                                     by value yBottoml
  634.                                     by value xl
  635.                                     by value yl
  636.                                     by value SIZEMOVESHOW size 2
  637.  
  638.                     end-perform
  639.  
  640.                 when    WM-HSCROLL
  641.  
  642.       * When a Scroll Bar is touched, we process it.
  643.       * All scroll bars are set up with a range of 0-99
  644.  
  645.                     move mp1w1 to si
  646.                     perform GetSliderPos
  647.                     evaluate mp2w2
  648.                         when SB-LINELEFT
  649.                             if i > 0
  650.                                 subtract 1 from i
  651.                             else
  652.                                 move 0 to si
  653.                             end-if
  654.                         when SB-LINERIGHT
  655.                             if i < 100
  656.                                 add 1 to i
  657.                             else
  658.                                 move 0 to si
  659.                             end-if
  660.                         when SB-PAGELEFT
  661.                             if i > 10
  662.                                 subtract 10 from i
  663.                             else
  664.                                 move 0 to si
  665.                             end-if
  666.                         when SB-PAGERIGHT
  667.                             if i < 90
  668.                                 add 10 to i
  669.                             else
  670.                                 move 0 to si
  671.                             end-if
  672.                         when SB-SLIDERPOSITION
  673.                         when SB-SLIDERTRACK
  674.                             move mp2w1 to i
  675.                         when other
  676.                     end-evaluate
  677.                     if si > 0
  678.                         call OS2API '__WinSendMsg' using
  679.                                     by value AdviseHwnd(si)
  680.                                     by value SBM-SETPOS size 2
  681.                                     by value i
  682.                                     by value 0 size 4
  683.  
  684. DDE   * If we are acting as a DDE Server, we have to notify our Clients
  685. DDE   * each time a piece of important data changes.
  686.  
  687.                         if AdviseOK(si)
  688.                             perform AdviseData
  689.                         end-if
  690.                     end-if
  691.  
  692.         when    WM-PAINT
  693.             call OS2API '__WinBeginPaint'
  694.                 using by value hwnd
  695.                       by value 0 size 4
  696.                       by reference rcl
  697.                                 returning hps
  698.  
  699.                     call OS2API '__WinQueryWindowRect'
  700.                                 using by value hwnd
  701.                                       by reference rcl
  702.  
  703.                     call OS2API '__WinFillRect'
  704.                                 using by value hps
  705.                                       by reference rcl
  706.                                       by value SYSCLR-WINDOW
  707.  
  708.                     divide xRight by 2 giving xLeft
  709.                     divide yTop by 2 giving yBottom
  710.                     call OS2API '__WinFillRect'
  711.                                 using by value hps
  712.                                       by reference rcl
  713.                                       by value RectColour
  714.  
  715.                     call OS2API '__WinQueryWindowRect'
  716.                                 using by value hwnd
  717.                                       by reference rcl
  718.  
  719.                     move 18 to yTop
  720.  
  721.                     call OS2API '__WinDrawText'
  722.                                 using by value hps
  723.                                       by value DDEMsgSize size 2
  724.                                       by reference DDEMsg
  725.                                       by reference rcl
  726.                                       by value SYSCLR-WINDOWTEXT size 4
  727.                                       by value SYSCLR-WINDOW     size 4
  728.                                       by value h'8500' size 2
  729.  
  730.             call OS2API '__WinEndPaint'
  731.                                 using by value hps
  732.  
  733.         when other
  734.             call OS2API '__WinDefWindowProc'
  735.                 using by value hwnd
  736.                       by value msg
  737.                       by value mp1
  738.                       by value mp2
  739.                 returning mresult
  740.  
  741.         end-evaluate
  742.  
  743.             exit program returning mresult.
  744.  
  745.         GetSliderPos section.
  746.             call OS2API '__WinSendMsg' using
  747.                         by value AdviseHwnd(si)
  748.                         by value SBM-QUERYPOS size 2
  749.                         by value 0 size 4
  750.                         by value 0 size 4
  751.                         returning i.
  752.  
  753.         AdviseGetData section.
  754.             perform GetSliderPos
  755.             move i to DDEReply9.
  756.  
  757. DDE   * When some data has changed, we tell DDEMgr of this fact, and
  758. DDE   * he will administer getting this information (via a callback function
  759. DDE   * XTYP-ADVREQ) and passing it on to interested clients.
  760.  
  761.         AdviseData section.
  762.             call OS2API '__DDEMgrPostAdvise' using
  763.                         by value hszAdviseTopic(si)
  764.                         by value hszAdviseItem(si).
  765.  
  766.         GetHszs Section.
  767. DDE   * Get hszs for Strings:
  768.             call OS2API '__DDEMgrGetHsz'
  769.                         using by reference TargetApp
  770.                         returning hszTargetApp
  771.             call OS2API '__DDEMgrGetHsz'
  772.                         using by reference TargetTopic
  773.                         returning hszTargetTopic
  774.             call OS2API '__DDEMgrGetHsz'
  775.                         using by reference DDEL-System
  776.                         returning hszSystem
  777.             call OS2API '__DDEMgrGetHsz'
  778.                         using by reference DDEL-Topics
  779.                         returning hszTopics
  780.             call OS2API '__DDEMgrGetHsz'
  781.                         using by reference DDEL-SysItems
  782.                         returning hszSysItems
  783.             call OS2API '__DDEMgrGetHsz'
  784.                         using by reference DDEL-Status
  785.                         returning hszStatus
  786.             call OS2API '__DDEMgrGetHsz'
  787.                         using by reference DDETopic
  788.                         returning hszDDETopic.
  789.  
  790.         FreeHszs Section.
  791.             call OS2API '__DDEMgrFreeHsz' using
  792.                         by value hszDDETopic
  793.             call OS2API '__DDEMgrFreeHsz' using
  794.                         by value hszStatus
  795.             call OS2API '__DDEMgrFreeHsz' using
  796.                         by value hszSysItems
  797.             call OS2API '__DDEMgrFreeHsz' using
  798.                         by value hszTopics
  799.             call OS2API '__DDEMgrFreeHsz' using
  800.                         by value hszSystem
  801.             call OS2API '__DDEMgrFreeHsz' using
  802.                         by value hszTargetTopic
  803.             call OS2API '__DDEMgrFreeHsz' using
  804.                         by value hszTargetApp.
  805.  
  806. DDE   * Initializing a conversation involves simply connecting with a
  807. DDE   * topic on a target machine.  The returned Conversation handle is
  808. DDE   * used for all communications.
  809.  
  810.         InitConv section.
  811.             if hConversation = NULL
  812.                 call OS2API '__DDEMgrConnect' using
  813.                              by value hszTargetApp
  814.                                       hszTargetTopic
  815.                                       0 size 4
  816.                             returning hConversation
  817.  
  818.                 if hConversation = NULL
  819.  
  820. DDE   * DDEMgrGetLastError returns the last noted error,
  821. DDE   * DDEMgrPostError will put up a message box indicating the error
  822.  
  823.                     call OS2API '__DDEMgrGetLastError'
  824.                                  returning errorCode
  825.                     call OS2API '__DDEMgrPostError'
  826.                                  using by value errorCode
  827.  
  828.                     move 'DDE Conversation Not Established' to DDEMsg
  829.                 else
  830.                     move 'DDE Conversation Established' to DDEMsg
  831.                 end-if
  832.                 perform Refresh
  833.             end-if.
  834.  
  835.         BeginConversation Section.
  836.             perform InitConv
  837.  
  838. DDE   * With a conversation established, we can start talking...
  839.       * The first thing we do is to EXECute a command in Excel.  This
  840.       * actually puts the value "Red" in cell A1 of Sheet1.
  841.       * EXEC is a once only, one way function.
  842.  
  843.             move Data1 to DataXfer
  844.             move Item1 to ItemXfer
  845.             move XTYP-EXEC to xtyp
  846.             perform DDEXfer
  847.  
  848.       * We then set up an Advise Loop on Sheet1!R1C1 so that we are notified
  849.       * each time it changes.
  850. DDE   * The actual notification is received in the call back function.
  851.  
  852.             move Data2 to DataXfer
  853.             move Item2 to ItemXfer
  854.             move XTYP-ADVSTART to xtyp
  855.             perform DDEXfer.
  856.  
  857. DDE   * To converse with a Conversation handle, we:
  858. DDE   *     Convert the conversation Item to a hsz
  859. DDE   *     Call DDEMgrClientXfer with parameters:
  860. DDE   *         Data to be sent to the Server
  861. DDE   *         Length of the data being sent
  862. DDE   *         Conversation handle
  863. DDE   *         hsz for the item
  864. DDE   *         Format indicator (here we always use TEXT)
  865. DDE   *         Communications type (see XTYP above and below)
  866. DDE   *         timeout value (in milli-seconds)
  867. DDE   *         a value used for assynchronous communications
  868. DDE   *                 (see DDEMgr documentation for details)
  869. DDE   *     It returns a handle to some data.
  870.  
  871.         DDEXfer section.
  872.             if hConversation not = NULL
  873.                 move 1 to i
  874.                 inspect DataXfer tallying i for characters
  875.                         before initial x"00"
  876.  
  877.                 call OS2API '__DDEMgrGetHsz'
  878.                             using by reference ItemXfer
  879.                             returning hszItemName
  880.                 call OS2API '__DDEMgrClientXfer' using
  881.                             by reference DataXfer
  882.                             by value i
  883.                             by value hConversation
  884.                             by value hszItemName
  885.                             by value DDEFMT-TEXT size 2
  886.                             by value xtyp
  887.                             by value 5000 size 4
  888.                             by reference pidXfer
  889.                         returning hDmgConvData
  890.  
  891.                 call OS2API '__DDEMgrGetLastError'
  892.                         returning errorCode
  893.                 call OS2API '__DDEMgrPostError'
  894.                              using by value errorCode
  895.  
  896.                 move spaces to DDEData
  897.  
  898. DDE   * If we REQUESTed some data from the Server, the hDmgConvData parameter
  899. DDE   * contains that data.  Use DDEMgrGetData to retrieve the data, and
  900. DDE   * DDEMgrFreeData to release the memory used.
  901. DDE   * (Allocating and free resources used by DDEMgr should be done
  902. DDE   * carefully.  This application should free everything it uses and you
  903. DDE   * should be safe to copy it, but more sophisticated applications
  904. DDE   * should refer to the DDEMgr documentation.
  905.  
  906.                 if xtyp = XTYP-REQUEST
  907.  
  908.                     call OS2API '__DDEMgrGetData' using
  909.                                 by value hDmgConvData
  910.                                 by reference DDEData
  911.                                 by value 255 size 4
  912.                                 by value 0 size 4
  913.  
  914.                     call OS2API '__DDEMgrGetLastError'
  915.                             returning errorCode
  916.                     call OS2API '__DDEMgrPostError'
  917.                                  using by value errorCode
  918.                     call OS2API '__DDEMgrFreeData' using
  919.                                 by value hDmgConvData
  920.  
  921.                 end-if
  922.  
  923.                 call OS2API '__DDEMgrFreeHsz'
  924.                             using by value hszItemName
  925.             end-if.
  926.  
  927. DDE   * Terminating a conversation is merely a case of Disconnecting.
  928.  
  929.         TermConv section.
  930.             if hConversation not = NULL
  931.                 call OS2API '__DDEMgrDisconnect'
  932.                             using by value hConversation
  933.                             returning errorCode
  934.  
  935.                 set hConversation to NULL
  936.  
  937.                 call OS2API '__DDEMgrGetLastError'
  938.                         returning errorCode
  939.             end-if.
  940.  
  941.         AdviseSelect section.
  942.             move 0 to si
  943.             evaluate hszItemString
  944.                 when 'Number1'
  945.                     move 1 to si
  946.                 when 'Number2'
  947.                     move 2 to si
  948.                 when 'Number3'
  949.                     move 3 to si
  950.                 when other
  951.             end-evaluate.
  952.  
  953.         AdviseRequest section.
  954.             perform varying si from 3 by -1
  955.                     until si = 0
  956.                         or (  hszItem = hszAdviseItem(si) and
  957.                              hszTopic = hszAdviseTopic(si)
  958.                            )
  959.             end-perform
  960.             if si not = 0
  961.                 perform AdviseGetData
  962.                 move length of DDEReply9 to i
  963.                 add 1 to i
  964.                 move DDEReply9 to DDEReply
  965.             end-if.
  966.  
  967.         Refresh Section.
  968.             call OS2API '__WinInvalidateRect'
  969.                         using by value hwndClient
  970.                               by value 0 size 4
  971.                               by value 0 size 2.
  972.  
  973. DDE   * Callback function from DDEManager.
  974.  
  975. DDE   * When the DDE Manager needs some information from the application
  976. DDE   * (Client or Server) it calls the registered callback function.
  977.  
  978.         DDEXferProc Section.
  979.         ENTRY 'DDEXFER' using by value      hConv
  980.                               by value      hszTopic
  981.                               by value      hszItem
  982.                               by value      usFmt
  983.                               by value      usType
  984.                               by value      hDmgData.
  985.  
  986.             move 0 to DDEResult
  987.             move all x'00' to ConversationData
  988.  
  989.             call OS2API '__DDEMgrGetHszString' using
  990.                          by value hszTopic
  991.                          by reference hszTopicString
  992.                          by value lszTopicString
  993.  
  994.             call OS2API '__DDEMgrGetHszString' using
  995.                          by value hszItem
  996.                          by reference hszItemString
  997.                          by value lszItemString
  998.  
  999.             inspect ConversationData replacing all x"00" by space
  1000.  
  1001.             move spaces to DDEReply
  1002.             move 1 to i
  1003.  
  1004. DDE   * Any of the XTYP functions could be seen here, but we only need
  1005. DDE   * to process some of them.
  1006.  
  1007.             evaluate usType
  1008.  
  1009. DDE   * XTYP-INIT
  1010. DDE   *     When another application wants to start a conversation with
  1011. DDE   *     this application, DDEMgr uses the XTYP-INIT function to
  1012. DDE   *     check whether the desired topic is supported by this
  1013. DDE   *     application.
  1014. DDE   *     The applciation should return True (1) if it does support
  1015. DDE   *     the topic, and False (0) otherwise.
  1016.  
  1017. DDE   *     DDE applications should support the System topic in addition
  1018. DDE   *     to working topics.
  1019.  
  1020.               when XTYP-INIT
  1021.                 if hszTopic = hszSystem or hszDDETopic
  1022.                     exit program returning 1
  1023.  
  1024. DDE   * XTYP-WILDINIT
  1025. DDE   *     Wild init should return a list of support topics as a string
  1026. DDE   *     of hszs.  If a large number of topics are to be supported,
  1027. DDE   *     There are advantages in coding a table.
  1028.  
  1029. DDE   * Throughout this section we are using i to tally the length
  1030. DDE   * of the data collected for return to DDEMgr.
  1031.  
  1032.               when XTYP-WILDINIT
  1033.                 call OS2API '__DDEMgrGetHsz' using
  1034.                             by reference 'System' & x"00"
  1035.                             returning DDEReply(i:2)
  1036.                 add 2 to i
  1037.                 call OS2API '__DDEMgrGetHsz' using
  1038.                             by reference DDETopic
  1039.                             returning DDEReply(i:2)
  1040.                 add 2 to i
  1041.  
  1042. DDE   * XTYP-REGISTER is received when another application becomes
  1043. DDE   * available for DDE transactions.
  1044. DDE   * We use this as notification to start a conversation.
  1045.  
  1046.               when XTYP-REGISTER
  1047.                 if hszItem = hszTargetApp
  1048.                     call OS2API '__WinSendMsg' using
  1049.                                 by value hwndClient
  1050.                                 by value WMUSER-INITDDE size 2
  1051.                                 by value 0 size 4
  1052.                                 by value 0 size 4
  1053.                 end-if
  1054.  
  1055. DDE   * XTYP-UNREGISTER is received when an application becomes
  1056. DDE   * unavailable for DDE transactions
  1057. DDE   * We use this as notification to terminate a conversation.
  1058.  
  1059.               when XTYP-UNREGISTER
  1060.                 if hszItem = hszTargetApp
  1061.                     set hConversation to null
  1062.                     call OS2API '__WinSendMsg' using
  1063.                                 by value hwndClient
  1064.                                 by value WMUSER-FREEHSZ size 2
  1065.                                 by value 0 size 4
  1066.                                 by value 0 size 4
  1067.                 end-if
  1068.  
  1069. DDE   * XTYP-REQUEST and XTYP-ADVREQ
  1070. DDE   * are the same in function, but different in origin.
  1071. DDE   * XTYP-REQUEST is the result of a XTYP-REQUEST conversation started
  1072. DDE   * by some client
  1073. DDE   * XTYP-ADVREQ is the result of a call to DDEMgrPostAdvise.
  1074. DDE   * In both cases, what is required is the value of some pieve of
  1075. DDE   * data.
  1076.  
  1077.               when XTYP-REQUEST
  1078.               when XTYP-ADVREQ
  1079.                 evaluate hszTopic
  1080.                   when hszSystem
  1081. DDE   * The System Topic should support the following Items:
  1082. DDE   *     Topics - return a list of all supported topics
  1083. DDE   *     SysItems - return a list of all supported Items for the System
  1084. DDE   *                         Topic
  1085. DDE   *     Status - return a Status indicator.
  1086. DDE   *     Multiple values are returned with TAB separators.
  1087.  
  1088.                     evaluate hszItem
  1089.                       when hszTopics
  1090.                         string 'System' & x"09"
  1091.                                L-TESTDATA
  1092.                             delimited by size
  1093.                             into DDEReply pointer i
  1094.                       when hszSysItems
  1095.                         string 'Topics'   & x"09"
  1096.                                'SysItems' & x"09"
  1097.                                'Status'
  1098.                             delimited by size
  1099.                             into DDEReply pointer i
  1100.                       when hszStatus
  1101.                         string 'OK' delimited by size
  1102.                           into DDEReply pointer i
  1103.                       when other
  1104.                     end-evaluate
  1105.                   when other
  1106. DDE   * If we allowed multiple topics here, we would have to do more
  1107. DDE   * work, but we take the easy option.
  1108.  
  1109.                     perform AdviseRequest
  1110.                 end-evaluate
  1111.  
  1112. DDE   * When a piece of data changes after a Client has requested notifaction
  1113. DDE   * of this fact, a XTYP-ADVDATA message is received by the Client.
  1114.  
  1115. DDE   * We check that it is an expected piece of data, and then extrat
  1116. DDE   * it from the hDmgData (which we free up)
  1117. DDE   * Excel tacks on a CR LF NULL sequence to the end of the data, so
  1118. DDE   * we strip these off, and then process the data.
  1119.  
  1120.               when XTYP-ADVDATA
  1121.  
  1122.       * Topic and Item are reversed here...
  1123.                 if hszTopicString = L-TARGETTOPIC and
  1124.                    hszItemString  = L-TARGETCELL
  1125.                     move all x'00' to DDEReply
  1126.                     call OS2API '__DDEMgrGetData' using
  1127.                                 by value hDmgData
  1128.                                 by reference DDEReply
  1129.                                 by value 40 size 4
  1130.                                 by value 0 size 4
  1131.                     call OS2API '__DDEMgrFreeData' using
  1132.                                 by value hDmgData
  1133.                     inspect DDEReply replacing all x"00" by spaces
  1134.                     inspect DDEReply replacing first x"0d" by space
  1135.                     inspect DDEReply replacing first x"0a" by space
  1136.                     evaluate DDEReply
  1137.                       when 'White'
  1138.                         move CLR-WHITE to RectColour
  1139.                       when 'Black'
  1140.                         move CLR-BLACK to RectColour
  1141.                       when 'Blue'
  1142.                         move CLR-BLUE to RectColour
  1143.                       when 'Red'
  1144.                         move CLR-RED to RectColour
  1145.                       when 'Magenta'
  1146.                         move CLR-MAGENTA to RectColour
  1147.                       when 'Green'
  1148.                         move CLR-GREEN to RectColour
  1149.                       when 'Cyan'
  1150.                         move CLR-CYAN to RectColour
  1151.                       when 'Yellow'
  1152.                         move CLR-YELLOW to RectColour
  1153.                     end-evaluate
  1154.                     perform Refresh
  1155.                     move spaces to DDEReply
  1156.  
  1157. DDE   * We also return an Acknowledge signal to the DDEMgr
  1158.  
  1159.                     move DDE-FACK to DDEResult
  1160.                 end-if
  1161.  
  1162.  
  1163. DDE   * When a Client requests a server to advise when some data changes,
  1164. DDE   * the Server receives a XTYP-ADVSTART function.
  1165. DDE   * The server should note the request (here we save the hszs for
  1166. DDE   * use when we need to PostAdvise) and return
  1167.  
  1168.               when XTYP-ADVSTART
  1169.                 if usFmt = DDEFMT-TEXT
  1170.                     perform AdviseSelect
  1171.                     if si >= 1 and si <= 3
  1172.                         set AdviseOK(si) to TRUE
  1173.                         call OS2API '__DDEMgrIncHszCount' using
  1174.                                     by value hszTopic
  1175.                         set hszAdviseTopic(si) to hszTopic
  1176.                         call OS2API '__DDEMgrIncHszCount' using
  1177.                                     by value hszItem
  1178.                         set hszAdviseItem(si) to hszItem
  1179.                         move 1 to DDEResult
  1180.                     end-if
  1181.                 end-if
  1182.  
  1183. DDE   * Similarly, when a Client no longer needs a piece of data, it sends
  1184. DDE   * XTYP-ADVSTOP message.
  1185.  
  1186.               when XTYP-ADVSTOP
  1187.                 perform AdviseSelect
  1188.                 if si >= 1 and si <= 3
  1189.                     set AdviseOff(si) to TRUE
  1190.                     call OS2API '__DDEMgrFreeHsz' using
  1191.                                 by value hszAdviseTopic(si)
  1192.                     call OS2API '__DDEMgrFreeHsz' using
  1193.                                 by value hszAdviseItem(si)
  1194.                     move 1 to DDEResult
  1195.                 end-if
  1196.  
  1197.               when other
  1198.             end-evaluate
  1199.  
  1200. DDE   * If there is data to be returned to DDEMgr, we do it by
  1201. DDE   * wrapping it in a data structure with DDEMgrPutData.
  1202. DDE   * Parameters to DDEMgrPutData are:
  1203. DDE   *     Data to pack
  1204. DDE   *     length of data
  1205. DDE   *     offset within return data structure to place this data
  1206. DDE   *     hsz for the Item this data refers to
  1207. DDE   *     format of this data
  1208. DDE   *     flag - see DDEMGR documentation for details.
  1209. DDE   * It returns a handle which should be returned in the EXIT PROGRAM
  1210. DDE   * statement.
  1211.  
  1212.             if DDEReply not = spaces
  1213.  
  1214.                 move x"00" to DDEReply(i:1)
  1215.  
  1216.                 call OS2API '__DDEMgrPutData' using
  1217.                             by reference    DDEReply
  1218.                             by value        i
  1219.                             by value        0 size 4
  1220.                             by value        hszItem
  1221.                             by value        DDEFMT-TEXT size 2
  1222.                             by value        0 size 2
  1223.                             returning       DDEResult
  1224.  
  1225.                 call OS2API '__DDEMgrGetLastError'
  1226.                         returning errorCode
  1227.  
  1228.             end-if
  1229.  
  1230.             exit program returning DDEResult.
  1231.