home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xf083czs.zip / NETSC421 / netscdde.c < prev    next >
C/C++ Source or Header  |  1998-11-22  |  25KB  |  688 lines

  1. /*
  2.  * netscdde.c:
  3.  *      this is the main (and only) C file for the
  4.  *      Netscape DDE interface. This code is much more
  5.  *      messy than XFolder's. It's a rather quick hack
  6.  *      done in about two days with DDE code stolen from
  7.  *      various places.
  8.  *
  9.  *      Use the undocumented "-D" parameter on the command
  10.  *      line to start NetscDDE in "debug" mode, which will
  11.  *      display a frame window with a menu where you may
  12.  *      debug the DDE messages. This window is invisible
  13.  *      when "-D" is not used. (Ugly, huh.)
  14.  *
  15.  *      Netscape's DDE topics are (horribly) documented
  16.  *      for all Netscape versions at
  17.  *      http://developer.netscape.com/library/documentation/communicator/DDE
  18.  *
  19.  *      Copyright (C) 1997-98 Ulrich Möller.
  20.  *      This program is free software; you can redistribute it and/or modify
  21.  *      it under the terms of the GNU General Public License as published by
  22.  *      the Free Software Foundation, in version 2 as it comes in the COPYING
  23.  *      file of the XFolder main distribution.
  24.  *      This program is distributed in the hope that it will be useful,
  25.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *      GNU General Public License for more details.
  28.  */
  29.  
  30. #define  INCL_WIN
  31. #define  INCL_DOS
  32.  
  33. #include <os2.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include "netscdde.h"
  37. #pragma  linkage (main,optlink)
  38.  
  39. void     ShowMessage(PSZ);
  40. MRESULT EXPENTRY LocalWndProc(HWND, ULONG, MPARAM, MPARAM);
  41.  
  42. HAB         hab;
  43. HWND        hwndDebug, hwndListbox,
  44.             hServerWnd = NULLHANDLE;
  45. PFNWP       SysWndProc;
  46.  
  47. CHAR        szURL[400] = "";
  48.  
  49. ULONG       idTimer = 0;
  50.  
  51. CONVCONTEXT context;
  52.  
  53. CHAR        szDDENetscape[] = "NETSCAPE",               // DDE server name
  54.             szNetscapeApp[CCHMAXPATH] = "NETSCAPE.EXE", // default program to start
  55.                                                         // if not running
  56.             szNetscapeParams[CCHMAXPATH] = "";          // space for params
  57.  
  58. PSZ         szOpenURLTopic = "WWW_OpenURL";             // open URL DDE topic
  59.                                                         // (see Netscape docs)
  60.  
  61. // options flags, modified by command line interface
  62. BOOL        optNewWindow = FALSE,
  63.             optDebug     = FALSE,
  64.             optExecute   = TRUE,
  65.             optConfirmStart   = TRUE,
  66.             optMinimized = FALSE,
  67.             optHidden = FALSE;
  68.  
  69. BOOL        NetscapeFound = FALSE;
  70.  
  71. // status window handle
  72. HWND        hwndContacting = NULLHANDLE;
  73.  
  74. /*
  75.  * CenterWindow:
  76.  *      centers a window within its parent window.
  77.  *      The window should not be visible to avoid flickering.
  78.  */
  79.  
  80. void CenterWindow(HWND hwnd)
  81. {
  82.    RECTL rclParent;
  83.    RECTL rclWindow;
  84.  
  85.    WinQueryWindowRect(hwnd, &rclWindow);
  86.    WinQueryWindowRect(WinQueryWindow(hwnd, QW_PARENT), &rclParent);
  87.  
  88.    rclWindow.xLeft   = (rclParent.xRight - rclWindow.xRight) / 2;
  89.    rclWindow.yBottom = (rclParent.yTop   - rclWindow.yTop  ) / 2;
  90.  
  91.    WinSetWindowPos(hwnd, NULLHANDLE, rclWindow.xLeft, rclWindow.yBottom,
  92.                     0, 0, SWP_MOVE | SWP_SHOW);
  93. }
  94.  
  95. /*
  96.  * WinCenteredDlgBox:
  97.  *      just like WinDlgBox, but the window is centered
  98.  */
  99.  
  100. ULONG WinCenteredDlgBox(HWND hwndParent, HWND hwndOwner,
  101.               PFNWP pfnDlgProc, HMODULE hmod, ULONG idDlg, PVOID pCreateParams)
  102. {
  103.     ULONG   ulReply;
  104.     HWND    hwndDlg = WinLoadDlg(hwndParent, hwndOwner, pfnDlgProc,
  105.                                 hmod, idDlg, pCreateParams);
  106.     CenterWindow(hwndDlg);
  107.     ulReply = WinProcessDlg(hwndDlg);
  108.     WinDestroyWindow(hwndDlg);
  109.     return (ulReply);
  110. }
  111.  
  112. /*
  113.  *  GenericDlgProc:
  114.  *          this is the dlg procedure for dlg boxes;
  115.  *          it really does nothing
  116.  */
  117.  
  118. MRESULT EXPENTRY GenericDlgProc(HWND hwnd,
  119.                                      ULONG msg,
  120.                                      MPARAM mp1,
  121.                                      MPARAM mp2)
  122. {
  123.     return (WinDefDlgProc(hwnd, msg, mp1, mp2));
  124. }
  125.  
  126. /*
  127.  * ExplainParams:
  128.  *      this displays the dlg box which explains
  129.  *      NetscDDE's usage in brief; called when the
  130.  *      parameters on the cmd line don't seem to
  131.  *      be complete
  132.  */
  133.  
  134. VOID ExplainParams(VOID)
  135. {
  136.     WinCenteredDlgBox(HWND_DESKTOP, HWND_DESKTOP,
  137.         GenericDlgProc,
  138.         NULLHANDLE,
  139.         ID_NDD_EXPLAIN,
  140.         NULL);
  141. }
  142.  
  143. /*
  144.  * main:
  145.  *      Program entry point; accepts URLs on the command line.
  146.  */
  147.  
  148. int main(int argc, char *argv[])
  149. {
  150.     HMQ         hmq;
  151.     FRAMECDATA  fcd;
  152.     QMSG        qmsg;
  153.     BOOL        Proceed = TRUE;
  154.  
  155.     if (!(hab = WinInitialize(0)))
  156.         return FALSE;
  157.  
  158.     if (!(hmq = WinCreateMsgQueue(hab, 0)))
  159.         return FALSE;
  160.  
  161.     // parse parameters on cmd line
  162.     if (argc > 1) {
  163.         SHORT i = 0;
  164.         while (i++ < argc-1) {
  165.             if (argv[i][0] == '-') {
  166.                 SHORT i2;
  167.                 for (i2 = 1; i2 < strlen(argv[i]); i2++) {
  168.                     switch (argv[i][i2]) {
  169.                         case 'n':
  170.                             optNewWindow = TRUE;
  171.                         break;
  172.  
  173.                         case 'x':
  174.                             optExecute = FALSE;
  175.                         break;
  176.  
  177.                         case 'm':
  178.                             optMinimized = TRUE;
  179.                         break;
  180.  
  181.                         case 'h':
  182.                             optHidden = TRUE;
  183.                         break;
  184.  
  185.                         case 'X':
  186.                             optConfirmStart = FALSE;
  187.                         break;
  188.  
  189.                         case 'p':  // netscape path
  190.                             if (i < argc) {
  191.                                 strcpy(szNetscapeApp, argv[i+1]);
  192.                                 i++;
  193.                                 i2 = 1000;
  194.                             }
  195.                             else
  196.                             {
  197.                                 ExplainParams();
  198.                                 Proceed = FALSE;
  199.                             }
  200.                         break;
  201.  
  202.                         case 'P':  // netscape parameters
  203.                             if (i < argc) {
  204.                                 strcpy(szNetscapeParams, argv[i+1]);
  205.                                 i++;
  206.                                 i2 = 1000;
  207.                             }
  208.                             else
  209.                             {
  210.                                 ExplainParams();
  211.                                 Proceed = FALSE;
  212.                             }
  213.                         break;
  214.  
  215.                         case 'D': // debug, show list box window w/ DDE msgs
  216.                             optDebug = TRUE;
  217.                         break;
  218.  
  219.                         default:  // unknown parameter
  220.                             ExplainParams();
  221.                             Proceed = FALSE;
  222.                         break;
  223.                     }
  224.                 }
  225.             }
  226.             else {
  227.                 // no option ("-"): seems to be URL
  228.                 if (strchr(argv[i], ' ')) {
  229.                     // if the URL contains spaces, we enclose it in quotes
  230.                     sprintf(szURL, "\"%s\"", argv[i]);
  231.                 }
  232.                 else
  233.                     strcpy(szURL, argv[i]);
  234.             }
  235.         }
  236.     }
  237.  
  238.     if (strlen(szURL) == 0) {
  239.         // no URL given: explain
  240.         ExplainParams();
  241.         Proceed = FALSE;
  242.     }
  243.  
  244.     if (Proceed) {
  245.         // OK, parameters seemed to be correct:
  246.         // create the main window, which is only
  247.         // visible in Debug mode ("-D" param). But
  248.         // even if not in debug mode, this window is
  249.         // used for DDE message processing.
  250.         fcd.cb = sizeof(FRAMECDATA);
  251.         fcd.flCreateFlags = FCF_TITLEBAR        |
  252.                             FCF_SYSMENU         |
  253.                             FCF_MENU            |
  254.                             FCF_SIZEBORDER      |
  255.                             FCF_SHELLPOSITION   |
  256.                             FCF_MINMAX          |
  257.                             FCF_TASKLIST;
  258.  
  259.         fcd.hmodResources = NULLHANDLE;
  260.         // set our resource key (so PM can find menus, icons, etc).
  261.         fcd.idResources = DDEC;
  262.         // create the frame
  263.         hwndDebug = WinCreateWindow(HWND_DESKTOP,
  264.                                     WC_FRAME,
  265.                                     "Netscape DDE",
  266.                                     0, 0, 0, 0, 0,
  267.                                     NULLHANDLE,
  268.                                     HWND_TOP,
  269.                                     DDEC,
  270.                                     &fcd,
  271.                                     NULL);
  272.  
  273.         if (!hwndDebug)
  274.           return FALSE;
  275.  
  276.         // set the NetscDDE icon for the frame window
  277.         WinSendMsg(hwndDebug,
  278.                    WM_SETICON,
  279.                    (MPARAM)WinLoadPointer(HWND_DESKTOP, NULLHANDLE,
  280.                         ID_ICON),
  281.                     NULL);
  282.  
  283.         // create a list window child
  284.         hwndListbox = WinCreateWindow(hwndDebug,
  285.                                    WC_LISTBOX,
  286.                                    NULL,
  287.                                    LS_HORZSCROLL,
  288.                                    0, 0, 0, 0,
  289.                                    hwndDebug,
  290.                                    HWND_BOTTOM,
  291.                                    FID_CLIENT,
  292.                                    NULL,
  293.                                    NULL);
  294.  
  295.         // we must intercept the frame window's messages;
  296.         // we save the return value (the current WndProc),
  297.         // so we can pass it all the other messages the frame gets.
  298.         SysWndProc = WinSubclassWindow(hwndDebug, (PFNWP)LocalWndProc);
  299.  
  300.         // the window we just created is normally invisible; we
  301.         // will only display it if the (undocumented) "-D" option
  302.         // was given on the command line.
  303.         if (optDebug)
  304.             WinShowWindow(hwndDebug, TRUE);
  305.  
  306.         // now show "Contacting Netscape"
  307.         hwndContacting = WinLoadDlg(HWND_DESKTOP, hwndDebug,
  308.             GenericDlgProc,
  309.             0, ID_NDD_CONTACTING,
  310.             0);
  311.  
  312.         WinShowWindow(hwndContacting, TRUE);
  313.  
  314.         // now post msg to main window to initiate DDE
  315.         WinPostMsg(hwndDebug, WM_COMMAND, MPFROM2SHORT(IDM_INITIATE, 0), 0);
  316.  
  317.         //  standard PM message loop
  318.         while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
  319.         {
  320.             WinDispatchMsg(hab, &qmsg);
  321.         }
  322.     } // end if (proceed)
  323.  
  324.     // clean up on the way out
  325.     if (hwndContacting)
  326.         WinDestroyWindow(hwndContacting);
  327.     WinDestroyMsgQueue(hmq);
  328.     WinTerminate(hab);
  329.  
  330.     return TRUE;
  331. }
  332.  
  333. /*
  334.  * DDERequest:
  335.  *      this routine tries to post a DDE request to Netscape
  336.  *      and returns TRUE only if this was successful.
  337.  */
  338.  
  339. BOOL DDERequest(HWND hwndClient, PSZ pszItemString)
  340. {
  341.     ULONG       mem;
  342.     PID         pid;
  343.     TID         tid;
  344.     PDDESTRUCT  pddeStruct;
  345.     PSZ         pszDDEItemName;
  346.  
  347.     // get some sharable memory
  348.     DosAllocSharedMem((PVOID)&mem,
  349.                       NULL,
  350.                       sizeof(DDESTRUCT)+1000,
  351.                       PAG_COMMIT |
  352.                       PAG_READ |
  353.                       PAG_WRITE |
  354.                       OBJ_GIVEABLE);
  355.  
  356.     // get the server's ID and give it access
  357.     // to the shared memory
  358.     WinQueryWindowProcess(hServerWnd, &pid, &tid);
  359.     DosGiveSharedMem(&mem, pid, PAG_READ | PAG_WRITE);
  360.  
  361.     /* here is definition for DDESTRUCT, for further reference:
  362.     typedef struct _DDESTRUCT {
  363.         ULONG    cbData;
  364.              This is the length of data that occurs after the offabData parameter. If no
  365.              data exists, this field should contain a zero (0).
  366.         USHORT   fsStatus;       /  Status of the data exchange.
  367.              DDE_FACK
  368.                 Positive acknowledgement
  369.              DDE_FBUSY
  370.                 Application is busy
  371.              DDE_FNODATA
  372.                 No data transfer for advise
  373.              DDE_FACKREQ
  374.                 Acknowledgements are requested
  375.              DDE_FRESPONSE
  376.                 Response to WM_DDE_REQUEST
  377.              DDE_NOTPROCESSED
  378.                 DDE message not understood
  379.              DDE_FAPPSTATUS
  380.                 A 1-byte field of bits that are reserved for application-specific returns.
  381.         USHORT   usFormat;       /  Data format.
  382.         USHORT   offszItemName;  /  Offset to item name.
  383.              This is the offset to the item name from the start of this structure. Item
  384.              name is a null (0x00) terminated string. If no item name exists, there must
  385.              be a single null (0x00) character in this position. (That is, ItemName is
  386.              ALWAYS a null terminated string.)
  387.  
  388.         USHORT   offabData;      /  Offset to beginning of data.
  389.              This is the offset to the data, from the start of this structure. This field
  390.              should be calculated regardless of the presence of data. If no data exists,
  391.              cbData must be zero (0).
  392.  
  393.              For compatibility reasons, this data should not contain embedded pointers.
  394.              Offsets should be used instead.
  395.  
  396.     --  CHAR     szItemName[]    /  offset: offszItemName
  397.     --  BYTE     abData[]        /  offset: offabData
  398.     } DDESTRUCT; */
  399.  
  400.     // setup DDE data structures
  401.     pddeStruct = (PDDESTRUCT)mem;
  402.     pddeStruct->fsStatus = 0; // DDE_FACKREQ;            // Status
  403.     pddeStruct->usFormat = DDEFMT_TEXT;  // Text format
  404.  
  405.     // go past end of data structure for the item name
  406.     pddeStruct->offszItemName = sizeof(DDESTRUCT);
  407.  
  408.     pszDDEItemName = ((BYTE*)pddeStruct)+(pddeStruct->offszItemName);
  409.     strcpy(pszDDEItemName, pszItemString);
  410.  
  411.     // go past end of data structure
  412.     // (plus past the name) for the data
  413.     pddeStruct->offabData = strlen(pszDDEItemName)+1;
  414.         // offset to BEGINNING of data
  415.     pddeStruct->cbData   = 500;
  416.         // length of the data
  417.  
  418.     // post our request to the server program
  419.     NetscapeFound = (WinDdePostMsg(hServerWnd,
  420.                   hwndClient,
  421.                   WM_DDE_REQUEST,
  422.                   pddeStruct,
  423.                   0));
  424.  
  425.     return (NetscapeFound);
  426. }
  427.  
  428. /*
  429.  * LocalWndProc:
  430.  *      window procedure for the main NetscDDE window, which
  431.  *      is only visible in Debug mode ("-D" option), mostly
  432.  *      processing DDE messages. If we're in debug mode, this
  433.  *      routine waits for certain menu selections, otherwise
  434.  *      the corresponding messages will be posted automatically.
  435.  */
  436.  
  437. MRESULT EXPENTRY LocalWndProc(HWND hwndFrame,ULONG msg,MPARAM mp1,MPARAM mp2)
  438. {
  439.     PSZ         szData;
  440.     PDDESTRUCT  pddeStruct;
  441.     ULONG       mem;
  442.  
  443.     CHAR        szBuffer[200];
  444.  
  445.     switch(msg)
  446.     {
  447.  
  448.         // all answers to the WinDDEInitate call arrive here
  449.         case WM_DDE_INITIATEACK: {
  450.             PDDEINIT    pddeInit;
  451.             PSZ         szInApp, szInTopic;
  452.  
  453.             pddeInit   = (PDDEINIT)mp2;
  454.             szInApp    = pddeInit->pszAppName;
  455.             szInTopic  = pddeInit->pszTopic;
  456.             ShowMessage("!! Netscape odpov╪d╪l.");
  457.             hServerWnd = (HWND)mp1;
  458.  
  459.         break; }
  460.  
  461.         // all answers to DDE requests arrive here
  462.         case WM_DDE_DATA: {
  463.             ShowMessage("!! P²ijata data od Netscape: ");
  464.             pddeStruct = (PDDESTRUCT)mp2;
  465.             DosGetSharedMem(pddeStruct, PAG_READ | PAG_WRITE);
  466.             szData = (BYTE *)(pddeStruct+(pddeStruct->offabData));
  467.             ShowMessage(szData);
  468.         break; }
  469.  
  470.         // menu item processing (in debug mode, otherwise these
  471.         // WM_COMMAND msgs have been posted automatically)
  472.         case WM_COMMAND:
  473.             switch (SHORT1FROMMP(mp1))
  474.             {
  475.                 // start DDE conversation: this was posted
  476.                 // by "main" before the PM loop was entered
  477.                 case IDM_INITIATE:
  478.                     WinPostMsg(hwndListbox, LM_DELETEALL, 0, 0);
  479.                     ShowMessage("--- Spouτtím DDE... Téma:");
  480.                     ShowMessage(szOpenURLTopic);
  481.                     context.cb = sizeof(CONVCONTEXT);
  482.                     context.fsContext = 0;
  483.                     WinDdeInitiate(hwndFrame, szDDENetscape,
  484.                         szOpenURLTopic, &context);
  485.                     if (!optDebug)
  486.                         // if we're not in debug mode, post subsequent
  487.                         // menu commands automatically
  488.                         WinPostMsg(hwndFrame, WM_COMMAND, MPFROM2SHORT(IDM_CHAIN2, 0), 0);
  489.                 break;
  490.  
  491.                 // "Open URL": request data from server
  492.                 case IDM_OPENURL: {
  493.                     ShowMessage("--- URL je:");
  494.                     ShowMessage(szURL);
  495.                     strcpy(szBuffer, szURL);
  496.                     strcat(szBuffer, ",,0xFFFFFFFF,0x0");
  497.                     ShowMessage("Odesílám poºadavek:");
  498.                     ShowMessage(szBuffer);
  499.  
  500.                     if (DDERequest(hwndFrame, szBuffer))
  501.                         ShowMessage("Zpráva DDE odeslána.");
  502.                     else
  503.                         ShowMessage("Chyba p²i odesílání zprávy DDE.");
  504.                 break; }
  505.  
  506.                 // "Open URL in new window": request data from server,
  507.                 // but with different parameters
  508.                 case IDM_OPENURLNEW: {
  509.                     ShowMessage("--- URL je:");
  510.                     ShowMessage(szURL);
  511.                     strcpy(szBuffer, szURL);
  512.                     strcat(szBuffer, ",,0x0,0x0");
  513.                     ShowMessage("Odesílám poºadavek:");
  514.                     ShowMessage(szBuffer);
  515.                     if (DDERequest(hwndFrame, szBuffer))
  516.                         ShowMessage("Zpráva DDE odeslána.");
  517.                     else
  518.                         ShowMessage("Chyba p²i odesílání zprávy DDE.");
  519.                 break; }
  520.  
  521.                 /*
  522.                  * IDM_CHAIN2:
  523.                  *      this is posted after DDE_INITIATE was
  524.                  *      successful
  525.                  */
  526.  
  527.                 case IDM_CHAIN2:
  528.                     {
  529.                         if (optNewWindow)
  530.                             WinPostMsg(hwndDebug, WM_COMMAND, MPFROM2SHORT(IDM_OPENURLNEW, 0), 0);
  531.                         else
  532.                             WinPostMsg(hwndDebug, WM_COMMAND, MPFROM2SHORT(IDM_OPENURL, 0), 0);
  533.                         WinPostMsg(hwndDebug, WM_COMMAND, MPFROM2SHORT(IDM_CHAIN3, 0), 0);
  534.                     }
  535.                 break;
  536.  
  537.                 /*
  538.                  * IDM_CHAIN3:
  539.                  *      this is posted to close the whole thing; we just need
  540.                  *      another msg before going for IDM_CLOSE, or some DDE
  541.                  *      msgs might get lost
  542.                  */
  543.  
  544.                 case IDM_CHAIN3:
  545.                     WinPostMsg(hwndDebug, WM_COMMAND, MPFROM2SHORT(IDM_CLOSE, 0), 0);
  546.                 break;
  547.  
  548.                 /*
  549.                  * IDM_CLOSE:
  550.                  *      this is posted to close the whole thing
  551.                  */
  552.  
  553.                 case IDM_CLOSE:
  554.                     WinDdePostMsg(hServerWnd,
  555.                                  hwndFrame,
  556.                                  WM_DDE_TERMINATE,
  557.                                  NULL,
  558.                                  DDEPM_RETRY);
  559.                     ShowMessage("Komunikace DDE ukonƒena.");
  560.  
  561.                     if (!optDebug)
  562.                         WinPostMsg(hwndFrame, WM_COMMAND, MPFROM2SHORT(IDM_DELAYEXIT, 0), 0);
  563.                 break;
  564.  
  565.                 /*
  566.                  * IDM_DELAYEXIT:
  567.                  *      this is posted after IDM_CLOSE; we will now
  568.                  *      check for whether the DDE conversation with
  569.                  *      Netscape was successful and, if not, start
  570.                  *      a new instance of Netscape according to the
  571.                  *      command line parameters
  572.                  */
  573.  
  574.                 case IDM_DELAYEXIT: {
  575.                     if ((!NetscapeFound) && (optExecute)) {
  576.                         // confirm start netscape
  577.                         if (    (!optConfirmStart)
  578.                             ||  (WinCenteredDlgBox(
  579.                                     HWND_DESKTOP,
  580.                                      hwndDebug,
  581.                                      GenericDlgProc,
  582.                                      NULLHANDLE,
  583.                                      ID_NDD_QUERYSTART,
  584.                                      NULL)
  585.                                 == DID_OK)
  586.                            )
  587.                         {
  588.                             STARTDATA SData       = {0};
  589.                             APIRET    rc          = 0;
  590.                             PID       pid         = 0;          // PID returned
  591.                             ULONG     ulSessID    = 0;          // session ID returned
  592.                             UCHAR     achObjBuf[256] = {0};     // Error data if DosStart fails
  593.  
  594.                             CHAR        szArgs[CCHMAXPATH];
  595.                             CHAR        szMsg[100];        // message
  596.  
  597.                             HWND         hwndNotify = HWND_DESKTOP;
  598.                             PROGDETAILS  Details;
  599.                             HAPP         happ;
  600.  
  601.                             // destroy "Contacting", create "Starting Netscape"
  602.                             // window
  603.                             if (hwndContacting)
  604.                                 WinDestroyWindow(hwndContacting);
  605.  
  606.                             hwndContacting = WinLoadDlg(HWND_DESKTOP, hwndDebug,
  607.                                 GenericDlgProc,
  608.                                 0, ID_NDD_STARTING,
  609.                                 0);
  610.  
  611.                             WinShowWindow(hwndContacting, TRUE);
  612.  
  613.                             // now start session
  614.                             strcpy(szArgs, szNetscapeParams);
  615.                             strcat(szArgs, " ");
  616.                             strcat(szArgs, szURL);
  617.  
  618.                             SData.Length  = sizeof(STARTDATA);
  619.                             SData.Related = SSF_RELATED_INDEPENDENT;
  620.                             SData.FgBg    = SSF_FGBG_FORE;
  621.                             SData.TraceOpt = SSF_TRACEOPT_NONE;
  622.  
  623.                             SData.PgmTitle = "Netscape";
  624.                             SData.PgmName = szNetscapeApp;
  625.                             SData.PgmInputs = szArgs;
  626.  
  627.                             SData.TermQ = 0;
  628.                             SData.Environment = 0;
  629.                             SData.InheritOpt = SSF_INHERTOPT_SHELL;
  630.                             SData.SessionType = SSF_TYPE_DEFAULT;
  631.                             SData.IconFile = 0;
  632.                             SData.PgmHandle = 0;
  633.  
  634.                             SData.PgmControl = (optMinimized)
  635.                                              ? (SSF_CONTROL_MINIMIZE |
  636.                                                     ((optHidden) ? SSF_CONTROL_INVISIBLE : SSF_CONTROL_VISIBLE)
  637.                                                )
  638.                                              : SSF_CONTROL_VISIBLE;
  639.                             SData.InitXPos  = 30;
  640.                             SData.InitYPos  = 40;
  641.                             SData.InitXSize = 200;
  642.                             SData.InitYSize = 140;
  643.                             SData.Reserved = 0;
  644.                             SData.ObjectBuffer  = achObjBuf;
  645.                             SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf);
  646.  
  647.                             rc = DosStartSession(&SData, &ulSessID, &pid);
  648.                         }
  649.                     }
  650.                     // keep "Contacting" / "Starting" window visible for two seconds
  651.                     idTimer = WinStartTimer(hab, hwndFrame, 1, 2000);
  652.                 break; }
  653.  
  654.                 // User closes the window
  655.                 case IDM_EXIT:
  656.                     WinPostMsg(hwndFrame, WM_CLOSE, 0, 0);
  657.                 break;
  658.             }
  659.             break;
  660.  
  661.             case WM_TIMER:
  662.                 // after two seconds, close status window
  663.                 WinStopTimer(hab, hwndFrame, idTimer);
  664.                 WinPostMsg(hwndFrame, WM_CLOSE, 0, 0);
  665.                 break;
  666.  
  667.             // Send the message to the usual WC_FRAME WndProc
  668.             default:
  669.                return (*SysWndProc)(hwndFrame, msg, mp1, mp2);
  670.     }
  671.  
  672.     return FALSE;
  673. }
  674.  
  675. /*
  676.  * ShowMessage:
  677.  *      add a string to the listbox.
  678.  */
  679.  
  680. void ShowMessage(PSZ szText)
  681. {
  682.    WinPostMsg(hwndListbox,
  683.               LM_INSERTITEM,
  684.               MPFROMSHORT(LIT_END),
  685.               szText);
  686. }
  687.  
  688.