home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / S12267.ZIP / SERVER.C < prev    next >
C/C++ Source or Header  |  1988-11-11  |  14KB  |  627 lines

  1. #define YEAH_PROCS
  2. #define INCL_PM
  3. #define INCL_WINDDE
  4. #define INCL_WINTRACKRECT
  5. #include <os2.h>
  6. #include "server.h"
  7.  
  8. HAB hab;
  9. HWND hwndServer;
  10. HWND hwndServerFrame;
  11. HMQ hmqServer;
  12.  
  13. HCHNL hchnlStockInfo;
  14. HCHNL hchnlSystem;
  15.  
  16. HWND hwndClient;
  17. HWND hwndSystem;
  18. char szServerClass[] = "Server";
  19. char szAppName[] = "Server";
  20. char szTopic[] = "StockInfo";
  21. char szSystem[] = "System";
  22. #define iStockMac 5
  23. BOOL fWaitAck[iStockMac];
  24. BOOL fStockAdvised[iStockMac];
  25. int cfFormat[iStockMac];
  26. int cfCSV;
  27. BOOL fQuit;
  28.  
  29. int cScroll=8;
  30. char szMarquee[256];
  31.  
  32. char *rgszItem[] = {  "IBM", "T", "GM", "INDU", "MSFT" };
  33.  
  34. /* These are sample strings that are exact duplicates of what the
  35.     real Server Application would send out.  Here is the format:
  36.  
  37.     name,dataaone,datatwo,datathree,datafour,voludme,exg,n,b,e
  38.  
  39.     name is 3 or 5 letter name of symbol
  40.     dataone is decimal number of last sale
  41.     datatwo is decimal number of previous close
  42.     datathree is decimal number of high
  43.     datafour is decimal number o low.
  44.     volume is volume
  45.     exg is exchange where traded.  Also signifies open or close.
  46.     n is news indicator
  47.     b is real time and background indicator
  48.     e is exchange where listed
  49.     a is optional indicator
  50.     [usually applications ignore the last four fields]
  51.  
  52.    NOTE:  dataone..datafour must be padded with leading spaces to the
  53.      hundreds digit.
  54.  
  55.  
  56. */
  57.  
  58. #define ichMax 11
  59. char *szstock[] = {  "IBM ,120.2,120.0,121.3,119.6,940K,P,N,Y,N",
  60.              "T   , 28.0, 27.5, 28.6, 27.4,1.40M,X,N,Y,N",
  61.              "GM  , 83.6, 83.5, 84.7, 82.4,390K,B,N,Y,N",
  62.              "INDU, 76.6, 76.5, 77.7, 76.4,220K,B,N,Y,N",
  63.              "MSFT, 49.5, 48.5, 50.5, 48.4,890K,B,N,Y,N"
  64.            };
  65.  
  66.  
  67. /************* PROCEDURE DECLARATIONS   */
  68.  
  69. MRESULT FAR PASCAL ServWndProc(HWND, USHORT, MPARAM, MPARAM);
  70. unsigned random();
  71.  
  72. /************* COMMAND DISPATCH TABLE   */
  73.  
  74. int (*rgpfnCmds[CCMDS])() = {
  75.     NULL, NULL, NULL, NULL,         /* File menu */
  76.     NULL, NULL, NULL, NULL, NULL    /* Edit menu */
  77. };
  78.  
  79. #define toupper(ch) ((ch)&0xdf)
  80.  
  81. /**************************************/
  82.  
  83. VOID DoCommand(cmd)
  84. int cmd;
  85. {
  86.     int (*pfn)();
  87.  
  88. /*
  89.     Lo byte of cmd value is index into dispatch table
  90.     Hi byte of cmd is menu index, or whatever.  Hi byte
  91.     can be used in a switch here to do common processing for
  92.     related commands.
  93. */
  94.     if ((pfn = rgpfnCmds[LOBYTE(cmd)]) != NULL)
  95.         (*pfn)();
  96. }
  97.  
  98. BOOL ServerInit()
  99. {
  100.     HATOMTBL hatomtbl;
  101.     
  102.     hab = WinInitialize(0);
  103.  
  104.     hmqServer = WinCreateMsgQueue(hab, 0);
  105.  
  106.     if (!WinRegisterClass(hab, szServerClass, (PFNWP)ServWndProc, 0L, 0))
  107.         return(FALSE);
  108.  
  109.     hatomtbl = WinQuerySystemAtomTable();
  110.     cfCSV = (int)WinAddAtom(hatomtbl, (PSZ)"Csv");
  111.  
  112.     randomize(42);
  113.  
  114.     LpszCopy((PSZ)"Market Open...................................................................", (PSZ)szMarquee);
  115.  
  116.     return(TRUE);
  117. }
  118.  
  119. int Os2Main(argc, argv)
  120. int argc;
  121. char **argv;
  122. {
  123.     int dx, dy;
  124.     long lgrbitCtl;
  125.     QMSG qmsg;
  126.     HCHNL HchnlCreate();
  127.     HPS hps;
  128.     FONTMETRICS fm;
  129.  
  130.     if (!ServerInit()) {
  131.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  132.         return(0);
  133.     }
  134.  
  135.     lgrbitCtl = FCF_DLGBORDER|FCF_TASKLIST;
  136.  
  137.     hwndServerFrame = WinCreateStdWindow(HWND_DESKTOP,
  138.             0L,
  139.             &lgrbitCtl,
  140.             szServerClass, NULL,
  141.             0L,
  142.             (HMODULE)NULL, 0,
  143.             (HWND FAR *)&hwndServer);
  144.  
  145.     hps = WinGetPS(hwndServer);
  146.     GpiQueryFontMetrics(hps, (long)sizeof(FONTMETRICS), &fm);
  147.     dx = fm.lAveCharWidth*40;
  148.     dy = fm.lXHeight*4;
  149.     WinReleasePS(hps);
  150.     WinSetWindowPos(hwndServerFrame, HWND_TOP, 10, 10, dx, dy, SWP_SIZE|SWP_MOVE|SWP_ZORDER);
  151.  
  152.     /* create windows for dde communication */
  153.     hchnlStockInfo = HchnlCreate(szTopic);
  154.     hchnlSystem = HchnlCreate(szSystem);
  155.     if (hwndServer == NULL || hchnlStockInfo == NULL || hchnlSystem == NULL)
  156.         return(0);
  157.  
  158.  
  159.     WinShowWindow(hwndServerFrame, TRUE);
  160.     WinShowWindow(hwndServer, TRUE);
  161.     WinSetFocus(HWND_DESKTOP, hwndServer);
  162.  
  163.     while (WinGetMsg(hab, (PQMSG)&qmsg, NULL, 0, 0)) {
  164.         WinDispatchMsg(hab, (PQMSG)&qmsg);
  165.     }
  166.  
  167.     WinDestroyWindow(hwndServerFrame);
  168.  
  169.     WinDestroyMsgQueue(hmqServer);
  170.     WinTerminate(hab);
  171.  
  172.     DosExit(EXIT_PROCESS, 0);
  173. }
  174.  
  175. /********** Server Window Procedure **************/
  176.  
  177. MRESULT FAR PASCAL ServWndProc(hwnd, msg, mp1, mp2)
  178. HWND hwnd;
  179. USHORT msg;
  180. MPARAM mp1;
  181. MPARAM mp2;
  182. {
  183.     int cf;
  184.     int iStock;
  185.     int ret;
  186.     HPS hps;
  187.     RECTL rclPaint;
  188.     VOID ServerPaint();
  189.     DDESTRUCT far *LpddeAlloc();
  190. #define lpdde ((DDESTRUCT far *)mp2)
  191. #define lpddeinit ((DDEINIT far *)mp2)
  192. #define hchnlClient ((HWND)mp1)
  193.  
  194.     switch (msg) {
  195.     case WM_PAINT:
  196.         hps = WinBeginPaint(hwnd, (HPS)NULL, &rclPaint);
  197.         ServerPaint(hwnd, hps);
  198.         WinEndPaint(hps);
  199.         return(0L);
  200.  
  201.     case WM_COMMAND:
  202.         DoCommand(LOUSHORT(mp1));
  203.         return(0L);
  204.  
  205.     case WM_TIMER:
  206.         GotTimer();
  207.         return(0L);
  208.         
  209.     case WM_CLOSE:
  210.     case WM_BUTTON1DBLCLK:
  211.         if (!hwndClient && !hwndSystem)
  212.             goto GoodNight;
  213.  
  214.         if (fQuit)
  215.             return(0L);
  216.         
  217.         fQuit=TRUE;
  218.         if (hwndClient != NULL)
  219.             WinDdePostMsg(hwndClient, hchnlStockInfo, WM_DDE_TERMINATE, 0L, TRUE);
  220.         if (hwndSystem != NULL)
  221.             WinDdePostMsg(hwndClient, hchnlSystem, WM_DDE_TERMINATE, 0L, TRUE);
  222.         break;
  223.  
  224.     case WM_BUTTON1DOWN:
  225.         return((ULONG)WinSendMsg(hwndServerFrame, WM_TRACKFRAME,
  226.                     (MPARAM)(((long)mp2&0xffff) | TF_MOVE), (MPARAM)0L));
  227.  
  228.     case WM_DDE_INITIATE:
  229.  
  230.         if ((CchLpszLen(lpddeinit->pszAppName) == 0 ||
  231.              FLpszEq(lpddeinit->pszAppName, (PSZ)szAppName)) && !fQuit)
  232.             {
  233.             if ((CchLpszLen(lpddeinit->pszTopic) == 0 ||
  234.                  FLpszEq(lpddeinit->pszTopic, (PSZ)szSystem)) &&
  235.                 hwndSystem == NULL)
  236.                 {
  237.                 WinDdeRespond(hchnlClient, hchnlSystem, (PSZ)szAppName, (PSZ)szSystem);
  238.                 hwndSystem = hchnlClient;
  239.                 }
  240.             if ((CchLpszLen(lpddeinit->pszTopic) == 0 ||
  241.                  FLpszEq(lpddeinit->pszTopic, (PSZ)szTopic)) &&
  242.                 hwndClient == NULL)
  243.                 {
  244.                 WinDdeRespond(hchnlClient, hchnlStockInfo, szAppName, szTopic);
  245.                 hwndClient = hchnlClient;
  246.                 }
  247.             }
  248.         break;
  249.     case WM_DDE_TERMINATE:
  250.         if (hwnd == hchnlStockInfo)
  251.             {
  252.             WinStopTimer(hab, hwndServer, 0xedf);
  253.             if (!fQuit)
  254.                 WinDdePostMsg(hwndClient, hwnd, WM_DDE_TERMINATE, 0L, TRUE);
  255.             hwndClient = NULL;
  256.             }
  257.         if (hwnd == hchnlSystem)
  258.             {
  259.             if (!fQuit)
  260.                 WinDdePostMsg(hwndSystem, hwnd, WM_DDE_TERMINATE, 0L, TRUE);
  261.             hwndSystem = NULL;
  262.             }
  263.         if (fQuit && hwndClient == NULL && hwndSystem == NULL)
  264.             {
  265. GoodNight:
  266.             WinDestroyWindow(hwndServerFrame);
  267.             WinDestroyMsgQueue(hmqServer);
  268.             WinTerminate(hab);
  269.             DosExit(EXIT_PROCESS, 0);
  270.             }
  271.         break;
  272.  
  273.     case WM_DDE_ACK:
  274.         for (iStock=0; iStock<iStockMac; iStock++)
  275.             if (FLpszEq(DDES_PSZITEMNAME(lpdde), (PSZ)rgszItem[iStock]))
  276.                 fWaitAck[iStock]=FALSE;
  277.         break;
  278.  
  279.     case WM_DDE_ADVISE:
  280.         /* Note this code Assumes CF_CSV is the requested
  281.         * Clipboard format.  Ideally one should check first,
  282.         * by checking the wFormat field of the Advise block
  283.         * which is passed as a handle in the loword of lParam.
  284.         */
  285.         if  (hwnd == hchnlSystem || fQuit)
  286.             break; /* shouldn't we nack here? */
  287.         cf = lpdde->usFormat;
  288.         ret=0;
  289.         for (iStock=0; iStock<iStockMac; iStock++)
  290.             if (FLpszEq(DDES_PSZITEMNAME(lpdde), (PSZ)rgszItem[iStock]) &&
  291.                 (cf == cfCSV || cf == DDEFMT_TEXT))
  292.                 {
  293.                 fStockAdvised[iStock]=TRUE;
  294.                 fWaitAck[iStock]=FALSE;
  295.                 cfFormat[iStock]=cf;
  296.                 ret = DDE_FACK;
  297.                 break;
  298.                 }
  299.         lpdde->fsStatus = ret;
  300.         WinDdePostMsg(hchnlClient, hwnd, WM_DDE_ACK, lpdde, TRUE);
  301.         if (ret)
  302.             WinStartTimer(hab, hwndServer, 0xedf, 250);
  303.         break;
  304.  
  305.     case WM_DDE_REQUEST:
  306.         if (hwnd == hchnlSystem && fQuit)
  307.             break;
  308.         cf = lpdde->usFormat;
  309.         for (iStock=0; iStock<iStockMac; iStock++)
  310.             if (FLpszEq(DDES_PSZITEMNAME(lpdde), (PSZ)rgszItem[iStock]) && (cf == cfCSV || cf == DDEFMT_TEXT))
  311.                 {
  312.                 DosFreeSeg(PDDESTOSEL(lpdde));
  313.                 lpdde = LpddeAlloc(rgszItem[iStock], 50);
  314.                 /* mark data as ack to request */
  315.                 lpdde->fsStatus = DDE_FRESPONSE;
  316.                 lpdde->usFormat = cf;
  317.                 LpszCopy((PSZ)szstock[iStock], DDES_PABDATA(lpdde));
  318.                 WinDdePostMsg(hwndClient, hchnlStockInfo, WM_DDE_DATA, lpdde, TRUE);
  319.                 break;
  320.                 }
  321.         if (iStock == iStockMac) /* Nack request if no item found */
  322.             {
  323.             lpdde->fsStatus = 0;
  324.             WinDdePostMsg(hchnlClient, hwnd, WM_DDE_ACK, lpdde, TRUE);
  325.             }
  326.         break;
  327.  
  328.     case WM_DDE_UNADVISE:
  329.         if (hwnd == hchnlSystem || fQuit)
  330.             break;
  331.         ret=0;
  332.         for (iStock=0; iStock<iStockMac; iStock++)
  333.             if (FLpszEq(DDES_PSZITEMNAME(lpdde), (PSZ)rgszItem[iStock]))
  334.                 {
  335.                 fStockAdvised[iStock]=FALSE;
  336.                 ret = DDE_FACK;
  337.                 break;
  338.                 }
  339.         lpdde->fsStatus = ret;
  340.         WinDdePostMsg(hchnlClient, hwnd, WM_DDE_ACK, lpdde, TRUE);
  341.         break;
  342.  
  343.     default:
  344. DefProc:
  345.         return(WinDefWindowProc(hwnd, msg, mp1, mp2));
  346.     }
  347. #undef lpdde
  348. #undef hchnlClient
  349. }
  350.  
  351. VOID ServerPaint(hwnd, hps)
  352. HWND hwnd;
  353. HPS hps;
  354. {
  355.     RECTL rcl;
  356.     CHARBUNDLE charb;
  357.     
  358.     GpiQueryAttrs(hps, PRIM_CHAR, CBB_BOX, &charb);
  359.     charb.sizfxCell.cy *= 4;
  360.     charb.sizfxCell.cx *= 4;
  361.     GpiSetAttrs(hps, PRIM_CHAR, CBB_BOX, CBB_SET, &charb);
  362.     WinQueryWindowRect(hwnd, &rcl);
  363.     WinDrawText(hps, -1, szMarquee, &rcl, SYSCLR_WINDOWTEXT,
  364.             SYSCLR_WINDOW, DT_ERASERECT);
  365. }
  366.  
  367.  
  368.  
  369. /* GetQuote:
  370.  
  371.    Assumes number is found between 2 commas, can have leading spaces.
  372.  
  373.    Number returned is 10x real #.
  374.    ie  XXXX,123.3,XXXX will be returned as 1233
  375. */
  376.  
  377. int GetQuote(nStock,nData)
  378. int nStock, nData;
  379.  
  380. {
  381.     char *cT;
  382.     int  nValue = 0;
  383.  
  384.     cT = szstock[nStock];
  385.     while( *cT && nData > 0)
  386.         {
  387.         if (*cT == ',')
  388.             nData--;
  389.         cT++;
  390.         }
  391.  
  392.     while ( *cT == ' ')    /* skip whspace */
  393.         cT++;
  394.  
  395.     while ( *cT != ',')    /* parse number */
  396.         {
  397.         if(*cT == '.')
  398.             cT++;
  399.         nValue = 10 * nValue + *cT - '0';
  400.         cT++;
  401.         }
  402.  
  403.     return nValue;
  404. }
  405.  
  406.  
  407.  
  408.  
  409. /* ChangeQuote:
  410.  
  411.   Assumes:
  412.     nValue < 10000;
  413.  
  414.   Note to avoid using FP, nValue is 10x what the real stock price is.
  415.  
  416. */
  417.  
  418. void ChangeQuote(nStock, nData, nValue)
  419. int nStock, nData, nValue;
  420. {
  421.     char *cT;
  422.     int nBase;
  423.     int nPrevValue;
  424.  
  425.     cT = szstock[nStock];
  426.     while(*cT && nData > 0)      /* Make cT point to char after comma */
  427.         {
  428.         if (*cT == ',')
  429.             nData--;
  430.         cT++;
  431.         }
  432.  
  433.     while( *cT != ',')          /* blank out field */
  434.         *cT++ = (*cT == '.' ? '.' : ' ');
  435.  
  436.     cT--;
  437.     while (nValue)
  438.         {
  439.         if (*cT == '.')
  440.             cT--;
  441.         *cT-- = nValue % 10 + '0';
  442.         nValue /= 10;
  443.         }
  444. }
  445.  
  446. GotTimer()
  447. {
  448.     DDESTRUCT far *lpdde;
  449.     int iStock;
  450.     int nQuote;
  451.     int ich, ichT;
  452.     DDESTRUCT far *LpddeAlloc();
  453.  
  454.     if (cScroll<ichMax)
  455.         {
  456.         LpszCopy((PSZ)szMarquee+1, (PSZ)szMarquee);
  457.         WinInvalidateRect(hwndServer, NULL, FALSE);
  458.         cScroll++;
  459.         return;
  460.         }
  461.  
  462.     iStock = random() % iStockMac;
  463.  
  464.     if (!fStockAdvised[iStock] || fWaitAck[iStock])
  465.         return;
  466.  
  467.     cScroll = 0;
  468.     nQuote = GetQuote(iStock,1) + (random()&0x07) - 0x03;
  469.     if(iStock == 4)                     /* msft */
  470.         nQuote++;
  471.     ChangeQuote(iStock,1,nQuote);
  472.  
  473.     lpdde = LpddeAlloc(rgszItem[iStock], 50);
  474.     lpdde->fsStatus = DDE_FACKREQ;
  475.     lpdde->usFormat = cfFormat[iStock];
  476.  
  477.     LpszCopy((PSZ)szstock[iStock], DDES_PABDATA(lpdde));
  478.  
  479.     WinDdePostMsg(hwndClient, hchnlStockInfo, WM_DDE_DATA, lpdde, TRUE);
  480.     fWaitAck[iStock]=TRUE;
  481.     for (ich=0, ichT=CchLpszLen((PSZ)szMarquee); ich<ichMax; ich++,ichT++)
  482.         {
  483.         szMarquee[ichT] = szstock[iStock][ich];
  484.         if (szMarquee[ichT] == ',')
  485.             szMarquee[ichT] = ' ';
  486.         }
  487.     szMarquee[ichT] = 0;
  488. }
  489.  
  490. HCHNL HchnlCreate(sz)
  491. char *sz;
  492. {
  493.     return(WinCreateWindow(HWND_OBJECT, szServerClass, &sz[1],
  494.             0L, 0, 0, 0, 0,
  495.             HWND_DESKTOP, HWND_TOP, 23, NULL, NULL));
  496. }
  497.  
  498. DDESTRUCT far *LpddeAlloc(sz, cbData)
  499. char *sz;
  500. int cbData;
  501. {
  502.     int cbBase;
  503.     SEL sel;
  504.     DDESTRUCT far *lpdde;
  505.  
  506.     cbBase = CchLpszLen((PSZ)sz)+1+sizeof(DDESTRUCT);
  507.     DosAllocSeg(cbBase+cbData, &sel, SEG_GIVEABLE);
  508.     lpdde = MAKEP(sel, 0);
  509.     lpdde->cbData = cbBase+cbData;
  510.     lpdde->fsStatus = 0;
  511.     lpdde->usFormat = 0;
  512.     lpdde->offszItemName = sizeof(DDESTRUCT);
  513.     lpdde->offabData = cbBase;
  514.     LpszCopy((char far *)sz, DDES_PSZITEMNAME(lpdde));
  515.     return(lpdde);
  516. }
  517.  
  518. CchLpszLen(lpch)
  519. char far *lpch;
  520. {
  521.     int cch;
  522.     
  523.     for (cch=0; *lpch++; cch++)
  524.         ;
  525.     return(cch);
  526. }
  527.  
  528. LpszCopy(lpchFrom, lpchTo)
  529. char far *lpchFrom;
  530. char far *lpchTo;
  531. {
  532.     while (*lpchTo++ = *lpchFrom++)
  533.         ;
  534. }
  535.  
  536. FLpszEq(lpch, lpch2)
  537. char far *lpch;
  538. char far *lpch2;
  539. {
  540.     for (; *lpch && toupper(*lpch2) == toupper(*lpch); lpch++, lpch2++)
  541.         ;
  542.     return(toupper(*lpch) == toupper(*lpch2));
  543. }
  544.  
  545. /*
  546.  *    Global data
  547.  */
  548.  
  549. static unsigned seed = 0;
  550. static unsigned rgrnd[55];
  551. static int j, k;
  552.  
  553.  
  554.  
  555. /***    random2 - returns a random unsigned integer
  556.  *
  557.  *      This is a simple linear congruence RNG.
  558.  *
  559.  *    random2()
  560.  *
  561.  *    Entry:    None
  562.  *    Exit:    returns - 16-bit unsigned pseudo-random number
  563.  *
  564.  *    The actual formula used is:
  565.  *    
  566.  *        seed = (25173 * seed + 13849) % 65536;
  567.  *
  568.  *    Since the modulus corresponds nicely with our word size, we
  569.  *    don't have to do the division.
  570.  */
  571.  
  572. unsigned random2()
  573. {
  574.         return(seed = 25173 * seed + 13849);
  575. }
  576.  
  577. /***    randomize - initialize RNG
  578.  *
  579.  *    Here we initialize our additive random number generator (RNG).
  580.  *
  581.  *    randomize(u)
  582.  *
  583.  *    Entry:    u - random number seed
  584.  *    Exit:    None
  585.  *
  586.  *    We just fill up our rgrnd array with pseudo-random numbers
  587.  *    (generated with a congruence RNG) and then initialize a couple
  588.  *    of pointers into the arrays (cf. Knuth).
  589.  */
  590.  
  591. randomize(u)
  592. unsigned u;
  593. {
  594.          seed = u;    /* seed random2() */
  595.     for (u = 0; u < 55; u++)
  596.         rgrnd[u] = random2();
  597.         j = 23; k = 54;
  598. }
  599.  
  600. /***    random - return a random number
  601.  *
  602.  *      This is our magic additive RNG.  Cf. Knuth and randomize()
  603.  *    above for further info.
  604.  *
  605.  *    random(umax)
  606.  *
  607.  *    Entry:    umax - range random number should be in
  608.  *    Exit:    returns - random number within [0..umax)
  609.  */
  610.  
  611. unsigned random(umax)
  612. unsigned umax;
  613. {
  614.     unsigned u;
  615.  
  616.         u = (rgrnd[k] += rgrnd[j]);
  617.         if (--j < 0)
  618.             j = 54;
  619.         if (--k < 0)
  620.             k = 54;
  621.     /* u is a random unsigned integer in the interval [0..65536).
  622.        Multiplying by umax will give us a 32-bit value with the
  623.        high 16 bits in the range [0..umax), which is just what we 
  624.        want. */
  625.         return((unsigned)(((long)u*umax)>>16));
  626. }
  627.