2005/5/9

     
 

ActiveScript.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdkx_com/src/acdkx/com/ActiveScript.cpp,v 1.8 2005/02/05 10:45:38 kommer Exp $


#include "ActiveScript.h"
#include "CoException.h"
#include "AcdkObject.h"

#include <acdk/cfgscript/Props.h>

//#include <ACTIVSCP.H>
//#include <comcat.h>
/*
class CActiveScriptSite :   public IActiveScriptSite,
                             public IActiveScriptSiteWindow {
     LONG m_cRef;
     IDispatch *m_pdispshell;
 public:
     CActiveScriptSite(IDispatch *pshell) 
         : m_cRef(0), m_pdispshell(pshell)     {
         if (m_pdispshell)
             m_pdispshell->AddRef();
     }
 
     ~CActiveScriptSite(void) {
         if (m_pdispshell)
             m_pdispshell->Release();
     }
 
 // IUnknown methods
     STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
         if (riid == IID_IUnknown||riid == IID_IActiveScriptSite)
             *ppv = (IActiveScriptSite*)this;
         else if (riid == IID_IActiveScriptSiteWindow)
             *ppv = (IActiveScriptSiteWindow*)this;
         else 
             return (*ppv = 0), E_OUTOFMEMORY;
         ((IUnknown*)*ppv)->AddRef();
         return S_OK;
     }
     
     STDMETHODIMP_(ULONG) AddRef()
     { return InterlockedIncrement(&m_cRef); }
 
     STDMETHODIMP_(ULONG) Release() {
         if (InterlockedDecrement(&m_cRef))
             return m_cRef;
         delete this;
         return 0;
     }
 
 // IActiveScriptSite methods
     STDMETHODIMP GetItemInfo(LPCOLESTR pstrName, DWORD dwReturnMask,
                              IUnknown **ppiunkItem, ITypeInfo **ppti) {
         HRESULT hr = E_FAIL;
         if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
             *ppiunkItem = 0;
         if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
             *ppti = 0;
 // see if top-level name is "shell"
         if (wcscmp(pstrName, OLESTR("shell")) == 0) {
             if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
                 if (*ppiunkItem = m_pdispshell)
                 {
                     (*ppiunkItem)->AddRef();
                     hr = S_OK;
                 }
             
             if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
                 hr = LoadTypeInfoFromThisModule(CLSID_CHostShell, ppti);
 
         }
         return hr;
     }
     
     STDMETHODIMP OnScriptError(IActiveScriptError *pscripterror) {
         DWORD dwCookie;
         LONG nChar;
         ULONG nLine;
         BSTR bstr = 0;
         EXCEPINFO ei; ZeroMemory(&ei, sizeof(ei));
         pscripterror->GetSourcePosition(&dwCookie, &nLine, &nChar);
         pscripterror->GetSourceLineText(&bstr);
         pscripterror->GetExceptionInfo(&ei);
         
         OLECHAR wszOutput[1024];
         swprintf(wszOutput, OLESTR("%s\n[Line: %d] %s\n%s"),
                   ei.bstrSource, nLine, ei.bstrDescription,
                   bstr ? bstr : OLESTR(""));
 
         SysFreeString(bstr);
         SysFreeString(ei.bstrSource);
         SysFreeString(ei.bstrDescription);
         SysFreeString(ei.bstrHelpFile);
         MessageBoxW(GetDesktopWindow(),
                     wszOutput,
                     L"Error",
                     MB_SETFOREGROUND);
 
         return S_OK;
     }
     
     STDMETHODIMP GetLCID(LCID *plcid)
     { *plcid = 9; return S_OK; }
     
     STDMETHODIMP GetDocVersionString(BSTR *pbstrVersion) 
     { *pbstrVersion = SysAllocString(L""); return S_OK; }
     
     STDMETHODIMP OnScriptTerminate(const VARIANT *pvr, const EXCEPINFO *pei)
     { return S_OK; }
     
     STDMETHODIMP OnStateChange(SCRIPTSTATE ssScriptState)
     { return S_OK; }
     
     STDMETHODIMP OnEnterScript(void)
     { return S_OK; }
     
     STDMETHODIMP OnLeaveScript(void) 
     { return S_OK; }
 
 // IActiveScriptSiteWindow methods    
     STDMETHODIMP GetWindow(HWND *phwnd)
     { *phwnd = GetDesktopWindow(); return S_OK; }
 
     STDMETHODIMP EnableModeless(BOOL)
     { return S_OK; }
 };

*/


