|
|
/*
* @doc INTERNAL * * @module object.cpp IRichEditOle implementation | * * Author: alexgo 8/15/95 * * Copyright (c) 1995-2000, Microsoft Corporation. All rights reserved. */
#include "_common.h"
#include "_edit.h"
#include "_objmgr.h"
#include "_coleobj.h"
#include "_rtext.h"
#include "_select.h"
#include "_m_undo.h"
#include "_disp.h"
// IUnknown is implemented elsewhere
/*
* CTxtEdit::GetClientSite (lplpolesite) * * @mfunc returns the client site */ STDMETHODIMP CTxtEdit::GetClientSite( LPOLECLIENTSITE FAR * lplpolesite) //@parm where to return
//the client site
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetClientSite");
if(!lplpolesite) return E_INVALIDARG;
COleObject *pobj = new COleObject(this); // should start with a ref count of 1.
if(pobj) { *lplpolesite = (IOleClientSite *)pobj; return NOERROR; } *lplpolesite = NULL; return E_OUTOFMEMORY; }
/*
* CTxtEdit::GetObjectCount * * @mfunc return the number of objects in this edit instance */ STDMETHODIMP_(LONG) CTxtEdit::GetObjectCount() { TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetObjectCount"); return _pobjmgr ? _pobjmgr->GetObjectCount() : 0; }
/*
* CTxtEdit::GetLinkCount * * @mfunc return the number of likns in this edit instance */ STDMETHODIMP_(LONG) CTxtEdit::GetLinkCount() { TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetLinkCount");
CObjectMgr *pobjmgr = GetObjectMgr(); return pobjmgr ? pobjmgr->GetLinkCount() : 0; }
/*
* CTxtEdit::GetObject(iob, preobj, dwFlags) * * @mfunc returns an object structure for the indicated object */ STDMETHODIMP CTxtEdit::GetObject( LONG iob, //@parm index of the object
REOBJECT * preobj, //@parm where to put object info
DWORD dwFlags) //@parm flags
{ COleObject *pobj = NULL; CCallMgr callmgr(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetObject"); if(!preobj || preobj->cbStruct != sizeof(REOBJECT)) return E_INVALIDARG;
CObjectMgr *pobjmgr = GetObjectMgr(); if(!pobjmgr) return E_OUTOFMEMORY;
// There are three cases of intestest; get the object at
// an index, at a given cp, or at the selection.
if(iob == REO_IOB_USE_CP || iob == REO_IOB_SELECTION) { if((Get10Mode() && preobj->cp == REO_CP_SELECTION) || iob == REO_IOB_SELECTION) { // Use selection cp
CTxtSelection *psel = GetSel(); if(psel) pobj = pobjmgr->GetObjectFromCp(psel->GetCpMin()); } else pobj = pobjmgr->GetObjectFromCp(Get10Mode() ? GetCpFromAcp(preobj->cp): preobj->cp); } else if (iob >= 0) pobj = pobjmgr->GetObjectFromIndex(iob);
if(pobj) { HRESULT hResult = pobj->GetObjectData(preobj, dwFlags);
if (Get10Mode()) preobj->cp = GetAcpFromCp(preobj->cp);
return hResult; }
// This return code is a bit of stretch, but basially
return E_INVALIDARG; }
/*
* CTxtEdit::InsertObject (preobj) * * @mfunc inserts a new object * * @rdesc * HRESULT */ STDMETHODIMP CTxtEdit::InsertObject( REOBJECT * preobj) //@parm object info
{ CCallMgr callmgr(this); CTxtRange rg(this, 0); IUndoBuilder * publdr; CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT, &publdr);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::InsertObject");
// Do some boundary case checking
if(!preobj) return E_INVALIDARG;
CTxtSelection *psel = GetSel(); if(!psel) return E_OUTOFMEMORY;
// The following code gives Outlook major fits if you click on a name in
// the To:, Cc:, or Bcc: fields, so I've commented it out. In principle,
// Outlook's EN_PROTECTION handler should say it's OK to insert in this case.
//
// if(!IsntProtectedOrReadOnly(0, 0, 0))
// return E_ACCESSDENIED;
// If the insertion of this character would cause
// us to exceed the text limit, fail
if((DWORD)(GetAdjustedTextLength() + 1) > TxGetMaxLength()) { // If we're not replacing a selection (or the
// selection is degenerate, then we will have exceeded
// our limit
if(preobj->cp != REO_CP_SELECTION || psel->GetCch() == 0) { GetCallMgr()->SetMaxText(); return E_OUTOFMEMORY; } } CObjectMgr *pobjmgr = GetObjectMgr(); if(pobjmgr) { LONG cch = 0; LONG cp;
undobldr.StopGroupTyping();
if(preobj->cp == REO_CP_SELECTION) { LONG cpFormat; LONG cpMost; psel->AdjustEndEOP(NEWCHARS); cch = psel->GetRange(cp, cpMost);
// Get cp of active end of selection from which we
// will obtain CF for object.
cpFormat = psel->GetCp(); if(publdr) HandleSelectionAEInfo(this, publdr, cpFormat, cch, cp + 1, 0, SELAE_FORCEREPLACE);
// Get format for ReplaceRange: for cp semantics, use format
// at the cp; for selection semantics, use the format at the
// active end of the selection.
rg.SetCp(cpFormat, FALSE); LONG iFormat = rg.Get_iCF(); rg.Set(cp, -cch); rg.Set_iCF(iFormat); // Use _iFormat at sel active end
rg.SetUseiFormat(TRUE); ReleaseFormats(iFormat, -1); } else { cp = Get10Mode() ? GetCpFromAcp(preobj->cp): preobj->cp; rg.SetCp(cp, FALSE); // Updates rg._iFormat
}
if(preobj->dwFlags & REO_USEASBACKGROUND) { CDocInfo *pDocInfo = GetDocInfo(); if(pDocInfo) pDocInfo->InitBackground(); } HRESULT hr = pobjmgr->InsertObject(&rg, preobj, publdr); CNotifyMgr *pnm = GetNotifyMgr(); // Get notification mgr
if(pnm) // Notify interested parties
pnm->NotifyPostReplaceRange(NULL, CP_INFINITE, 0, 0, cp, cp + 1);
// Don't want object selected
psel->SetSelection(cp + 1, cp + 1); if(preobj->dwFlags & REO_USEASBACKGROUND) _pdp->UpdateView();
TxUpdateWindow(); return hr; } return E_OUTOFMEMORY; }
/*
* CTxtEdit::ConvertObject(iob, rclsidNew, lpstrUserTypeNew) * * @mfunc Converts the specified object to the specified class. Does reload * the object but does NOT force an update (caller must do this). * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::ConvertObject( LONG iob, //@parm index of the object
REFCLSID rclsidNew, //@parm the destination clsid
LPCSTR lpstrUserTypeNew) //@parm the new user type name
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ConvertObject"); CCallMgr callmgr(this);
// If iob was invalid return
COleObject * pobj = ObjectFromIOB(iob); if(!pobj) return E_INVALIDARG;
//Delegate to the object.
return pobj->Convert(rclsidNew, lpstrUserTypeNew); }
/*
* CTxtEdit::ActivateAs(rclsid, rclsidAs) * * @mfunc Handles a request by the user to activate all objects of a * particular class as objects of another class. * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::ActivateAs( REFCLSID rclsid, //@parm clsid which we're going to change
REFCLSID rclsidAs) //@parm clsid to activate as
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ActivateAs"); CCallMgr callmgr(this);
CObjectMgr * pobjmgr = GetObjectMgr(); if(!pobjmgr) return E_OUTOFMEMORY;
return pobjmgr->ActivateObjectsAs(rclsid, rclsidAs); }
/*
* CTxtEdit::SetHostNames(lpstrContainerApp, lpstrContainerDoc) * * @mfunc Sets the host names for this instance */ STDMETHODIMP CTxtEdit::SetHostNames( LPCSTR lpstrContainerApp, //@parm App name
LPCSTR lpstrContainerDoc) //@parm Container Object (doc) name
{ CCallMgr callmgr(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetHostNames"); WCHAR *pwsContainerApp = W32->ConvertToWideChar(lpstrContainerApp); WCHAR *pwsContainerDoc = W32->ConvertToWideChar(lpstrContainerDoc);
CObjectMgr *pobjmgr = GetObjectMgr(); if(pobjmgr && pwsContainerApp && pwsContainerDoc) { HRESULT hr = pobjmgr->SetHostNames(pwsContainerApp, pwsContainerDoc); delete pwsContainerApp; delete pwsContainerDoc; return hr; } return E_OUTOFMEMORY; }
/*
* CTxtEdit::SetLinkAvailable(iob, fAvailable) * * @mfunc * Allows client to tell us whether the link is available or not. */ STDMETHODIMP CTxtEdit::SetLinkAvailable( LONG iob, //@parm index of the object
BOOL fAvailable) //@parm if TRUE, make object linkable
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetLinkAvailable");
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj) return E_INVALIDARG;
// Delegate this to the object.
return pobj->SetLinkAvailable(fAvailable); }
/*
* CTxtEdit::SetDvaspect(iob, dvaspect) * * @mfunc Allows client to tell us which aspect to use and force us * to recompute positioning and redraw. * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::SetDvaspect( LONG iob, //@parm index of the object
DWORD dvaspect) //@parm the aspect to use
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetDvaspect"); CCallMgr callmgr(this); COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj) return E_INVALIDARG;
// Delegate this to the object.
pobj->SetDvaspect(dvaspect); return NOERROR; }
/*
* CTxtEdit::HandsOffStorage(iob) * * @mfunc see IPersistStorage::HandsOffStorage * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::HandsOffStorage( LONG iob) //@parm index of the object
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::HandsOffStorage"); CCallMgr callmgr(this);
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj) return E_INVALIDARG;
// Delegate this to the object.
pobj->HandsOffStorage(); return NOERROR; }
/*
* CTxtEdit::SaveCompleted(iob, lpstg) * * @mfunc see IPersistStorage::SaveCompleted * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::SaveCompleted( LONG iob, //@parm index of the object
LPSTORAGE lpstg) //@parm new storage
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SaveCompleted"); CCallMgr callmgr(this);
COleObject * pobj = ObjectFromIOB(iob);
// If iob was invalid, return
if (!pobj) return E_INVALIDARG;
// Delegate this to the object.
pobj->SaveCompleted(lpstg); return NOERROR; }
/*
* CTxtEdit::InPlaceDeactivate() * * @mfunc Deactivate */ STDMETHODIMP CTxtEdit::InPlaceDeactivate() { COleObject *pobj; HRESULT hr = NOERROR; CCallMgr callmgr(this);
TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::InPlaceDeactivate"); CObjectMgr *pobjmgr = GetObjectMgr(); if(pobjmgr) { pobj = pobjmgr->GetInPlaceActiveObject(); if(pobj) hr = pobj->DeActivateObj(); }
return hr; }
/*
* CTxtEdit::ContextSensitiveHelp(fEnterMode) * * @mfunc enter/leave ContextSensitiveHelp mode * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::ContextSensitiveHelp( BOOL fEnterMode) //@parm enter/exit mode
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ContextSensitiveHelp");
HRESULT hr = NOERROR; CCallMgr callmgr(this);
CObjectMgr * pobjmgr = GetObjectMgr(); if(!pobjmgr) return E_OUTOFMEMORY;
// If the mode changes
if(pobjmgr->GetHelpMode() != fEnterMode) { pobjmgr->SetHelpMode(fEnterMode); COleObject * pobj = pobjmgr->GetInPlaceActiveObject(); if(pobj) { IOleWindow *pow; hr = pobj->GetIUnknown()->QueryInterface(IID_IOleWindow, (void **)&pow); if(hr == NOERROR) { hr = pow->ContextSensitiveHelp(fEnterMode); pow->Release(); } } } return hr; }
/*
* CTxtEdit::GetClipboardData(lpchrg, reco, lplpdataobj) * * @mfunc return an data transfer object for the indicated * range * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::GetClipboardData( CHARRANGE *lpchrg, //@parm the range of text to use
DWORD reco, //@parm operation the data is for
LPDATAOBJECT *lplpdataobj) //@parm where to put the data object
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetClipboardData");
CCallMgr callmgr(this); HRESULT hr; LONG cpMin, cpMost; CLightDTEngine * pldte = GetDTE();
//Make sure cpMin and cpMost are within the current text limits.
//Interpret neg. value for cpMin as the beginning of the text,
//and neg. value for cpMax as the end of the text. If a char range
//is not given use the current selection.
if(lpchrg) { LONG cchText = GetTextLength(); cpMin = max(0, lpchrg->cpMin); cpMin = min(cchText, lpchrg->cpMin); cpMost = lpchrg->cpMost; if(lpchrg->cpMost < 0 || lpchrg->cpMost > cchText) cpMost = cchText; } else { CTxtSelection * psel = GetSel(); psel->GetRange(cpMin, cpMost); }
//Make sure this is a valid range.
if(cpMin >= cpMost) { *lplpdataobj = NULL; return cpMin == cpMost ? NOERROR : ResultFromScode(E_INVALIDARG); }
CTxtRange rg(this, cpMin, cpMin-cpMost);
//We don't use reco for anything.
hr = pldte->RangeToDataObject(&rg, SF_RTF, lplpdataobj);
#if !defined(NOFULLDEBUG) && defined(DEBUG)
if(hr != NOERROR) TRACEERRSZSC("GetClipboardData", E_OUTOFMEMORY); #endif
return hr; }
/*
* CTxtEdit::ImportDataObject(lpdataobj, cf, hMetaPict) * * @mfunc morally equivalent to paste, but with a data object * * @rdesc * HRESULT Success code. */ STDMETHODIMP CTxtEdit::ImportDataObject( LPDATAOBJECT lpdataobj, //@parm Data object to use
CLIPFORMAT cf, //@parm Clibpoard format to use
HGLOBAL hMetaPict) //@parm Metafile to use
{ TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ImportDataObject");
CCallMgr callmgr(this); IUndoBuilder * publdr; REPASTESPECIAL rps = {DVASPECT_CONTENT, NULL}; CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT, &publdr);
if(hMetaPict) { rps.dwAspect = DVASPECT_ICON; rps.dwParam = (DWORD_PTR) hMetaPict; }
return PasteDataObjectToRange(lpdataobj, GetSel(), cf, &rps, publdr, PDOR_NOQUERY); }
/*
* CTxtEdit::ObjectFromIOB(iob) * * @mfunc Gets an object based on an IOB type index. * * @rdesc: * pointer to COleObject or NULL if none. */ COleObject * CTxtEdit::ObjectFromIOB( LONG iob) { CObjectMgr * pobjmgr = GetObjectMgr(); if(!pobjmgr) return NULL;
COleObject * pobj = NULL;
// Figure out the index of the selection
if (iob == REO_IOB_SELECTION) { CTxtSelection * psel = GetSel();
pobj = pobjmgr->GetFirstObjectInRange(psel->GetCpMin(), psel->GetCpMost()); } else { // Make sure the IOB is in range
if(0 <= iob && iob < GetObjectCount()) pobj = pobjmgr->GetObjectFromIndex(iob); } return pobj; }
|