The IDebugDocumentHelper Interface interface greatly simplifies the task of creating a smart host for Active Debugging, because it provides implementations for many interfaces necessary for smart hosting.
To be a smart host using IDebugDocumentHelper, a host application must do only three things:
CoCreate the Process Debug Manager, and use the IProcessDebugManager Interface interface to add your application to the list of debuggable applications.
Create a debug document helper for each script object, using the IProcessDebugManager::CreateDebugDocumentHelper method. Make sure that the document name, parent document, text, and script blocks are defined.
Implement the IActiveScriptSiteDebug Interface interface on your object that implements the IActiveScriptSite interface (which is needed for Active Scripting). The only non-trivial method on the IActiveScriptSiteDebug interface simply delegates to the helper.
Optionally, the host can implement the IDebugDocumentHost Interface interface if it needs additional control over syntax color, document context creation, and other extended functionality.
The main limitation on the smart host helper is that it can only handle documents whose contents change or shrink after they have been added (although documents can expand). For many smart hosts, however, the functionality it provides is exactly what is needed.
The following sections explain each step in more detail.
Before the smart host helper can be used, it is necessary to create an IDebugApplication Interface object to represent your application in the debugger.
To create an application object
Create an instance of the process debug manager using CoCreateInstance.
Set the name on the application by using IDebugApplication::SetName.
Add the application object to the list of debuggable applications by using IProcessDebugManager::AddApplication.
The code below outlines the process, but it does not include error checking or other robust programming techniques.
CoCreateInstance(CLSID_ProcessDebugManager, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER, IID_IProcessDebugManager, (void **)&g_ppdm); g_ppdm->CreateApplication(&g_pda); g_pda->SetName(L"My cool application"); g_ppdm->AddApplication(g_pda, &g_dwAppCookie);
To use the helper (minimal sequence of steps)
For each host document, create a helper using IProcessDebugManager::CreateDebugDocumentHelper.
Call IDebugDocumentHelper::Init on the helper, giving the name, document attributes, and so on.
Call IDebugDocumentHelper::Attach with parent helper for the document (or NULL if the document is the root) to define the position of the document in the tree and make it visible to the debugger.
Call IDebugDocumentHelper::AddDBCSText or IDebugDocumentHelper::AddUnicodeText to define the text of the document. (These can be called multiple times if document is downloaded incrementally, as in the case of a browser.)
Call IDebugDocumentHelper::DefineScriptBlock to define the ranges for each script block and the associated script engines.
To implement IActiveScriptSiteDebug::GetDocumentContextFromPosition, get the helper corresponding to the given site, and then get the starting document offset for the given source context, as follows:
pddh->GetScriptBlockInfo(dwSourceContext, NULL, &ulStartPos, NULL);
Next, use the helper to create a new document context for the given character offset:
pddh->CreateDebugDocumentContext(ulStartPos + uCharacterOffset, cChars, &pddcNew);
To implement IActiveScriptSiteDebug::GetRootApplicationNode, simply call IDebugApplication::GetRootNode (inherited from IRemoteDebugApplication::GetRootNode).
To implement IDebugDocumentHelper::GetDebugApplicationNode, simply return the IDebugApplication you initially created using the process debug manager.
The host can provide an implementation of the IDebugDocumentHost Interface by using IDebugDocumentHelper::SetDebugDocumentHost to give it additional control over the helper. Here are some of the key things the host interface allows you to do:
Add text using IDebugDocumentHelper::AddDeferredText so that the host does not need to provide the actual characters immediately. When the characters are really needed, the helper will call IDebugDocumentHost::GetDeferredText on the host.
Override the default syntax coloring provided by the helper. The helper calls IDebugDocumentHost::GetScriptTextAttributes to determine the coloring for a range of characters, falling back on its default implementation if the host return E_NOTIMPL.
Provide a controlling unknown for document contexts created by the helper by implementing IDebugDocumentHost::OnCreateDocumentContext. This allows the host to override the functionality of the default document context implementation.
Provide a path name in the file system for the document. Some debugging UIs use this to permit the user to edit and save changes to the document. IDebugDocumentHost::NotifyChanged is called to notify the host after the document has been saved.