namespace acdkx {
namespace com {

#if defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
IActiveScriptParse* getScript(IN(RString) language)
{
#if defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
  IActiveScriptParse *ppas = 0;
  RString wlanguage = language->convert(CCUcs2);
  OLECHAR* wszProgID = (OLECHAR*)S2OLE(wlanguage);
  CLSID clsid;
  HRESULT hr = CLSIDFromProgID(wszProgID, &clsid);
  if (SUCCEEDED(hr))
  {
     hr = CoCreateInstance(clsid, 0, CLSCTX_ALL,
                          IID_IActiveScriptParse,
                           (void**)&ppas);
     if (SUCCEEDED(hr))
       return ppas;
  }
  THROW2(CoException, hr, "getScript");
#else
/FONT>
  THROW1(CoException, "ActiveScript not supported");
#endif
/FONT>
  return 0;
}


class ActiveScriptSite
: extends acdkx::com::IUnknown
, implements ::IActiveScriptSite
, implements ::IActiveScriptSiteWindow
  
{
  typedef acdkx::com::IUnknown Super;
  
public:
  acdk::cfgscript::RProps _globals;
  ActiveScriptSite()
    : _globals(new acdk::cfgscript::Props())
  {
  }
  virtual ULONG STDMETHODCALLTYPE AddRef() { return Super::AddRef(); }
  virtual ULONG STDMETHODCALLTYPE Release() { return Super::Release(); }
  virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void** ppvObject)
  {
    if (riid == IID_IUnknown)
    {
      *ppvObject = (IUnknown*)this;
    }
    else if (riid == IID_IActiveScriptSite)
    {
      *ppvObject = (IActiveScriptSite*)this;
    }
    else if (riid == IID_IActiveScriptSiteWindow)
    {
      *ppvObject = (IActiveScriptSiteWindow*)this;
    }
    else
    {
      *ppvObject = 0;
      return E_NOINTERFACE;
    }
    addRef();
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE GetLCID(LCID __RPC_FAR *plcid)
  {
    return E_NOTIMPL;
  }
  virtual HRESULT STDMETHODCALLTYPE GetItemInfo( 
            LPCOLESTR pstrName,
            DWORD dwReturnMask,
            ::IUnknown __RPC_FAR *__RPC_FAR *ppiunkItem,
            ::ITypeInfo __RPC_FAR *__RPC_FAR *ppti)
  {
    if (ppiunkItem == 0)
      return E_INVALIDARG;
    *ppiunkItem = 0;
    if (ppti != 0)
      *ppti = 0;
    int _clength;
    RString key = OLE2S(pstrName);
    ::acdk::lang::dmi::RDmiObject obj = _globals->get(key);
    if (obj == Nil)
      return TYPE_E_ELEMENTNOTFOUND;
    RAcdkObject acobj = new AcdkObject(obj->getObjectVar());
    acobj->QueryInterface(IID_IUnknown, (void**)ppiunkItem);
    return S_OK;

    //
  }
  virtual HRESULT STDMETHODCALLTYPE GetDocVersionString(BSTR __RPC_FAR *pbstrVersion)
  {
    return E_NOTIMPL;
  }
  virtual HRESULT STDMETHODCALLTYPE OnScriptTerminate(const VARIANT __RPC_FAR *pvarResult, const EXCEPINFO __RPC_FAR *pexcepinfo)
  {
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE OnStateChange(SCRIPTSTATE ssScriptState)
  {
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE OnScriptError(IActiveScriptError __RPC_FAR *pscripterror)
  {
    DWORD sourceContext = 0;
    ULONG lineNumber = 0;
    LONG charPosition = 0;
    pscripterror->GetSourcePosition(&sourceContext, &lineNumber, &charPosition);
    StringBuffer sb("");
    sb.append((int)lineNumber);
    sb.append(":");
    sb.append((int)charPosition);
    BSTR bstr = 0;
    sb.append(":");
    pscripterror->GetSourceLineText(&bstr);
    int _clength;
    if (bstr)
    {
      sb.append(OLE2S(bstr));
      SysFreeString(bstr);
    }
    sb.append(": ");

    EXCEPINFO exInfo;
    memset(&exInfo, 0, sizeof(exInfo));
    pscripterror->GetExceptionInfo(&exInfo);
    if (exInfo.pfnDeferredFillIn != 0)
        exInfo.pfnDeferredFillIn(&exInfo);
    if (exInfo.bstrDescription)
      sb.append(W2CS(exInfo.bstrDescription));
    SysFreeString(exInfo.bstrSource);
    SysFreeString(exInfo.bstrDescription);
    SysFreeString(exInfo.bstrHelpFile);
    THROW1(Exception, sb.toString());
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE OnEnterScript()
  {
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE OnLeaveScript()
  {
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd)
  {
    *phwnd = GetDesktopWindow();
    return S_OK;
  }
  virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable)
  {
    return S_OK;
  }
};

#endif //defined(ACDKX_ORB_WITH_ACTIVESCRIPT)

ActiveScript::ActiveScript(IN(RString) language)
#if defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
: _interface(getScript(language))
, _activeScriptSide(new ActiveScriptSite())
{
  HRESULT hr = _interface->InitNew();
  if (FAILED(hr))
    THROW2(CoException, hr, "InitNew");
  IHolder<IActiveScript> as = iface_cast<IActiveScript>(_interface);
  as->SetScriptSite(&_activeScriptSide);
  as->SetScriptState(SCRIPTSTATE_STARTED);
#else
/FONT>
{
#endif //defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
}

void checkInvokeResult(HRESULT hr, EXCEPINFO& exInfo, UINT argErr);
void 
ActiveScript::parseEval(IN(RString) code)
{
#if defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
  //DisplayEngines();
  EXCEPINFO excepinfo;
  memset(&excepinfo, 0, sizeof(excepinfo));
  RString wcode = code->convert(CCUcs2);
  checkInvokeResult(_interface->ParseScriptText(S2OLE(wcode), NULL, NULL, NULL, 0, 0, SCRIPTTEXT_ISVISIBLE, NULL, &excepinfo), excepinfo, 0);
#endif //defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
}


void 
ActiveScript::setVar(IN(RString) name, IN(acdk::lang::Object) obj)
{
#if defined(ACDKX_ORB_WITH_ACTIVESCRIPT)
  _activeScriptSide->_globals->setObjectVal(name, obj);
  IHolder<IActiveScript> as = iface_cast<IActiveScript>(_interface);
  RString wname = name->convert(CCUcs2);
  HRESULT hr = as->AddNamedItem(S2OLE(wname), SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);
  if (FAILED(hr))
    THROW2(CoException, hr, "ActiveScript::setVar");
#endif //defined(ACDKX_ORB_WITH_ACTIVESCRIPT)

}

} // namespace com 
} // namespace acdkx