home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / internet / scripting / spruuids / game.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-12  |  45.8 KB  |  1,804 lines

  1. //---------------------------------------------------------------------------
  2. // Game.cpp
  3. //---------------------------------------------------------------------------
  4. // Sample spr program
  5. //---------------------------------------------------------------------------
  6. // (C) Copyright 1992-1997 by Microsoft Corporation.  All rights reserved.
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  9. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  10. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  11. // PARTICULAR PURPOSE.
  12. //---------------------------------------------------------------------------
  13.  
  14. #include "Main.h"
  15. #pragma hdrstop
  16. #include "Game.h"
  17. #include "App.h"
  18. #include "Spr.h"
  19. #include "Score.h"
  20. #include "SpruuidP.h"
  21. #include <math.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <stdio.h>
  25.  
  26.  
  27. //---------------------------------------------------------------------------
  28. // DEBUG info
  29. //---------------------------------------------------------------------------
  30. SZTHISFILE
  31.  
  32.  
  33. //---------------------------------------------------------------------------
  34. // Forward Declares
  35. //---------------------------------------------------------------------------
  36. int DisplayScriptError(HINSTANCE hinst, HWND hwndParent, LPCSTR pszError, int ichError);
  37.  
  38.  
  39. //---------------------------------------------------------------------------
  40. // Image data
  41. //---------------------------------------------------------------------------
  42. #define ADDPIX(    id,idNext,x,y,cx,cy) {iimg##idNext, x, y, cx, cy},
  43. #define ADDPIXLAST(id,idNext,x,y,cx,cy) {iimg##idNext, x, y, cx, cy}
  44. #define ADDPIXIMG
  45. IMG Game_img[] = {
  46. #include "SpruuidP.pix"
  47. };
  48. #undef ADDPIX
  49. #undef ADDPIXLAST
  50. #undef ADDPIXIMG
  51.  
  52.  
  53. //---------------------------------------------------------------------------
  54. // Various Globals
  55. //---------------------------------------------------------------------------
  56. CGame     *g_pgame            = NULL;
  57. ITypeLib  *g_ptlGameSubObj    = NULL;
  58. ITypeInfo *g_ptinfoClsGame    = NULL;
  59. ITypeInfo *g_ptinfoIntGame    = NULL;
  60. char      *CGame::s_pszError  = NULL;
  61. ULONG      g_clineOffset;
  62.  
  63.  
  64. //---------------------------------------------------------------------------
  65. // Cover for contstructor.  Use instead of new CGame!
  66. //---------------------------------------------------------------------------
  67. HRESULT CGame::s_hr = E_FAIL;
  68.  
  69. HRESULT CGame::CreateGame
  70. (
  71.   HINSTANCE hinst,
  72.   HWND      hwndDlg,
  73.   HWND      hwndPS,
  74.   HWND      hwndStat,
  75.   IOleComponentManager *pcm,
  76.   CGame   **ppgameOut
  77. )
  78. {
  79.   CGame  *pgame;
  80.   HRESULT hr;
  81.  
  82.   *ppgameOut = NULL;
  83.   pgame = new CGame(hinst, hwndDlg, hwndPS, hwndStat, pcm);
  84.   if (!pgame)
  85.     return E_OUTOFMEMORY;
  86.   else if (pgame->s_hr)
  87.     {
  88.     delete pgame;
  89.     return s_hr;
  90.     }
  91.  
  92. // ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
  93. // Add the Game as a Named Item & load its code
  94.   g_clineOffset = 0;
  95.   hr = pgame->ParseFile(g_pszCodeFile, L"Game");
  96.   if (hr)
  97.     {
  98.     MessageBox(g_papp->m_hwndDlg, s_pszError ? s_pszError : "Unspecified Error", "Spruuids", MB_OK | MB_ICONEXCLAMATION);
  99.     return hr;
  100.     }
  101. // #####  END  ACTIVEX SCRIPTING SUPPORT #####
  102.  
  103.   // Create sprite classes based upon $OBJECT lines in file
  104.   for (int i=0; i<pgame->m_csubobj; i++)
  105.     {
  106.     CHECK(CSpriteClass::Create(pgame->m_pdisp, &pgame->m_rgpsc[i]));
  107.     pgame->m_rgpdispSubObjs[i] = pgame->m_rgpsc[i]->GetDispatch();
  108.     pgame->m_rgpdispSubObjs[i]->AddRef();
  109.     }
  110.  
  111.   if (hr)
  112.     {
  113. CleanUp:
  114.     delete pgame;
  115.     return hr;
  116.     }
  117.  
  118. // ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
  119.   // Start the script running...
  120.   hr = pgame->m_ps->SetScriptState(SCRIPTSTATE_CONNECTED);
  121.   if (hr)
  122.     {
  123.     delete pgame;
  124.     return hr;
  125.     }
  126. // #####  END  ACTIVEX SCRIPTING SUPPORT #####
  127.  
  128.   // Success
  129.   *ppgameOut = pgame;
  130.   return S_OK;
  131. }
  132.  
  133.  
  134. //---------------------------------------------------------------------------
  135. // Constructor
  136. //---------------------------------------------------------------------------
  137. CGame::CGame
  138. (
  139.   HINSTANCE hinst,
  140.   HWND      hwndDlg,
  141.   HWND      hwndPS,
  142.   HWND      hwndStat,
  143.   IOleComponentManager *pcm
  144. )
  145. {
  146.   INIT_SIGNATURE(SIG_Game);
  147.  
  148.   // Setup globals
  149.   g_pgame       = this;
  150.   s_hr          = S_OK;
  151.  
  152.   // Init members
  153.   m_hinst        = hinst;
  154.   m_hwndDlg      = hwndDlg;
  155.   m_hwndPS       = hwndPS;
  156.   m_hwndStat     = hwndStat;
  157.   m_cref         = 1;
  158.   m_fPaused      = FALSE;
  159.   m_fShipDead    = FALSE;
  160.   m_fShipRestart = FALSE;
  161.   m_fGameOver    = TRUE;
  162.   m_pcm          = pcm;
  163.   m_ps           = NULL;
  164.   m_psp          = NULL;
  165.   VariantInit(&m_varTag);
  166.   m_pscore       = NULL;
  167.   m_pdisp        = NULL;
  168.   m_pdispBaseObject = NULL;
  169.   m_pgameoa      = NULL;
  170.   m_csubobj      = 0;
  171.  
  172.   CoCreateGuid(&m_libidSubObj);
  173.   CoCreateGuid(&m_clsidSubObj);
  174.   CoCreateGuid(&m_iidSubObj);
  175.  
  176.   m_pgameoa = new CGameOA(this);
  177.   if (!m_pgameoa)
  178.     {
  179.     s_hr = E_OUTOFMEMORY;
  180.     return;
  181.     }
  182.   this->SetBaseObject(m_pgameoa->GetDispatch());
  183.  
  184.   m_pdisp = new CDisplay(hinst, hwndPS, GetDC(hwndPS),
  185.                          this->GetUnknown(), CGameOA::FireCollide,
  186.                          sizeof(Game_img)/sizeof(IMG), Game_img, ID_BMP_SPRITES);
  187.   if (!m_pdisp)
  188.     {
  189.     s_hr = E_OUTOFMEMORY;
  190.     return;
  191.     }
  192.  
  193.   s_hr = CScore::CreateScore(
  194.                       m_hinst,       // hinst to load resources from
  195.                       m_hwndDlg,     // hwnd on which to draw score
  196.                       m_hwndPS,      // hwnd of PlaySurface
  197.                       m_hwndStat,    // hwnd of Status bar
  198.                       2500,          // scoreFirst1Up
  199.                       5000,          // scoreSecond1Up
  200.                       2500,          // dscoreNext1Up
  201.                       3,             // cshipStart;
  202.                       ID_BMP_SHIP,   // idbmpShip;
  203.                       ID_BMP_PLUS,   // idbmpPlus;
  204.                       &m_pscore);
  205.   if (s_hr)
  206.     return;
  207.   ASSERT(m_pscore, "Good hr, but m_pscore==NULL");
  208.  
  209.   // Default to VBScript
  210.   extern const CLSID CLSID_VBScript;
  211.   m_clsidEngine = CLSID_VBScript;
  212.  
  213.   // Success
  214.   s_hr = S_OK;
  215. }
  216.  
  217.  
  218. //---------------------------------------------------------------------------
  219. // Clean up allocated resources
  220. //---------------------------------------------------------------------------
  221. CGame::~CGame
  222. (
  223.   void
  224. )
  225. {
  226.   CHECK_SIGNATURE(SIG_Game);
  227.   this->Close();
  228.   if (m_pgameoa)
  229.     delete m_pgameoa;
  230.   DESTROY_SIGNATURE(SIG_Game);
  231. }
  232.  
  233.  
  234. //---------------------------------------------------------------------------
  235. // Clean up allocated resources
  236. //---------------------------------------------------------------------------
  237. void CGame::Close
  238. (
  239.   void
  240. )
  241. {
  242.   CHECK_SIGNATURE(SIG_Game);
  243.  
  244.   if (g_mode != MODE_PLAYBACK)
  245.     KillTimer(m_hwndPS, 0);
  246.  
  247.   g_pgame = NULL;
  248.  
  249.   // Clear this, since it may be an object
  250.   VariantClear(&m_varTag);
  251.  
  252. // ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
  253.   // Release the language engine, since it may hold on to us
  254.   if (m_psp)
  255.     m_psp->Release();
  256.   if (m_ps)
  257.     {
  258.     m_ps->Close();
  259.     m_ps->Release();
  260.     }
  261. // #####  END  ACTIVEX SCRIPTING SUPPORT #####
  262.  
  263.   // Drop all sink's that have Advise()'d us, since they might keep us alive
  264.   m_pgameoa->m_cp.Close();
  265.  
  266.   // Release all existing sprites
  267.   if (m_pdisp)
  268.     m_pdisp->DestroyAll();
  269.  
  270.   // Close & Release the SpriteClass Sub Objects
  271.   for (int i=0; i<m_csubobj; i++)
  272.     {
  273.     delete [] m_rgpwszSubObjs[i];
  274.     if (m_rgpdispSubObjs[i])
  275.       {
  276.       m_rgpdispSubObjs[i]->Release();
  277.       m_rgpdispSubObjs[i] = NULL;
  278.       }
  279.     if (m_rgpsc[i])
  280.       {
  281.       m_rgpsc[i]->Close();
  282.       m_rgpsc[i]->Release();
  283.       m_rgpsc[i] = NULL;
  284.       }
  285.     }
  286.  
  287.   // Now destroy the Score & Display objects
  288.   if (m_pscore)
  289.     {
  290.     delete m_pscore;
  291.     m_pscore = NULL;
  292.     }
  293.   if (m_pdisp)
  294.     {
  295.     delete m_pdisp;
  296.     m_pdisp = NULL;
  297.     }
  298. }
  299.  
  300.  
  301. //***************************************************************************
  302. // IUnknown Interface
  303. //***************************************************************************
  304.  
  305. //---------------------------------------------------------------------------
  306. // 
  307. //---------------------------------------------------------------------------
  308. STDMETHODIMP CGame::QueryInterface
  309. (
  310.   REFIID  iid,
  311.   LPVOID* ppvObjOut
  312. )
  313. {
  314.   if (!ppvObjOut)
  315.     return E_INVALIDARG;
  316.  
  317.   *ppvObjOut = NULL;
  318.  
  319.   if (iid == IID_IUnknown)
  320.     *ppvObjOut = this->GetUnknown();
  321.   else if (iid == IID_IDispatch)
  322.     *ppvObjOut = this->GetDispatch();
  323.   else if (iid == IID_IGameSubObjects)
  324.     *ppvObjOut = this->GetDispatch();
  325.   else if (iid == IID_IActiveScriptSite)
  326.     *ppvObjOut = (IActiveScriptSite *)this;
  327.   else if (iid == IID_IActiveScriptSiteWindow)
  328.     *ppvObjOut = (IActiveScriptSiteWindow *)this;
  329.   else if (iid == IID_IProvideClassInfo)
  330.     *ppvObjOut = (IProvideClassInfo *)this;
  331.   else if (iid == IID_IProvideMultipleClassInfo)
  332.     *ppvObjOut = (IProvideMultipleClassInfo *)this;
  333.   else if (iid == IID_IGame)
  334.     *ppvObjOut = (IGame *)(this->m_pgameoa);
  335.   else if (iid == IID_IConnectionPointContainer)
  336.     *ppvObjOut = (IConnectionPointContainer *)(this->m_pgameoa);
  337.  
  338.   if (*ppvObjOut)
  339.     {
  340.     this->AddRef();
  341.     return S_OK;
  342.     }
  343.  
  344.   return E_NOINTERFACE;
  345. }
  346.  
  347.  
  348. //---------------------------------------------------------------------------
  349. // 
  350. //---------------------------------------------------------------------------
  351. STDMETHODIMP_(ULONG) CGame::AddRef
  352. (
  353.   void 
  354. )
  355. {
  356.   return ++m_cref;
  357. }
  358.  
  359.  
  360. //---------------------------------------------------------------------------
  361. // 
  362. //---------------------------------------------------------------------------
  363. STDMETHODIMP_(ULONG) CGame::Release
  364. (
  365.   void 
  366. )
  367. {
  368.   ASSERT(m_cref, "bad m_cref");
  369.   m_cref--;
  370.   if (!m_cref)
  371.     {
  372.     m_pgameoa->m_cp.Close();     // Make sure nobody's holding on to us because we're holding their sink
  373.     if (!m_cref && !m_pgameoa->m_cp.m_cref)
  374.       {
  375.       delete this;
  376.       return 0;
  377.       }
  378.     }
  379.   return m_cref;
  380. }
  381.  
  382.  
  383. //***************************************************************************
  384. // IDispatch Interface
  385. //***************************************************************************
  386.  
  387. //---------------------------------------------------------------------------
  388. // Re-implement COleAuto's GetIDsOfNames(), so we can implement the dynamic
  389. // properties we added for the $OBJECT=SpriteClassName lines.
  390. //---------------------------------------------------------------------------
  391. STDMETHODIMP CGame::GetIDsOfNames
  392. (
  393.   REFIID    iid,
  394.   OLECHAR** rgszNames,
  395.   UINT      cNames,
  396.   LCID      lcid,
  397.   DISPID*   prgdispid
  398. )
  399. {
  400.   // Validate Args
  401.   if (iid != IID_NULL)
  402.       return E_INVALIDARG;
  403.  
  404.   // See if a sub-object matches the name passed in.
  405.   for (int i=0; i<m_csubobj; i++)
  406.     if (!wcscmp(*rgszNames, m_rgpwszSubObjs[i]))
  407.       {
  408.       if (cNames != 1)
  409.         return DISP_E_NONAMEDARGS;
  410.       *prgdispid = 0x80010000 | i;
  411.       return S_OK;
  412.       }
  413.  
  414.   return COleAuto::GetIDsOfNames(iid, rgszNames, cNames, lcid, prgdispid);
  415. }
  416.  
  417.  
  418. //---------------------------------------------------------------------------
  419. // Re-implement COleAuto's Invoke(), so we can implement the dynamic
  420. // properties we added for the $OBJECT=SpriteClassName lines.
  421. //---------------------------------------------------------------------------
  422. STDMETHODIMP CGame::Invoke
  423. (
  424.   DISPID      dispid,
  425.   REFIID      riid,
  426.   LCID        lcid,
  427.   WORD        wFlags,
  428.   DISPPARAMS* pdispparams,
  429.   VARIANT*    pvarResult,
  430.   EXCEPINFO*  pexcepinfo, 
  431.   UINT*       puArgErr)
  432. {
  433.   IDispatch *pdisp = NULL;
  434.  
  435.   // Validate Args
  436.   if (pvarResult)
  437.     VariantInit(pvarResult);
  438.   if (puArgErr)
  439.     *puArgErr = 0;
  440.   SetErrorInfo(0L, NULL);
  441.  
  442.   // If dispid isn't a dynamic property, call COleAuto's dispatch,
  443.   // and it will forward the request on to m_pdispBaseObject.
  444.   if ((dispid & 0x80010000) != 0x80010000)
  445.     return COleAuto::Invoke(dispid, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  446.   // It's for one of our property objects...
  447.  
  448.   // Make sure we have either a PropGet or a Method
  449.   if (!(wFlags & (DISPATCH_METHOD | DISPATCH_PROPERTYGET)))
  450.     return DISP_E_MEMBERNOTFOUND;
  451.  
  452.   dispid &= 0xffff;
  453.   if (dispid >= m_csubobj)
  454.     return DISP_E_MEMBERNOTFOUND;
  455.  
  456.   if (pdispparams->cArgs)
  457.     return DISP_E_BADPARAMCOUNT;
  458.  
  459.   if (pdispparams->cNamedArgs)
  460.     return DISP_E_NONAMEDARGS;
  461.  
  462.   // Get an addref'd IDispatch to the property object
  463.   pdisp = m_rgpdispSubObjs[dispid];
  464.   ASSERT(pdisp, "NULL m_rgpdispSubObjs[]");
  465.  
  466.   if (pvarResult)    
  467.     {
  468.     pvarResult->vt = VT_DISPATCH;
  469.     pvarResult->pdispVal = pdisp;
  470.     pdisp->AddRef();        // We're returning this disp ptr
  471.     }
  472.  
  473.   return S_OK;
  474. }
  475.  
  476.  
  477. //---------------------------------------------------------------------------
  478. // Method needed by COleAuto, so it can implement IDispatch for us.
  479. //---------------------------------------------------------------------------
  480. HRESULT CGame::GetTypeLibInfo
  481. (
  482.   HINSTANCE    *phinstOut,
  483.   const GUID  **pplibidOut, 
  484.   SHORT        *pwMajLib, 
  485.   SHORT        *pwMinLib,
  486.   const CLSID **ppclsidOut, 
  487.   const IID   **ppiidOut, 
  488.   ITypeLib   ***ppptlOut
  489. )
  490. {
  491.   HRESULT hr = this->BuildTypeInfo();
  492.   if (hr)
  493.     return hr;
  494.   *phinstOut  = NULL;
  495.   *pplibidOut = &m_libidSubObj;
  496.   *pwMajLib   = 1;
  497.   *pwMinLib   = 0;
  498.   *ppclsidOut = &m_clsidSubObj;
  499.   *ppiidOut   = &m_iidSubObj;
  500.   *ppptlOut   = &g_ptlGameSubObj;
  501.   return S_OK;
  502. }
  503.  
  504.  
  505. //***************************************************************************
  506. // IProvideClassInfo Interfaces
  507. //***************************************************************************
  508.  
  509. //---------------------------------------------------------------------------
  510. // 
  511. //---------------------------------------------------------------------------
  512. STDMETHODIMP CGame::GetClassInfo
  513. (
  514.   ITypeInfo** pptinfoOut
  515. )
  516. {
  517.   HRESULT hr = ((COleAuto *)this)->CheckTypeInfo(0, 0x0409);
  518.   if (hr)
  519.     return hr;
  520.   *pptinfoOut = g_ptinfoClsGame;
  521.   (*pptinfoOut)->AddRef();
  522.   return S_OK;
  523. }
  524.  
  525.  
  526. //---------------------------------------------------------------------------
  527. // 
  528. //---------------------------------------------------------------------------
  529. STDMETHODIMP CGame::GetGUID
  530. (
  531.   DWORD dwGuidKind,
  532.   GUID* pGUID
  533. )
  534. {
  535.   if (pGUID)
  536.     return E_INVALIDARG;
  537.  
  538.   if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
  539.     return E_INVALIDARG;
  540.  
  541.   *pGUID = DIID_IGameEvents;
  542.   return S_OK;
  543. }
  544.  
  545.  
  546. //---------------------------------------------------------------------------
  547. // 
  548. //---------------------------------------------------------------------------
  549. STDMETHODIMP CGame::GetMultiTypeInfoCount
  550. (
  551.   ULONG *pcti
  552. )
  553. {
  554.   if (!pcti)
  555.     return E_INVALIDARG;
  556.  
  557.   *pcti = 2;
  558.   return S_OK;
  559. }
  560.  
  561.  
  562. //---------------------------------------------------------------------------
  563. // 
  564. //---------------------------------------------------------------------------
  565. STDMETHODIMP CGame::GetInfoOfIndex
  566. (
  567.   ULONG       iti,
  568.   DWORD       dwFlags,
  569.   ITypeInfo** pptiCoClass,
  570.   DWORD*      pdwTIFlags,
  571.   ULONG*      pcdispidReserved,
  572.   IID*        piidPrimary,
  573.   IID*        piidSource
  574. )
  575. {
  576.   HRESULT    hr        = S_OK;
  577.   ITypeInfo *ptinfoOut = NULL;
  578.  
  579.   if (iti > 1)
  580.     hr = E_FAIL;
  581.  
  582. //  if (dwFlags & ~MULTICLASSINFO_ALL)
  583. //    hr = E_INVALIDARG;
  584.  
  585.   if (dwFlags & MULTICLASSINFO_GETTYPEINFO)
  586.     {
  587.     if (!pptiCoClass || !pdwTIFlags)
  588.       hr = E_INVALIDARG;
  589.     else
  590.       {
  591.       *pdwTIFlags  = 0L;
  592.       *pptiCoClass = NULL;
  593.       if (iti == 0)
  594.         {
  595.         hr = ((COleAuto *)this)->CheckTypeInfo(0, 0x0409);
  596.         if (hr)
  597.           return hr;
  598.         ptinfoOut = g_ptinfoClsGame;
  599.         }
  600.       else
  601.         {
  602.         hr = ((COleAuto *)m_pgameoa)->CheckTypeInfo(0, 0x0409);
  603.         if (hr)
  604.           return hr;
  605.         ptinfoOut = g_ptinfoClsGameOA;
  606.         }
  607.       }
  608.     }
  609.  
  610.   if (dwFlags & MULTICLASSINFO_GETNUMRESERVEDDISPIDS)
  611.     {
  612.     if (!pcdispidReserved)
  613.       hr = E_INVALIDARG;
  614.     else
  615.       *pcdispidReserved = 256;
  616.     }
  617.  
  618.   if (dwFlags & MULTICLASSINFO_GETIIDPRIMARY)
  619.     {
  620.     if (!piidPrimary)
  621.       hr = E_INVALIDARG;
  622.     else if (iti == 0)
  623.       *piidPrimary = IID_IGameSubObjects;
  624.     else
  625.       *piidPrimary = IID_IGame;
  626.     }
  627.  
  628.   if (dwFlags & MULTICLASSINFO_GETIIDSOURCE)
  629.     {
  630.     if (!piidSource)
  631.       hr = E_INVALIDARG;
  632.     else if (iti == 0)
  633.       *piidSource = IID_NULL;
  634.     else
  635.       *piidSource = DIID_IGameEvents;
  636.     }
  637.  
  638.   // Fill in ptinfo out param
  639.   if (hr)
  640.     {
  641.     if (pptiCoClass)
  642.       *pptiCoClass = NULL;
  643.     }
  644.   else if (pptiCoClass)
  645.     {
  646.     *pptiCoClass = ptinfoOut;
  647.     (*pptiCoClass)->AddRef();
  648.     }
  649.  
  650.   return hr;
  651. }
  652.  
  653.  
  654.  
  655. // ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
  656. //***************************************************************************
  657. // IActiveScriptSite Interface
  658. //***************************************************************************
  659.  
  660. //---------------------------------------------------------------------------
  661. // 
  662. //---------------------------------------------------------------------------
  663. STDMETHODIMP CGame::GetLCID
  664. (
  665.   LCID *plcid
  666. )
  667. {
  668.   return E_NOTIMPL;     // Use system settings
  669. }
  670.  
  671.  
  672. //---------------------------------------------------------------------------
  673. // 
  674. //---------------------------------------------------------------------------
  675. STDMETHODIMP CGame::GetItemInfo
  676. (
  677.   LPCOLESTR   pstrName,
  678.   DWORD       dwReturnMask,
  679.   IUnknown**  ppunkItemOut,
  680.   ITypeInfo** pptinfoOut
  681. )
  682. {
  683.   HRESULT hr;
  684.  
  685.   if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
  686.     {
  687.     if (!pptinfoOut)
  688.       return E_INVALIDARG;
  689.     *pptinfoOut = NULL;
  690.     }
  691.  
  692.   if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
  693.     {
  694.     if (!ppunkItemOut)
  695.       return E_INVALIDARG;
  696.     *ppunkItemOut = NULL;
  697.     }
  698.  
  699.   if (!_wcsicmp(L"game", pstrName))
  700.     {
  701.     if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
  702.       {
  703.       hr = ((COleAuto *)this)->CheckTypeInfo(0, 0x0409);
  704.       if (hr)
  705.         return hr;
  706.       *pptinfoOut = g_ptinfoClsGame;
  707.       (*pptinfoOut)->AddRef();      // because returning
  708.       }
  709.     if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
  710.       {
  711.       *ppunkItemOut = this->GetUnknown();
  712.       (*ppunkItemOut)->AddRef();    // because returning
  713.       }
  714.     return S_OK;
  715.     }
  716.  
  717.   return TYPE_E_ELEMENTNOTFOUND;
  718. }
  719.  
  720.  
  721. //---------------------------------------------------------------------------
  722. // 
  723. //---------------------------------------------------------------------------
  724. STDMETHODIMP CGame::GetDocVersionString
  725. (
  726.   BSTR *pbstrVersion
  727. )
  728. {
  729.   return E_NOTIMPL;   // UNDONE: Implement this method
  730. }
  731.  
  732.  
  733. //---------------------------------------------------------------------------
  734. // 
  735. //---------------------------------------------------------------------------
  736. STDMETHODIMP CGame::RequestItems
  737. (
  738.   void 
  739. )
  740. {
  741.   return m_ps->AddNamedItem(L"Game", SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
  742. }
  743.  
  744.  
  745. //---------------------------------------------------------------------------
  746. // 
  747. //---------------------------------------------------------------------------
  748. STDMETHODIMP CGame::RequestTypeLibs
  749. (
  750.   void 
  751. )
  752. {
  753.   return m_ps->AddTypeLib(LIBID_SPRUUIDS, 1, 0, 0);
  754. }
  755.  
  756.  
  757. //---------------------------------------------------------------------------
  758. // 
  759. //---------------------------------------------------------------------------
  760. STDMETHODIMP CGame::OnScriptTerminate
  761. (
  762.   const VARIANT   *pvarResult,
  763.   const EXCEPINFO *pexcepinfo
  764. )
  765. {
  766.   // UNDONE: Put up error dlg here
  767.   return S_OK;
  768. }
  769.  
  770.  
  771. //---------------------------------------------------------------------------
  772. // 
  773. //---------------------------------------------------------------------------
  774. STDMETHODIMP CGame::OnStateChange
  775. (
  776.   SCRIPTSTATE ssScriptState
  777. )
  778. {
  779.   // Don't care about notification
  780.   return S_OK;
  781. }
  782.  
  783.  
  784. //---------------------------------------------------------------------------
  785. // Display the error
  786. //---------------------------------------------------------------------------
  787. STDMETHODIMP CGame::OnScriptError
  788. (
  789.   IActiveScriptError *pse
  790. )
  791. {
  792.   char      szError[1024];
  793.   char     *pszArrow = NULL;
  794.   BOOL      fAlloc = FALSE;
  795.   EXCEPINFO ei;
  796.   DWORD     dwSrcContext;
  797.   ULONG     ulLine;
  798.   LONG      ichError;
  799.   BSTR      bstrLine = NULL;
  800.   HRESULT   hr;
  801.  
  802.   CHECK(pse->GetExceptionInfo(&ei));
  803.   CHECK(pse->GetSourcePosition(&dwSrcContext, &ulLine, &ichError));
  804.   ulLine += g_clineOffset;    // Adjust for $ENGINE/$OBJECT/etc. lines
  805.   hr = pse->GetSourceLineText(&bstrLine);
  806.   if (hr)
  807.     hr = S_OK;  // Ignore this error, there may not be source available
  808.   
  809.   if (!hr)
  810.     {
  811.     MAKE_ANSIPTR_FROMWIDE(pszSrc,  ei.bstrSource);
  812.     MAKE_ANSIPTR_FROMWIDE(pszDesc, ei.bstrDescription);
  813.     MAKE_ANSIPTR_FROMWIDE(pszLine, bstrLine);
  814.     if (ichError > 0 && ichError < 255)
  815.       {
  816.       pszArrow = new char[ichError+1];
  817.       memset(pszArrow, '-', ichError);
  818.       pszArrow[ichError-1] = 'v';
  819.       pszArrow[ichError]   = 0;
  820.       fAlloc = TRUE;
  821.       }
  822.     else
  823.       pszArrow = "";
  824.  
  825.     wsprintf(szError, "Source:'%s'\nFile:'%s'  Line:%d  Char:%d\nError:%d  '%s'\n%s\n%s",
  826.                       pszSrc, g_pszCodeFile, ulLine, ichError,
  827.                       (int)ei.wCode, pszDesc, pszArrow, pszLine);
  828.     DisplayScriptError(g_hinst, m_hwndDlg, szError, ichError);
  829.     }
  830.  
  831. CleanUp:
  832.   if (fAlloc)
  833.     delete [] pszArrow;
  834.   if (bstrLine)
  835.     SysFreeString(bstrLine);
  836.  
  837.   return hr;
  838. }
  839.  
  840.  
  841. //---------------------------------------------------------------------------
  842. // 
  843. //---------------------------------------------------------------------------
  844. STDMETHODIMP CGame::OnEnterScript
  845. (
  846.   void 
  847. )
  848. {
  849.   // No need to do anything
  850.   return S_OK;
  851. }
  852.  
  853.  
  854. //---------------------------------------------------------------------------
  855. // 
  856. //---------------------------------------------------------------------------
  857. STDMETHODIMP CGame::OnLeaveScript
  858. (
  859.   void 
  860. )
  861. {
  862.   // No need to do anything
  863.   return S_OK;
  864. }
  865.  
  866.  
  867.  
  868. //***************************************************************************
  869. // IActiveScriptSiteWindow Interface
  870. //***************************************************************************
  871.  
  872. //---------------------------------------------------------------------------
  873. // 
  874. //---------------------------------------------------------------------------
  875. STDMETHODIMP CGame::GetWindow
  876. (
  877.   HWND *phwndOut
  878. )
  879. {
  880.   if (!phwndOut)
  881.     return E_INVALIDARG;
  882.   *phwndOut = m_hwndDlg;
  883.   return S_OK;
  884. }
  885.  
  886.  
  887. //---------------------------------------------------------------------------
  888. // 
  889. //---------------------------------------------------------------------------
  890. STDMETHODIMP CGame::EnableModeless
  891. (
  892.   BOOL fEnable
  893. )
  894. {
  895.   if (fEnable)
  896.     m_pcm->FOnComponentExitState(g_papp->m_idcomp, cmgrstateModal, cmgrcontextAll, 0, NULL);
  897.   else
  898.     m_pcm->OnComponentEnterState(g_papp->m_idcomp, cmgrstateModal, cmgrcontextAll, 0, NULL, NULL);
  899.   return S_OK;
  900. }
  901. // #####  END  ACTIVEX SCRIPTING SUPPORT #####
  902.  
  903.  
  904. //***************************************************************************
  905. // Misc WndProc-related Methods
  906. //***************************************************************************
  907.  
  908. //---------------------------------------------------------------------------
  909. //
  910. //---------------------------------------------------------------------------
  911. BOOL AppEvt_DlgProc
  912. (
  913.   HWND   hwnd,
  914.   UINT   msg,
  915.   WPARAM wp,
  916.   LPARAM lp
  917. )
  918. {
  919.   if (!g_pgame)
  920.     return FALSE;
  921.  
  922.   return g_pgame->DlgProc(hwnd, msg, wp, lp);
  923. }
  924.  
  925.  
  926. //---------------------------------------------------------------------------
  927. //
  928. //---------------------------------------------------------------------------
  929. BOOL CGame::DlgProc
  930. (
  931.   HWND   hwnd,
  932.   UINT   msg,
  933.   WPARAM wp,
  934.   LPARAM lp
  935. )
  936. {
  937.   switch (msg)
  938.     {
  939.     case WM_ERASEBKGND:
  940.       if (m_pscore)
  941.         {
  942.         m_pscore->Paint((HDC)wp);
  943.         return TRUE;
  944.         }
  945.       break;
  946.     }
  947.   return FALSE;
  948. }
  949.  
  950.  
  951. //---------------------------------------------------------------------------
  952. //
  953. //---------------------------------------------------------------------------
  954. LRESULT AppEvt_PSWndProc
  955. (
  956.   HWND   hwnd,
  957.   UINT   msg,
  958.   WPARAM wp,
  959.   LPARAM lp
  960. )
  961. {
  962.   if (!g_pgame)
  963.     return DefWindowProc(hwnd, msg, wp, lp);
  964.  
  965.   return g_pgame->PSWndProc(hwnd, msg, wp, lp);
  966. }
  967.  
  968.  
  969. //---------------------------------------------------------------------------
  970. //
  971. //---------------------------------------------------------------------------
  972. LRESULT CGame::PSWndProc
  973. (
  974.   HWND   hwnd,
  975.   UINT   msg,
  976.   WPARAM wp,
  977.   LPARAM lp
  978. )
  979. {
  980.   switch (msg)
  981.     {
  982.     case WM_PAINT:
  983.       if (m_pdisp)
  984.         {
  985.         if (wp)
  986.           m_pdisp->Paint((HDC)wp);
  987.         else
  988.           {
  989.           PAINTSTRUCT ps;
  990.  
  991.           BeginPaint(hwnd, &ps);
  992.           m_pdisp->Paint(ps.hdc);
  993.           EndPaint(hwnd, &ps);
  994.           }
  995.         return 1L;
  996.         }
  997.       break;
  998.  
  999.     case WM_ERASEBKGND:
  1000.       SelectObject((HDC)wp, (HGDIOBJ)(m_pdisp->m_hbrushBack ? (HBRUSH)(m_pdisp->m_hbrushBack) : (HBRUSH)g_hbrushStock));
  1001.       PatBlt((HDC)wp, 0, 0, 32000, 32000, PATCOPY);
  1002.       SelectObject((HDC)wp, g_hbrushStock);
  1003.       return TRUE;
  1004.  
  1005.     case WM_SIZE:
  1006.       {
  1007.       RECT rect;
  1008.  
  1009.       GetClientRect(hwnd, &rect);
  1010.       m_pdisp->m_cx = rect.right;
  1011.       m_pdisp->m_cy = rect.bottom;
  1012.       break;
  1013.       }
  1014.  
  1015.     case WM_TIMER:
  1016.       {
  1017.       if (m_fGameOver)
  1018.         break;
  1019.  
  1020.       m_pdisp->Timer();
  1021.  
  1022.       if (m_fPaused)
  1023.         break;
  1024.  
  1025.       if (m_fShipRestart)
  1026.         {
  1027.         m_pdisp->Refresh();
  1028.         break;
  1029.         }
  1030.  
  1031.       if (!m_fShipDead)
  1032.         {
  1033.         static cRefresh = 0;
  1034.  
  1035.         m_pgameoa->FireTick();
  1036.         if (++cRefresh > 5)          // What's a reasonable number?
  1037.           {
  1038.           m_pdisp->Refresh();
  1039.           cRefresh = 0;
  1040.           }
  1041.         }
  1042.       else
  1043.         {
  1044.         m_pscore->ShipKilled();
  1045.         InvalidateRect(m_hwndDlg, NULL, TRUE);
  1046.         if (m_pscore->GetCShip() <= 0)
  1047.           {
  1048.           this->GameOver();
  1049.           break;
  1050.           }
  1051.  
  1052.         m_fShipDead = FALSE;
  1053.         m_fShipRestart = TRUE;
  1054.         InvalidateRect(hwnd, NULL, TRUE);
  1055.         }
  1056.       break;
  1057.       }
  1058.  
  1059.     case WM_KEYDOWN:
  1060.       m_pgameoa->FireKeyDown(wp);
  1061.       break;
  1062.  
  1063.     case WM_CHAR:
  1064.       m_pgameoa->FireKeyPress(wp);
  1065.       break;
  1066.  
  1067.     case WM_KEYUP:
  1068.       m_pgameoa->FireKeyUp(wp);
  1069.       break;
  1070.  
  1071.     case WM_MOUSEMOVE:
  1072.       m_pgameoa->FireMouseMove(LOWORD(lp), HIWORD(lp), wp);
  1073.       break;
  1074.  
  1075.     case WM_LBUTTONDOWN:
  1076.       m_pgameoa->FireMouseDown(LOWORD(lp), HIWORD(lp), wp, MK_LBUTTON);
  1077.       break;
  1078.  
  1079.     case WM_RBUTTONDOWN:
  1080.       m_pgameoa->FireMouseDown(LOWORD(lp), HIWORD(lp), wp, MK_RBUTTON);
  1081.       break;
  1082.  
  1083.     case WM_MBUTTONDOWN:
  1084.       m_pgameoa->FireMouseDown(LOWORD(lp), HIWORD(lp), wp, MK_MBUTTON);
  1085.       break;
  1086.  
  1087.     case WM_LBUTTONUP:
  1088.       m_pgameoa->FireMouseUp(LOWORD(lp), HIWORD(lp), wp, MK_LBUTTON);
  1089.       break;
  1090.  
  1091.     case WM_RBUTTONUP:
  1092.       m_pgameoa->FireMouseUp(LOWORD(lp), HIWORD(lp), wp, MK_RBUTTON);
  1093.       break;
  1094.  
  1095.     case WM_MBUTTONUP:
  1096.       m_pgameoa->FireMouseUp(LOWORD(lp), HIWORD(lp), wp, MK_MBUTTON);
  1097.       break;
  1098.     }
  1099.  
  1100.   return DefWindowProc(hwnd, msg, wp, lp);
  1101. }
  1102.  
  1103.  
  1104. //---------------------------------------------------------------------------
  1105. //
  1106. //---------------------------------------------------------------------------
  1107. LRESULT CALLBACK ScriptErrorDialog
  1108. (
  1109.   HWND   hwnd,
  1110.   UINT   msg,
  1111.   WPARAM wp,
  1112.   LPARAM lp
  1113. )
  1114. {
  1115.   LPCSTR pszError;
  1116.  
  1117.   switch (msg) 
  1118.     {
  1119.     case WM_INITDIALOG:
  1120.       pszError = (LPCSTR)lp;
  1121.       ShowWindow(hwnd, SW_HIDE);
  1122.       SendDlgItemMessage(hwnd, ID_CTL_ERROR, WM_SETFONT,
  1123.                          (WPARAM)GetStockObject(ANSI_FIXED_FONT), MAKELPARAM(FALSE,0));
  1124.       SendDlgItemMessage(hwnd, ID_CTL_ERROR, WM_SETTEXT, 0, (LPARAM)pszError);
  1125.       ShowWindow(hwnd, SW_SHOW);
  1126.       return (TRUE);
  1127.  
  1128.      case WM_COMMAND:
  1129.        switch(LOWORD(wp))
  1130.          {
  1131.          case IDOK:
  1132.          case IDCANCEL:
  1133.            goto Destroy;
  1134.          }
  1135.        break;
  1136.     }
  1137.   return FALSE;
  1138.  
  1139. Destroy:
  1140.   EndDialog(hwnd, 0);
  1141.   return TRUE;
  1142. }
  1143.  
  1144.  
  1145. //---------------------------------------------------------------------------
  1146. //
  1147. //---------------------------------------------------------------------------
  1148. int DisplayScriptError
  1149. (
  1150.   HINSTANCE hinst,
  1151.   HWND      hwndParent,
  1152.   LPCSTR    pszError,
  1153.   int       ichError
  1154. )
  1155. {
  1156.   int   result;
  1157.   UINT  len = lstrlen(pszError);
  1158.   UINT  newlen;
  1159.   UINT  newindex;
  1160.   UINT  i;
  1161.   LPSTR pszNewError;
  1162.  
  1163.   // Figure out how long the real string will be
  1164.   newlen = 0;
  1165.   for (i=0; i<len; i++)
  1166.     {
  1167.     CHAR c = pszError[i];
  1168.  
  1169.     if (c == '\n')
  1170.       newlen +=1;               // Convert \n to \r\n
  1171.     else if (c == '\r')
  1172.       {
  1173.       if (pszError[i+1] == '\n')
  1174.         {
  1175.         newlen++;               // Leave \r\n alone
  1176.         i++;
  1177.         }
  1178.       else
  1179.         newlen++;               // Convert \r to \r\n
  1180.       }
  1181.     newlen++;
  1182.     }
  1183.  
  1184.   // Create the real string:
  1185.   pszNewError = new char[newlen+1];
  1186.   if (!pszNewError)
  1187.     return -1;
  1188.  
  1189.   newindex = 0;
  1190.   for (i=0; i<len; i++)
  1191.     {
  1192.     CHAR c = pszError[i];
  1193.  
  1194.     if (c == '\n')
  1195.       pszNewError[newindex++] = '\r';             // Convert \n to \r\n
  1196.     else if (c == '\r')
  1197.       {
  1198.       if (pszError[i+1] == '\n')
  1199.         {
  1200.         pszNewError[newindex++] = pszError[i++];  // Leave \r\n alone
  1201.         i++;
  1202.         }
  1203.       else
  1204.         {
  1205.         pszNewError[newindex++] = c;              // Convert \r to \r\n
  1206.         c = '\n';
  1207.         }
  1208.       }
  1209.     pszNewError[newindex++] = c;
  1210.     }
  1211.   pszNewError[newindex] = '\0';
  1212.  
  1213.   // Create the dialog box
  1214.   g_pgame->m_pcm->OnComponentEnterState(g_papp->m_idcomp, cmgrstateModal, cmgrcontextAll, 0, NULL, NULL);
  1215.   g_pgame->Pause(1);
  1216.   result = DialogBoxParam(
  1217.       hinst,                         // Handle to application instance
  1218.       MAKEINTRESOURCE(ID_DLG_ERROR), // Identifies dialog box template name  
  1219.       hwndParent,                    // Handle to owner window
  1220.       (DLGPROC)ScriptErrorDialog,    // Pointer to dialog box procedure
  1221.       (DWORD)pszNewError);           // Context
  1222.   g_pgame->m_pcm->FOnComponentExitState(g_papp->m_idcomp, cmgrstateModal, cmgrcontextAll, 0, NULL);
  1223.   SetFocus(g_pgame->m_hwndPS);
  1224.  
  1225.   delete[] pszNewError;
  1226.  
  1227.   return result;
  1228. }
  1229.  
  1230.  
  1231. //***************************************************************************
  1232. // Misc General Methods
  1233. //***************************************************************************
  1234.  
  1235. //---------------------------------------------------------------------------
  1236. // New level
  1237. //---------------------------------------------------------------------------
  1238. void CGame::NewLevel
  1239. (
  1240.   void
  1241. )
  1242. {
  1243.   g_pgame->m_pdisp->DestroyAll();
  1244.   m_pscore->NextLevel();
  1245.   m_fShipRestart = TRUE;
  1246.   InvalidateRect(m_hwndPS,  NULL, TRUE);
  1247.   InvalidateRect(m_hwndDlg, NULL, TRUE);
  1248.   m_pgameoa->FireNewLevel();
  1249. }
  1250.  
  1251.  
  1252. //---------------------------------------------------------------------------
  1253. //
  1254. //---------------------------------------------------------------------------
  1255. void AppEvt_NewGame
  1256. (
  1257.   void
  1258. )
  1259. {
  1260.   g_pgame->NewGame();
  1261. }
  1262.  
  1263.  
  1264. //---------------------------------------------------------------------------
  1265. //
  1266. //---------------------------------------------------------------------------
  1267. void CGame::NewGame
  1268. (
  1269.   void
  1270. )
  1271. {
  1272.   m_pdisp->DestroyAll();
  1273.   m_pscore->NewGame();
  1274.   m_fGameOver    = FALSE;
  1275.   m_fShipRestart = TRUE;
  1276.   m_pgameoa->FireNewGame();
  1277. }
  1278.  
  1279.  
  1280. //---------------------------------------------------------------------------
  1281. //
  1282. //---------------------------------------------------------------------------
  1283. BOOL AppEvt_Pause
  1284. (
  1285.   int pause
  1286. )
  1287. {
  1288.   return g_pgame->Pause(pause);
  1289. }
  1290.  
  1291.  
  1292. //---------------------------------------------------------------------------
  1293. //
  1294. //---------------------------------------------------------------------------
  1295. BOOL CGame::Pause
  1296. (
  1297.   int pause
  1298. )
  1299. {
  1300.   if (pause == -1)            // Toggle
  1301.     pause = !m_fPaused;
  1302.  
  1303.   switch (pause)
  1304.     {
  1305.     case 1:                   // Pause
  1306.       if (m_fGameOver)
  1307.         goto UnPause;
  1308.       if (g_mode != MODE_PLAYBACK)
  1309.         KillTimer(m_hwndPS, 0);
  1310.       m_fPaused = TRUE;
  1311.       break;
  1312.  
  1313.     case 0:                   // UnPause
  1314. UnPause:
  1315.       if (g_mode != MODE_PLAYBACK)
  1316.         SetTimer(m_hwndPS, 0, 40, NULL);
  1317.       m_fPaused = FALSE;
  1318.       break;
  1319.     }
  1320.  
  1321.   if (m_fPaused)
  1322.     m_pscore->SetStatusText("Game Paused.  Press F3 to Continue.");
  1323.   else
  1324.     m_pscore->SetStatusText("");
  1325.  
  1326.   return m_fPaused;
  1327. }
  1328.  
  1329.  
  1330. //---------------------------------------------------------------------------
  1331. //
  1332. //---------------------------------------------------------------------------
  1333. BOOL AppEvt_FQueryTerminate
  1334. (
  1335.   BOOL fPromptUser
  1336. )
  1337. {
  1338.   return g_pgame->FQueryTerminate(fPromptUser);
  1339. }
  1340.  
  1341.  
  1342. //---------------------------------------------------------------------------
  1343. //
  1344. //---------------------------------------------------------------------------
  1345. BOOL CGame::FQueryTerminate
  1346. (
  1347.   BOOL fPromptUser
  1348. )
  1349. {
  1350.   // UNDONE
  1351.   return TRUE;
  1352. }
  1353.  
  1354.  
  1355. //---------------------------------------------------------------------------
  1356. //
  1357. //---------------------------------------------------------------------------
  1358. void CGame::GameOver
  1359. (
  1360.   void
  1361. )
  1362. {
  1363.   m_fGameOver = TRUE;
  1364.   InvalidateRect(m_hwndPS, NULL, TRUE);
  1365.   m_pscore->SetStatusText("Game Over.  Press F2 to Play a New Game.");
  1366. }
  1367.  
  1368.  
  1369. // ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
  1370. //---------------------------------------------------------------------------
  1371. //
  1372. //---------------------------------------------------------------------------
  1373. HRESULT CGame::CreateScriptEngine
  1374. (
  1375.   LPCOLESTR pstrItemName
  1376. )
  1377. {
  1378.   HRESULT hr;
  1379.  
  1380.   if (m_ps)
  1381.     return S_FALSE;   // Already created it
  1382.  
  1383.   // Create the ActiveX Scripting Engine
  1384.   hr = CoCreateInstance(m_clsidEngine, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void **)&m_ps);
  1385.   if (hr)
  1386.     {
  1387.     s_pszError = "Creating the ActiveX Scripting engine failed.  Scripting engine is probably not correctly registered or CLSID incorrect.";
  1388.     return E_FAIL;
  1389.     }
  1390.   // Script Engine must support IActiveScriptParse for us to use it
  1391.   hr = m_ps->QueryInterface(IID_IActiveScriptParse, (void **)&m_psp);
  1392.   if (hr)
  1393.     {
  1394.     s_pszError = "ActiveX Scripting engine does not support IActiveScriptParse";
  1395.     return hr;
  1396.     }
  1397.   hr = m_ps->SetScriptSite(this);
  1398.   if (hr)
  1399.     return hr;
  1400.   // InitNew the object:
  1401.   hr = m_psp->InitNew();
  1402.   if (hr)
  1403.     return hr;
  1404.   hr = m_ps->AddNamedItem(L"Game", SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
  1405.   return hr;
  1406. }
  1407. // #####  END  ACTIVEX SCRIPTING SUPPORT #####
  1408.  
  1409.  
  1410.  
  1411. //***************************************************************************
  1412. // Parsing support
  1413. //***************************************************************************
  1414.  
  1415. //---------------------------------------------------------------------------
  1416. // Skip white space, counting lines.  Treat \r & \n as white space only if
  1417. // fSkipNewLines is TRUE.
  1418. //---------------------------------------------------------------------------
  1419. void SkipWhite
  1420. (
  1421.   char **ppsz,
  1422.   BOOL   fSkipNewLines
  1423. )
  1424. {
  1425.   // Skip white space
  1426.   while (**ppsz && **ppsz<=' ')
  1427.     {
  1428.     if (**ppsz == '\r' || **ppsz == '\n')
  1429.       {
  1430.       if (!fSkipNewLines)
  1431.         return;
  1432.       if (**ppsz == '\r' && (*ppsz)[1] == '\n')
  1433.         ++*ppsz;
  1434.       g_clineOffset++;
  1435.       }
  1436.     ++*ppsz;
  1437.     }
  1438. }
  1439.  
  1440.  
  1441. //---------------------------------------------------------------------------
  1442. // Finds $OBJECT, $ENGINE, $INCLUDE, etc, parses past '=' to argument.  NULL
  1443. // terminates the argument, then returns a ptr to begining of arg & to beg
  1444. // of next line.
  1445. //---------------------------------------------------------------------------
  1446. struct
  1447.   {
  1448.   int   cch;
  1449.   char *psz;
  1450.   } g_rgtoken[] = 
  1451.     {
  1452.       {7, "$ENGINE"},
  1453.       {7, "$OBJECT"},
  1454.       {8, "$INCLUDE"},
  1455.       {0, ""},
  1456.     };
  1457.  
  1458. int FindToken
  1459. (
  1460.   char    *pszCur,
  1461.   char   **ppszBeginArg,
  1462.   char   **ppszNextLine,
  1463.   HRESULT *phr,
  1464.   char   **ppszError
  1465. )
  1466. {
  1467.   char chQuote = 0;
  1468.   char ch;
  1469.  
  1470.   *phr = S_OK;
  1471.   SkipWhite(&pszCur, TRUE);
  1472.   if (*pszCur != '$')
  1473.     {
  1474.     *ppszNextLine = pszCur;
  1475.     return 0;   // No token found
  1476.     }
  1477.  
  1478.   for (int i=0; g_rgtoken[i].cch; i++)
  1479.     {
  1480.     if (!strncmp(pszCur, g_rgtoken[i].psz, g_rgtoken[i].cch))
  1481.       {
  1482.       pszCur += g_rgtoken[i].cch;
  1483.       SkipWhite(&pszCur, FALSE);
  1484.       if (*pszCur != '=')
  1485.         {
  1486.         *ppszError = "Missing '=' on $ENGINE, $OBJECT, or $INCLUDE line";
  1487.         *phr = E_FAIL;
  1488.         return 0;
  1489.         }
  1490.       pszCur++;
  1491.       SkipWhite(&pszCur, FALSE);
  1492.       if (*pszCur <= ' ')
  1493.         {
  1494.         *ppszError = "Missing argument on $ENGINE, $OBJECT, or $INCLUDE line";
  1495.         *phr = E_FAIL;
  1496.         return 0;
  1497.         }
  1498.       if (*pszCur=='"' || *pszCur=='\'' || *pszCur=='<')
  1499.         {
  1500.         chQuote = *pszCur;
  1501.         if (chQuote == '<')
  1502.           chQuote = '>';
  1503.         pszCur++;
  1504.         }
  1505.       *ppszBeginArg = pszCur;
  1506.       if (chQuote)
  1507.         {
  1508.         // Look for End of String, EOL, or End of Quote
  1509.         while (*pszCur && *pszCur!='\n' && *pszCur!='\r' && *pszCur!=chQuote)
  1510.           pszCur++;
  1511.         }
  1512.       else
  1513.         {
  1514.         // Skip non-white space
  1515.         while (*pszCur > ' ')
  1516.           pszCur++;
  1517.         }
  1518.       ch = *pszCur;
  1519.       *pszCur = 0;
  1520. NextChar:
  1521.       switch (ch)
  1522.         {
  1523.         default:
  1524.           // Look for EOL
  1525.           pszCur++;
  1526.           ch = *pszCur;
  1527.           goto NextChar;
  1528.  
  1529.         case '\r':
  1530.           // Skip the cr we're at
  1531.           g_clineOffset++;
  1532.           pszCur++;
  1533.           if (*pszCur == '\n')
  1534.             pszCur++;
  1535.           break;
  1536.  
  1537.         case '\n':
  1538.           // Skip the newline we're at
  1539.           g_clineOffset++;
  1540.           pszCur++;
  1541.           break;
  1542.  
  1543.         case 0:
  1544.            break;
  1545.         }
  1546.  
  1547.       *ppszNextLine = pszCur;
  1548.       return i+1;
  1549.       }
  1550.     }
  1551.  
  1552.   *ppszError = "unrecognized token; must be $ENGINE, $OBJECT, or $INCLUDE";
  1553.   *phr = E_FAIL;
  1554.   return 0;
  1555. }
  1556.  
  1557.  
  1558. //---------------------------------------------------------------------------
  1559. //
  1560. //---------------------------------------------------------------------------
  1561. HRESULT CGame::ParseFile
  1562. (
  1563.   char     *pszFileName,
  1564.   LPCOLESTR pstrItemName
  1565. )
  1566. {
  1567.   struct _stat stat;
  1568.   size_t       cch;
  1569.   EXCEPINFO    ei;
  1570.   char        *pszT;
  1571.   char        *pszAlloc;
  1572.   FILE        *pfile;
  1573.   HRESULT      hr = S_OK;
  1574.   int          tk = 0;
  1575.   char        *pszArg;
  1576.  
  1577.   // Find the length of the file
  1578.   if (_stat(pszFileName, &stat))
  1579.     return E_FAIL;
  1580.   cch = stat.st_size;
  1581.  
  1582.   // Allocate a buffer to read the file
  1583.   pszAlloc = new char[cch+1];
  1584.   if (!pszAlloc)
  1585.     return E_OUTOFMEMORY;
  1586.   memset(pszAlloc, 0, cch);   // HACK: Since cch may be too large, zero-fill string
  1587.  
  1588.   // Open & read the file
  1589.   pfile = fopen(pszFileName, "rb");
  1590.   if (!pfile)
  1591.     {
  1592.     s_pszError = "Bad file name";
  1593.     hr = E_FAIL;
  1594.     goto Error;
  1595.     }
  1596.   fread(pszAlloc, cch, 1, pfile);
  1597.   fclose(pfile);
  1598.  
  1599.   // Parse lines begining w/$
  1600.   pszAlloc[cch] = 0;
  1601.   pszT = pszAlloc;
  1602.   while (tk=FindToken(pszT, &pszArg, &pszT, &hr, &s_pszError))
  1603.     {
  1604.     switch (tk)
  1605.       {
  1606.       case 1:   // $ENGINE
  1607.         {
  1608.         MAKE_WIDEPTR_FROMANSI(pwszCLSID, pszArg);
  1609.         hr = CLSIDFromString(pwszCLSID, &m_clsidEngine);
  1610.         if (hr)
  1611.           {
  1612.           s_pszError = "Bad $ENGINE={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} syntax";
  1613.           goto Error;
  1614.           }
  1615.         hr = this->CreateScriptEngine(pstrItemName);
  1616.         if (hr == S_FALSE)
  1617.           {
  1618.           s_pszError = "$ENGINE must be first line; Script Engine already created.";
  1619.           goto Error;
  1620.           }
  1621.         else if (hr)
  1622.           goto Error;
  1623.         break;
  1624.         }
  1625.  
  1626.       case 2:  // $OBJECT
  1627.         if (m_csubobj >= csubobjMAX)
  1628.           {
  1629.           s_pszError = "Too many $OBJECT lines";
  1630.           goto Error;
  1631.           }
  1632.  
  1633.         m_rgpwszSubObjs[m_csubobj] = new WCHAR [strlen(pszArg)+1];
  1634.         if (!m_rgpwszSubObjs[m_csubobj])
  1635.           {
  1636.           s_pszError = "Out Of Memory";
  1637.           goto Error;
  1638.           }
  1639.         UNICODE_FROM_ANSI(m_rgpwszSubObjs[m_csubobj], pszArg, 2*strlen(pszArg));
  1640.         m_rgpdispSubObjs[m_csubobj] = NULL;
  1641.         m_rgpsc[m_csubobj] = NULL;
  1642.         m_csubobj++;
  1643.         break;
  1644.  
  1645.       case 3:   // $INCLUDE
  1646.         hr = this->ParseFile(pszArg, pstrItemName);
  1647.         if (hr)
  1648.           goto Error;
  1649.         break;
  1650.       }
  1651.     }
  1652.  
  1653.   // If there's anything left, assume it's code
  1654.   if (*pszT)
  1655.     {
  1656. // ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
  1657.     // Make sure we've created the scripting engine
  1658.     if (!m_ps)
  1659.       {
  1660.       hr = this->CreateScriptEngine(pstrItemName);
  1661.       if (hr)
  1662.         goto Error;
  1663.       }
  1664.  
  1665.     // Hand it the code
  1666.     MAKE_WIDEPTR_FROMANSI(pwszCode, pszT);
  1667.     hr = m_psp->ParseScriptText(pwszCode, pstrItemName, NULL, NULL, 0, 0, 0L, NULL, &ei);
  1668.     hr = S_OK;    // Ignore parse errors, so user can press F9 to view source...
  1669. // #####  END  ACTIVEX SCRIPTING SUPPORT #####
  1670.     }
  1671.  
  1672. Error:
  1673.   delete [] pszAlloc;
  1674.   return hr;
  1675. }
  1676.  
  1677.  
  1678.  
  1679. //***************************************************************************
  1680. // Dynamic object model support
  1681. //***************************************************************************
  1682.  
  1683. //---------------------------------------------------------------------------
  1684. // Builds the typeinfo for the container object from the list of property 
  1685. // objects.
  1686. //---------------------------------------------------------------------------
  1687. HRESULT CGame::BuildTypeInfo
  1688. (
  1689.   void
  1690. )
  1691. {
  1692.   static GUID guidStdOle = {0x00020430,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46};
  1693.   ITypeLib*        ptlStdOle   = NULL;
  1694.   ITypeInfo*       ptinfoIDisp = NULL;
  1695.   ICreateTypeLib * pcreatetl   = NULL;
  1696.   ICreateTypeInfo* pctiCoClass = NULL;        // For creating the CoClass
  1697.   ICreateTypeInfo* pctiProps   = NULL;        // For creating the Primary (Property) Dispinterface
  1698.   FUNCDESC         funcdesc    = {0};
  1699.   TYPEDESC         tdescUser   = {0};
  1700.   ELEMDESC         edArg       = {0};
  1701.   HREFTYPE         hreftype;
  1702.   int              index;
  1703.   int              i;
  1704.   HRESULT          hr;
  1705.  
  1706.   if (g_ptinfoIntGame && g_ptinfoClsGame)
  1707.     return S_OK;
  1708.  
  1709.   // Create TypeLib
  1710.   CHECKSZ(CreateTypeLib(SYS_WIN32, L"c:\\SprdSubO.tlb" /* szFile */, &pcreatetl), "CreateTypeLib FAILED");
  1711.  
  1712.   // Misc. global props of the TypeLib
  1713.   CHECKSZ(pcreatetl->SetGuid(m_libidSubObj), "TL SetGuid FAILED");
  1714.   CHECKSZ(pcreatetl->SetVersion(1, 0), "TL SetVersion FAILED");
  1715.   CHECKSZ(pcreatetl->SetName(L"Sprds"), "TL SetName FAILED");
  1716.   CHECKSZ(pcreatetl->SetLcid(LOCALE_SYSTEM_DEFAULT), "TL SetLcid FAILED");
  1717.  
  1718.   // Get Information on IDispatch
  1719.   CHECKSZ(LoadRegTypeLib(guidStdOle, STDOLE_MAJORVERNUM, STDOLE_MINORVERNUM, STDOLE_LCID, &ptlStdOle), "LoadRegTypeLib FAILED");
  1720.   CHECKSZ(ptlStdOle->GetTypeInfoOfGuid(IID_IDispatch, &ptinfoIDisp), "GetTypeInfoOfGuid (IID_IDispatch) FAILED");
  1721.  
  1722.   // Create TypeInfo
  1723.   CHECKSZ(pcreatetl->CreateTypeInfo(L"GameSubObjs", TKIND_DISPATCH, &pctiProps), "Create TI FAILED");
  1724.   CHECKSZ(pctiProps->SetGuid(m_iidSubObj), "cti SetGuid FAILED");
  1725.   CHECKSZ(pctiProps->SetVersion(1, 0), "cti SetVersion FAILED");
  1726.   CHECKSZ(pctiProps->AddRefTypeInfo(ptinfoIDisp, &hreftype), "cti AddRefTypeInfoo FAILED");     // Reference StdOLE
  1727.   CHECKSZ(pctiProps->AddImplType(0, hreftype), "cti AddImplType FAILED");
  1728.  
  1729.   funcdesc.funckind = FUNC_DISPATCH;
  1730.   funcdesc.invkind  = INVOKE_PROPERTYGET;
  1731.   funcdesc.callconv = CC_STDCALL;
  1732.   funcdesc.cScodes  = -1;
  1733.   funcdesc.elemdescFunc.tdesc.vt = VT_PTR;
  1734.   funcdesc.elemdescFunc.tdesc.lptdesc = &tdescUser;
  1735.   tdescUser.vt = VT_USERDEFINED;
  1736.  
  1737.   // Loop through all of the SpriteClasses ($OBJECTs) in this game, adding a
  1738.   // property to pctiProps which corresponds to the control.
  1739.   index = 0;
  1740.   for (i=0; i<m_csubobj; i++)
  1741.     {
  1742.     // Need to make sure this starts out cleared
  1743.     if (!g_ptinfoClsSpriteClass)
  1744.       {
  1745.       CHECKCL(LoadTypeInfo(g_hinst, 0, 1, 0, 0x0409,
  1746.                            LIBID_SPRUUIDS, CLSID_SpriteClass, IID_ISpriteClass, FALSE,
  1747.                            &g_ptlMain, &g_ptinfoClsSpriteClass, &g_ptinfoIntSpriteClass));
  1748.       }
  1749.     CHECKCL(pctiProps->AddRefTypeInfo(g_ptinfoClsSpriteClass, &tdescUser.hreftype));
  1750.     funcdesc.memid = 0x80010000 | i;
  1751.     funcdesc.wFuncFlags = FUNCFLAG_FSOURCE;
  1752.  
  1753.     CHECKCL(pctiProps->AddFuncDesc(index, &funcdesc));
  1754.     CHECKCL(pctiProps->SetFuncAndParamNames(index, &m_rgpwszSubObjs[i], 1));
  1755.  
  1756.     index++;
  1757.     continue;
  1758.  
  1759. CheckLoop:
  1760.     // Do any clean up here
  1761.  
  1762.     CHECKSZ(hr,"BuildTypeInfo FAILED");
  1763.     break;
  1764.     }
  1765.  
  1766.   // Finish off the TI for the Props
  1767.   CHECKSZ(pctiProps->LayOut(), "BuildTypeInfo FAILED");
  1768.   CHECKSZ(pctiProps->QueryInterface(IID_ITypeInfo, (void **)&g_ptinfoIntGame), "BuildTypeInfo FAILED");
  1769.  
  1770.   // Now we have to create a coclass for the interface
  1771.   CHECKSZ(pcreatetl->CreateTypeInfo(L"Game", TKIND_COCLASS, &pctiCoClass), "BuildTypeInfo FAILED");
  1772.   CHECKSZ(pctiCoClass->SetGuid(m_clsidSubObj), "BuildTypeInfo FAILED");
  1773.   CHECKSZ(pctiCoClass->SetVersion(1, 0), "BuildTypeInfo FAILED");
  1774.  
  1775.   // Add the Page Property dispinterface to coclass
  1776.   CHECKSZ(pctiCoClass->AddRefTypeInfo(g_ptinfoIntGame, &hreftype), "BuildTypeInfo FAILED");
  1777.   CHECKSZ(pctiCoClass->AddImplType(0, hreftype), "BuildTypeInfo FAILED");
  1778.   CHECKSZ(pctiCoClass->SetImplTypeFlags(0, IMPLTYPEFLAG_FDEFAULT), "BuildTypeInfo FAILED");
  1779.  
  1780.   // Finish off the CoClass
  1781.   CHECKSZ(pctiCoClass->LayOut(), "BuildTypeInfo FAILED");
  1782.   CHECKSZ(pctiCoClass->QueryInterface(IID_ITypeInfo, (void **)&g_ptinfoClsGame), "BuildTypeInfo FAILED");
  1783.  
  1784.   // Finish off the Library
  1785.   CHECKSZ(pcreatetl->QueryInterface(IID_ITypeLib, (void **)&g_ptlGameSubObj), "BuildTypeLib FAILED");
  1786.  
  1787. CleanUp:
  1788.   // Code to release refs aquired during page build.
  1789.   if (pctiCoClass)
  1790.     pctiCoClass->Release();
  1791.   if (pctiProps)
  1792.     pctiProps->Release();
  1793.   if (ptinfoIDisp)
  1794.     ptinfoIDisp->Release();
  1795.   if (ptlStdOle)
  1796.     ptlStdOle->Release();
  1797.   if (pcreatetl)
  1798.     pcreatetl->Release();
  1799.  
  1800.   return hr;
  1801. };
  1802.  
  1803. //--- EOF -------------------------------------------------------------------
  1804.