HRESULT TestMarkupServices(BSTR bstrHtml, MarkupCallback *pCallback, BSTR &message) { IHTMLDocument3 *pHtmlDocRoot = NULL; // Create the root document -- a "workspace" for parsing. HRESULT hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pHtmlDocRoot)); if (SUCCEEDED(hr) && pHtmlDocRoot) { IPersistStreamInit *pPersistStreamInit = NULL; hr = pHtmlDocRoot->QueryInterface(IID_PPV_ARGS(&pPersistStreamInit)); if (SUCCEEDED(hr)) { // Initialize the root document to a default state -- ready for parsing. pPersistStreamInit->InitNew(); IMarkupServices *pMarkupServices = NULL; hr = pHtmlDocRoot->QueryInterface(IID_PPV_ARGS(&pMarkupServices)); if (SUCCEEDED(hr)) { IMarkupPointer *pMarkupBegin = NULL; IMarkupPointer *pMarkupEnd = NULL; // These markup pointers indicate the insertion point. hr = pMarkupServices->CreateMarkupPointer(&pMarkupBegin); if (SUCCEEDED(hr)) hr = pMarkupServices->CreateMarkupPointer(&pMarkupEnd); if (SUCCEEDED(hr) && pMarkupBegin && pMarkupEnd) { IMarkupContainer *pMarkupContainer = NULL; // Parse the string -- the markup container contains the parsed HTML. // Markup pointers are updated to point to begining and end of new container. hr = pMarkupServices->ParseString(bstrHtml, 0, &pMarkupContainer, pMarkupBegin, pMarkupEnd); if (SUCCEEDED(hr) && pMarkupContainer) { IHTMLDocument3 *pHtmlDoc = NULL; // Retrieve the document interface to the markup container. hr = pMarkupContainer->QueryInterface(IID_PPV_ARGS(&pHtmlDoc)); if (SUCCEEDED(hr) && pHtmlDoc) { // Invoke the user-defined action for this new fragment. hr = pCallback(pHtmlDoc, message); // Clean up. pHtmlDoc->Release(); } pMarkupContainer->Release(); } pMarkupEnd->Release(); } if (pMarkupBegin) pMarkupBegin->Release(); pMarkupServices->Release(); } pPersistStreamInit->Release(); } pHtmlDocRoot->Release(); } return hr; }
void CHtmlCaretTestView::OnMovetoend() { IHTMLDocument2 *pHTMLDocument2; if(!GetDHtmlDocument(&pHTMLDocument2))return; IDisplayServices *pDisplayServices; HRESULT hRes = pHTMLDocument2->QueryInterface(IID_IDisplayServices, reinterpret_cast<void**>(&pDisplayServices)); if (FAILED(hRes)) return; IDisplayPointer *pDisplayPointer; hRes = pDisplayServices->CreateDisplayPointer(&pDisplayPointer); if (FAILED(hRes)) return; IMarkupServices *pMarkupServices; hRes = pDisplayServices->QueryInterface(IID_IMarkupServices, reinterpret_cast<void**>(&pMarkupServices)); if (FAILED(hRes)) return; IMarkupPointer *pMarkupPointer; hRes = pMarkupServices->CreateMarkupPointer(&pMarkupPointer); if (FAILED(hRes)) return; IHTMLElement *pElement; pHTMLDocument2->get_body(&pElement); hRes = pMarkupPointer->MoveAdjacentToElement(pElement, ELEM_ADJ_BeforeEnd); if (FAILED(hRes)) return; hRes = pDisplayPointer->MoveToMarkupPointer(pMarkupPointer, NULL); if (FAILED(hRes)) return; IHTMLCaret *pHTMLCaret; hRes = pDisplayServices->GetCaret(&pHTMLCaret); if (FAILED(hRes)) return; hRes = pHTMLCaret->MoveCaretToPointerEx(pDisplayPointer, TRUE, TRUE, CARET_DIRECTION_FORWARD); if (FAILED(hRes)) return; }
HRESULT CCopyCommand::PrivateExec(DWORD nCmdexecopt, VARIANTARG* pvarargIn, VARIANTARG* pvarargOut) { HRESULT hr = S_OK; INT iSegmentCount; ISegmentList* pSegmentList = NULL; SELECTION_TYPE eSelectionType; IMarkupPointer* pStart = NULL; IMarkupPointer* pEnd = NULL; CXindowsEditor* pEditor = GetEditor(); IHTMLElement* pElement = NULL; BOOL fRet; IMarkupServices* pMarkupServices = GetMarkupServices(); // Do the prep work ((IHTMLEditor*)pEditor)->AddRef(); IFC(GetSegmentList(&pSegmentList)); IFC(pSegmentList->GetSegmentCount(&iSegmentCount, &eSelectionType)); // If there is no segments we're done, it's a nogo if(iSegmentCount == 0) { goto Cleanup; } // Fire the canceable event IFC(pMarkupServices->CreateMarkupPointer(&pStart)); IFC(pMarkupServices->CreateMarkupPointer(&pEnd)); IFC(MovePointersToSegmentHelper(GetViewServices(), pSegmentList, 0, &pStart, &pEnd)); IFC(FindCommonElement(pMarkupServices, GetViewServices(), pStart, pEnd, &pElement)); hr = GetViewServices()->FireCancelableEvent( pElement, DISPID_EVMETH_ONCOPY, DISPID_EVPROP_ONCOPY, _T("copy"), &fRet); if(hr) { goto Cleanup; } if(!fRet) { goto Cleanup; } // Do the actual copy IFC(GetViewServices()->SaveSegmentsToClipboard(pSegmentList)); Cleanup: ReleaseInterface(pElement); ReleaseInterface((IHTMLEditor*)pEditor); ReleaseInterface(pSegmentList); ReleaseInterface(pStart); ReleaseInterface(pEnd); RRETURN(hr); }
HRESULT CPasteCommand::PasteFromClipboard ( IMarkupPointer* pPasteStart, IMarkupPointer* pPasteEnd, IDataObject* pDataObject, CSpringLoader* psl) { CXindowsEditor* pEditor = GetEditor(); IDataObject* pdoFromClipboard = NULL; CLIPFORMAT cf = 0; HGLOBAL hglobal = NULL; HRESULT hr = DV_E_FORMATETC; HRESULT hr2 = S_OK; HGLOBAL hUnicode = NULL; int i; int nFETC; STGMEDIUM medium = { 0, NULL }; FORMATETC* pfetc; LPTSTR ptext = NULL; IHTMLViewServices* pViewServices = pEditor->GetViewServices(); IHTMLElement* pElement = NULL; IHTMLElement* pFlowElement = NULL; BOOL fAcceptsHTML, fContainer; IMarkupServices* pMarkupServices = pEditor->GetMarkupServices(); IMarkupPointer* pRangeStart = NULL; IMarkupPointer* pRangeEnd = NULL; IDataObject* pdoFiltered = NULL; IDocHostUIHandler* pHostUIHandler = NULL; // Set up a pair of pointers for URL Autodetection after the insert IFC(pMarkupServices->CreateMarkupPointer(&pRangeStart)); IFC(pRangeStart->MoveToPointer(pPasteStart)); IFC(pRangeStart->SetGravity(POINTER_GRAVITY_Left)); IFC(pMarkupServices->CreateMarkupPointer(&pRangeEnd)); IFC(pRangeEnd->MoveToPointer(pPasteStart)); IFC(pRangeEnd->SetGravity(POINTER_GRAVITY_Right)); pfetc = GetFETCs(&nFETC); Assert(pfetc); if(!pDataObject) { hr2 = OleGetClipboard(&pdoFromClipboard); if(hr2 != NOERROR) { return hr2; } Assert(pdoFromClipboard); // See if the host handler wants to give us a massaged data object. IFC(pViewServices->GetDocHostUIHandler(&pHostUIHandler)); pDataObject = pdoFromClipboard; if(pHostUIHandler) { // The host may want to massage the data object to block/add // certain formats. hr = pHostUIHandler->FilterDataObject(pDataObject, &pdoFiltered); if(!hr && pdoFiltered) { pDataObject = pdoFiltered; } else { hr = S_OK; } } } if(pPasteEnd) { IFC(pMarkupServices->Remove(pPasteStart, pPasteEnd)); } // Check if we accept HTML IFC(pViewServices->GetFlowElement(pPasteStart, &pFlowElement)); if(!pFlowElement) { // Elements that do not accept HTML, e.g. TextArea, always have a flow layout. // If the element does not have a flow layout then it might have been created // using the DOM (see bug 42685). Set fAcceptsHTML to true. fAcceptsHTML = TRUE; } else { IFC(pViewServices->IsContainerElement(pFlowElement, &fContainer, &fAcceptsHTML)); } for(i=0; i<nFETC; i++,pfetc++) { // make sure the format is either 1.) a plain text format // if we are in plain text mode or 2.) a rich text format // or 3.) matches the requested format. if(cf && cf!=pfetc->cfFormat) { continue; } // If we don't accept HTML and i does not correspond to text format // skip it if(fAcceptsHTML || i==iAnsiFETC || i==iUnicodeFETC) { // make sure the format is available if(pDataObject->QueryGetData(pfetc) != NOERROR) { continue; } // If we have one of the formats that uses an hglobal get it // and lock it. if(i==iAnsiFETC || i==iUnicodeFETC || i==iHTML) { if(pDataObject->GetData(pfetc, &medium) == NOERROR) { Assert(medium.tymed == TYMED_HGLOBAL); hglobal = medium.hGlobal; ptext = (LPTSTR)GlobalLock(hglobal); if(!ptext) { ReleaseStgMedium(&medium); return E_OUTOFMEMORY; } } else { continue; } } switch(i) { case iHTML: { // Fire the springloader. BOOL fSamePosition = FALSE; if(pPasteStart && psl && (!pPasteEnd || (S_OK==pPasteStart->IsEqualTo(pPasteEnd, &fSamePosition) && fSamePosition)) && S_OK==psl->Fire(pPasteStart) && pPasteEnd) { pPasteEnd->MoveToPointer(pPasteStart); } hr = pViewServices->DoTheDarnPasteHTML(pPasteStart, pPasteEnd, hglobal); goto Cleanup; } case iRtfFETC: { BOOL fEnabled = FALSE; continue; } case iRtfAsTextFETC: case iAnsiFETC: // ANSI plain text. If data can be stored hUnicode = TextHGlobalAtoW(hglobal); if(hUnicode) { ptext = (LPTSTR)GlobalLock(hUnicode); if(!ptext) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = GetEditor()->InsertSanitizedText(ptext, pPasteStart, pMarkupServices, psl, FALSE); GlobalUnlock(hUnicode); } goto Cleanup; case iUnicodeFETC: // Unicode plain text ptext = (LPTSTR)GlobalLock(hglobal); if(!ptext) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = GetEditor()->InsertSanitizedText(ptext, pPasteStart, pMarkupServices, psl, FALSE); goto Cleanup; } //Break out of the for loop break; } } Cleanup: ReleaseInterface(pRangeStart); ReleaseInterface(pRangeEnd); ReleaseInterface(pElement); ReleaseInterface(pFlowElement); ReleaseInterface(pdoFiltered); ReleaseInterface(pHostUIHandler); ReleaseInterface(pdoFromClipboard); if(hUnicode) { GlobalFree(hUnicode); } //If we used the hglobal unlock it and free it. if(hglobal) { GlobalUnlock(hglobal); ReleaseStgMedium(&medium); } return hr; }
//+--------------------------------------------------------------------------- // // CPasteCommand::Exec // //---------------------------------------------------------------------------- HRESULT CPasteCommand::PrivateExec(DWORD nCmdexecopt, VARIANTARG* pvarargIn, VARIANTARG* pvarargOut) { HRESULT hr = S_OK; int iSegmentCount, i; IMarkupPointer* pStart = NULL; IMarkupPointer* pEnd = NULL; SELECTION_TYPE eSelectionType; IHTMLViewServices* pViewServices = GetViewServices(); IMarkupServices* pMarkupServices = GetMarkupServices(); ISegmentList* pSegmentList = NULL; BOOL fRet; DWORD code = 0; CXindowsEditor* pEditor = GetEditor(); CUndoUnit undoUnit(pEditor); ((IHTMLEditor*)pEditor)->AddRef(); if(IsSelectionActive()) { return S_OK; // don't paste into an active selection } // Get the segment etc., let's get busy IFC(GetSegmentList(&pSegmentList)); IFC(pSegmentList->GetSegmentCount(&iSegmentCount, &eSelectionType)); IFC(pMarkupServices->CreateMarkupPointer(&pStart)); IFC(pMarkupServices->CreateMarkupPointer(&pEnd)); if(iSegmentCount != 0) { SP_IHTMLElement spElement; /*IFC(undoUnit.Begin(IDS_EDUNDOPASTE)); wlw note*/ for(i=0; i<iSegmentCount; i++) { IFC(MovePointersToSegmentHelper(GetViewServices(), pSegmentList, i, &pStart, &pEnd)); IFC(IsPastePossible(pStart, pEnd, &fRet)); if(!fRet) { continue; } IFC(FindCommonElement(pMarkupServices, GetViewServices(), pStart, pEnd, &spElement)); if(!spElement) { continue; } IFC(pViewServices->FireCancelableEvent(spElement, DISPID_EVMETH_ONPASTE, DISPID_EVPROP_ONPASTE, _T("paste"), &fRet)); if(!fRet) { continue; } if(pvarargIn && V_VT(pvarargIn)==VT_BSTR) { // Paste the passed in bstrText IFC(Paste(pStart, pEnd, GetSpringLoader(), V_BSTR(pvarargIn))); } else { // Paste from the clipboard IFC(PasteFromClipboard(pStart, pEnd, NULL, GetSpringLoader())); } } if((eSelectionType!=SELECTION_TYPE_Auto) && (eSelectionType!=SELECTION_TYPE_Control)) // Control is handled in ExitTree { pEditor->GetSelectionManager()->EmptySelection(); } if(eSelectionType != SELECTION_TYPE_Auto) { // Update selection - go to pStart since it has gravity Right pEnd->MoveToPointer(pStart); pEditor->Select(pStart, pEnd, SELECTION_TYPE_Caret, &code); Assert(code == 0); } } Cleanup: ReleaseInterface((IHTMLEditor*)pEditor); ReleaseInterface(pSegmentList); ReleaseInterface(pStart); ReleaseInterface(pEnd); RRETURN (hr); }
//+--------------------------------------------------------------------------- // // CCutCommand::Exec // //---------------------------------------------------------------------------- HRESULT CCutCommand::PrivateExec(DWORD nCmdexecopt, VARIANTARG* pvarargIn, VARIANTARG* pvarargOut) { HRESULT hr = S_OK; IHTMLElement* pElement = NULL; int iSegmentCount; IMarkupPointer* pStart = NULL; IMarkupPointer* pEnd = NULL; SELECTION_TYPE eSelectionType; IMarkupServices* pMarkupServices = GetMarkupServices(); ISegmentList* pSegmentList = NULL; BOOL fRet; BOOL fNotRange = TRUE; CUndoUnit undoUnit(GetEditor()); CXindowsEditor* pEditor = GetEditor(); ((IHTMLEditor*)pEditor)->AddRef(); // Do the prep work IFC(GetSegmentList(&pSegmentList)); IFC(pSegmentList->GetSegmentCount(&iSegmentCount, &eSelectionType)); // Cut is allowed iff we have a non-empty segment if(eSelectionType==SELECTION_TYPE_Caret || iSegmentCount==0) { goto Cleanup; } IFC(pMarkupServices->CreateMarkupPointer(&pStart)); IFC(pMarkupServices->CreateMarkupPointer(&pEnd)); IFC(MovePointersToSegmentHelper(GetViewServices(), pSegmentList, 0, &pStart, &pEnd)); IFC(pStart->IsEqualTo(pEnd, &fRet)); if(fRet) { goto Cleanup; } // Cannot delete or cut unless the range is in the same flow layout if(!PointersInSameFlowLayout(pStart, pEnd, NULL, GetViewServices())) { goto Cleanup; } // Now Handle the cut /*IFC(undoUnit.Begin(IDS_EDUNDOCUT)); wlw note*/ IFC(FindCommonElement(pMarkupServices, GetViewServices(), pStart, pEnd, &pElement)); if(!pElement) { goto Cleanup; } IFC(GetViewServices()->FireCancelableEvent( pElement, DISPID_EVMETH_ONCUT, DISPID_EVPROP_ONCUT, _T("cut"), &fRet)); if(!fRet) { goto Cleanup; } IFC(GetViewServices()->SaveSegmentsToClipboard(pSegmentList)); fNotRange = (eSelectionType!=SELECTION_TYPE_Auto && eSelectionType!=SELECTION_TYPE_Control); IFC(pEditor->Delete(pStart, pEnd, fNotRange)); if(eSelectionType == SELECTION_TYPE_Selection) { pEditor->GetSelectionManager()->EmptySelection(); } Cleanup: ReleaseInterface((IHTMLEditor*)pEditor); ReleaseInterface(pSegmentList); ReleaseInterface(pStart); ReleaseInterface(pEnd); ReleaseInterface(pElement); RRETURN(hr); }