Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

598 lines
14 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module object.cpp IRichEditOle implementation |
  5. *
  6. * Author: alexgo 8/15/95
  7. *
  8. * Copyright (c) 1995-2000, Microsoft Corporation. All rights reserved.
  9. */
  10. #include "_common.h"
  11. #include "_edit.h"
  12. #include "_objmgr.h"
  13. #include "_coleobj.h"
  14. #include "_rtext.h"
  15. #include "_select.h"
  16. #include "_m_undo.h"
  17. #include "_disp.h"
  18. // IUnknown is implemented elsewhere
  19. /*
  20. * CTxtEdit::GetClientSite (lplpolesite)
  21. *
  22. * @mfunc returns the client site
  23. */
  24. STDMETHODIMP CTxtEdit::GetClientSite(
  25. LPOLECLIENTSITE FAR * lplpolesite) //@parm where to return
  26. //the client site
  27. {
  28. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetClientSite");
  29. if(!lplpolesite)
  30. return E_INVALIDARG;
  31. COleObject *pobj = new COleObject(this);
  32. // should start with a ref count of 1.
  33. if(pobj)
  34. {
  35. *lplpolesite = (IOleClientSite *)pobj;
  36. return NOERROR;
  37. }
  38. *lplpolesite = NULL;
  39. return E_OUTOFMEMORY;
  40. }
  41. /*
  42. * CTxtEdit::GetObjectCount
  43. *
  44. * @mfunc return the number of objects in this edit instance
  45. */
  46. STDMETHODIMP_(LONG) CTxtEdit::GetObjectCount()
  47. {
  48. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetObjectCount");
  49. return _pobjmgr ? _pobjmgr->GetObjectCount() : 0;
  50. }
  51. /*
  52. * CTxtEdit::GetLinkCount
  53. *
  54. * @mfunc return the number of likns in this edit instance
  55. */
  56. STDMETHODIMP_(LONG) CTxtEdit::GetLinkCount()
  57. {
  58. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetLinkCount");
  59. CObjectMgr *pobjmgr = GetObjectMgr();
  60. return pobjmgr ? pobjmgr->GetLinkCount() : 0;
  61. }
  62. /*
  63. * CTxtEdit::GetObject(iob, preobj, dwFlags)
  64. *
  65. * @mfunc returns an object structure for the indicated object
  66. */
  67. STDMETHODIMP CTxtEdit::GetObject(
  68. LONG iob, //@parm index of the object
  69. REOBJECT * preobj, //@parm where to put object info
  70. DWORD dwFlags) //@parm flags
  71. {
  72. COleObject *pobj = NULL;
  73. CCallMgr callmgr(this);
  74. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetObject");
  75. if(!preobj || preobj->cbStruct != sizeof(REOBJECT))
  76. return E_INVALIDARG;
  77. CObjectMgr *pobjmgr = GetObjectMgr();
  78. if(!pobjmgr)
  79. return E_OUTOFMEMORY;
  80. // There are three cases of intestest; get the object at
  81. // an index, at a given cp, or at the selection.
  82. if(iob == REO_IOB_USE_CP || iob == REO_IOB_SELECTION)
  83. {
  84. if((Get10Mode() && preobj->cp == REO_CP_SELECTION) || iob == REO_IOB_SELECTION)
  85. {
  86. // Use selection cp
  87. CTxtSelection *psel = GetSel();
  88. if(psel)
  89. pobj = pobjmgr->GetObjectFromCp(psel->GetCpMin());
  90. }
  91. else
  92. pobj = pobjmgr->GetObjectFromCp(Get10Mode() ? GetCpFromAcp(preobj->cp): preobj->cp);
  93. }
  94. else if (iob >= 0)
  95. pobj = pobjmgr->GetObjectFromIndex(iob);
  96. if(pobj)
  97. {
  98. HRESULT hResult = pobj->GetObjectData(preobj, dwFlags);
  99. if (Get10Mode())
  100. preobj->cp = GetAcpFromCp(preobj->cp);
  101. return hResult;
  102. }
  103. // This return code is a bit of stretch, but basially
  104. return E_INVALIDARG;
  105. }
  106. /*
  107. * CTxtEdit::InsertObject (preobj)
  108. *
  109. * @mfunc inserts a new object
  110. *
  111. * @rdesc
  112. * HRESULT
  113. */
  114. STDMETHODIMP CTxtEdit::InsertObject(
  115. REOBJECT * preobj) //@parm object info
  116. {
  117. CCallMgr callmgr(this);
  118. CTxtRange rg(this, 0);
  119. IUndoBuilder * publdr;
  120. CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT, &publdr);
  121. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::InsertObject");
  122. // Do some boundary case checking
  123. if(!preobj)
  124. return E_INVALIDARG;
  125. CTxtSelection *psel = GetSel();
  126. if(!psel)
  127. return E_OUTOFMEMORY;
  128. // The following code gives Outlook major fits if you click on a name in
  129. // the To:, Cc:, or Bcc: fields, so I've commented it out. In principle,
  130. // Outlook's EN_PROTECTION handler should say it's OK to insert in this case.
  131. //
  132. // if(!IsntProtectedOrReadOnly(0, 0, 0))
  133. // return E_ACCESSDENIED;
  134. // If the insertion of this character would cause
  135. // us to exceed the text limit, fail
  136. if((DWORD)(GetAdjustedTextLength() + 1) > TxGetMaxLength())
  137. {
  138. // If we're not replacing a selection (or the
  139. // selection is degenerate, then we will have exceeded
  140. // our limit
  141. if(preobj->cp != REO_CP_SELECTION || psel->GetCch() == 0)
  142. {
  143. GetCallMgr()->SetMaxText();
  144. return E_OUTOFMEMORY;
  145. }
  146. }
  147. CObjectMgr *pobjmgr = GetObjectMgr();
  148. if(pobjmgr)
  149. {
  150. LONG cch = 0;
  151. LONG cp;
  152. undobldr.StopGroupTyping();
  153. if(preobj->cp == REO_CP_SELECTION)
  154. {
  155. LONG cpFormat;
  156. LONG cpMost;
  157. psel->AdjustEndEOP(NEWCHARS);
  158. cch = psel->GetRange(cp, cpMost);
  159. // Get cp of active end of selection from which we
  160. // will obtain CF for object.
  161. cpFormat = psel->GetCp();
  162. if(publdr)
  163. HandleSelectionAEInfo(this, publdr, cpFormat, cch,
  164. cp + 1, 0, SELAE_FORCEREPLACE);
  165. // Get format for ReplaceRange: for cp semantics, use format
  166. // at the cp; for selection semantics, use the format at the
  167. // active end of the selection.
  168. rg.SetCp(cpFormat, FALSE);
  169. LONG iFormat = rg.Get_iCF();
  170. rg.Set(cp, -cch);
  171. rg.Set_iCF(iFormat); // Use _iFormat at sel active end
  172. rg.SetUseiFormat(TRUE);
  173. ReleaseFormats(iFormat, -1);
  174. }
  175. else
  176. {
  177. cp = Get10Mode() ? GetCpFromAcp(preobj->cp): preobj->cp;
  178. rg.SetCp(cp, FALSE); // Updates rg._iFormat
  179. }
  180. if(preobj->dwFlags & REO_USEASBACKGROUND)
  181. {
  182. CDocInfo *pDocInfo = GetDocInfo();
  183. if(pDocInfo)
  184. pDocInfo->InitBackground();
  185. }
  186. HRESULT hr = pobjmgr->InsertObject(&rg, preobj, publdr);
  187. CNotifyMgr *pnm = GetNotifyMgr(); // Get notification mgr
  188. if(pnm) // Notify interested parties
  189. pnm->NotifyPostReplaceRange(NULL, CP_INFINITE, 0, 0, cp, cp + 1);
  190. // Don't want object selected
  191. psel->SetSelection(cp + 1, cp + 1);
  192. if(preobj->dwFlags & REO_USEASBACKGROUND)
  193. _pdp->UpdateView();
  194. TxUpdateWindow();
  195. return hr;
  196. }
  197. return E_OUTOFMEMORY;
  198. }
  199. /*
  200. * CTxtEdit::ConvertObject(iob, rclsidNew, lpstrUserTypeNew)
  201. *
  202. * @mfunc Converts the specified object to the specified class. Does reload
  203. * the object but does NOT force an update (caller must do this).
  204. *
  205. * @rdesc
  206. * HRESULT Success code.
  207. */
  208. STDMETHODIMP CTxtEdit::ConvertObject(
  209. LONG iob, //@parm index of the object
  210. REFCLSID rclsidNew, //@parm the destination clsid
  211. LPCSTR lpstrUserTypeNew) //@parm the new user type name
  212. {
  213. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ConvertObject");
  214. CCallMgr callmgr(this);
  215. // If iob was invalid return
  216. COleObject * pobj = ObjectFromIOB(iob);
  217. if(!pobj)
  218. return E_INVALIDARG;
  219. //Delegate to the object.
  220. return pobj->Convert(rclsidNew, lpstrUserTypeNew);
  221. }
  222. /*
  223. * CTxtEdit::ActivateAs(rclsid, rclsidAs)
  224. *
  225. * @mfunc Handles a request by the user to activate all objects of a
  226. * particular class as objects of another class.
  227. *
  228. * @rdesc
  229. * HRESULT Success code.
  230. */
  231. STDMETHODIMP CTxtEdit::ActivateAs(
  232. REFCLSID rclsid, //@parm clsid which we're going to change
  233. REFCLSID rclsidAs) //@parm clsid to activate as
  234. {
  235. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ActivateAs");
  236. CCallMgr callmgr(this);
  237. CObjectMgr * pobjmgr = GetObjectMgr();
  238. if(!pobjmgr)
  239. return E_OUTOFMEMORY;
  240. return pobjmgr->ActivateObjectsAs(rclsid, rclsidAs);
  241. }
  242. /*
  243. * CTxtEdit::SetHostNames(lpstrContainerApp, lpstrContainerDoc)
  244. *
  245. * @mfunc Sets the host names for this instance
  246. */
  247. STDMETHODIMP CTxtEdit::SetHostNames(
  248. LPCSTR lpstrContainerApp, //@parm App name
  249. LPCSTR lpstrContainerDoc) //@parm Container Object (doc) name
  250. {
  251. CCallMgr callmgr(this);
  252. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetHostNames");
  253. WCHAR *pwsContainerApp = W32->ConvertToWideChar(lpstrContainerApp);
  254. WCHAR *pwsContainerDoc = W32->ConvertToWideChar(lpstrContainerDoc);
  255. CObjectMgr *pobjmgr = GetObjectMgr();
  256. if(pobjmgr && pwsContainerApp && pwsContainerDoc)
  257. {
  258. HRESULT hr = pobjmgr->SetHostNames(pwsContainerApp, pwsContainerDoc);
  259. delete pwsContainerApp;
  260. delete pwsContainerDoc;
  261. return hr;
  262. }
  263. return E_OUTOFMEMORY;
  264. }
  265. /*
  266. * CTxtEdit::SetLinkAvailable(iob, fAvailable)
  267. *
  268. * @mfunc
  269. * Allows client to tell us whether the link is available or not.
  270. */
  271. STDMETHODIMP CTxtEdit::SetLinkAvailable(
  272. LONG iob, //@parm index of the object
  273. BOOL fAvailable) //@parm if TRUE, make object linkable
  274. {
  275. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetLinkAvailable");
  276. COleObject * pobj = ObjectFromIOB(iob);
  277. // If iob was invalid, return
  278. if (!pobj)
  279. return E_INVALIDARG;
  280. // Delegate this to the object.
  281. return pobj->SetLinkAvailable(fAvailable);
  282. }
  283. /*
  284. * CTxtEdit::SetDvaspect(iob, dvaspect)
  285. *
  286. * @mfunc Allows client to tell us which aspect to use and force us
  287. * to recompute positioning and redraw.
  288. *
  289. * @rdesc
  290. * HRESULT Success code.
  291. */
  292. STDMETHODIMP CTxtEdit::SetDvaspect(
  293. LONG iob, //@parm index of the object
  294. DWORD dvaspect) //@parm the aspect to use
  295. {
  296. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SetDvaspect");
  297. CCallMgr callmgr(this);
  298. COleObject * pobj = ObjectFromIOB(iob);
  299. // If iob was invalid, return
  300. if (!pobj)
  301. return E_INVALIDARG;
  302. // Delegate this to the object.
  303. pobj->SetDvaspect(dvaspect);
  304. return NOERROR;
  305. }
  306. /*
  307. * CTxtEdit::HandsOffStorage(iob)
  308. *
  309. * @mfunc see IPersistStorage::HandsOffStorage
  310. *
  311. * @rdesc
  312. * HRESULT Success code.
  313. */
  314. STDMETHODIMP CTxtEdit::HandsOffStorage(
  315. LONG iob) //@parm index of the object
  316. {
  317. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::HandsOffStorage");
  318. CCallMgr callmgr(this);
  319. COleObject * pobj = ObjectFromIOB(iob);
  320. // If iob was invalid, return
  321. if (!pobj)
  322. return E_INVALIDARG;
  323. // Delegate this to the object.
  324. pobj->HandsOffStorage();
  325. return NOERROR;
  326. }
  327. /*
  328. * CTxtEdit::SaveCompleted(iob, lpstg)
  329. *
  330. * @mfunc see IPersistStorage::SaveCompleted
  331. *
  332. * @rdesc
  333. * HRESULT Success code.
  334. */
  335. STDMETHODIMP CTxtEdit::SaveCompleted(
  336. LONG iob, //@parm index of the object
  337. LPSTORAGE lpstg) //@parm new storage
  338. {
  339. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::SaveCompleted");
  340. CCallMgr callmgr(this);
  341. COleObject * pobj = ObjectFromIOB(iob);
  342. // If iob was invalid, return
  343. if (!pobj)
  344. return E_INVALIDARG;
  345. // Delegate this to the object.
  346. pobj->SaveCompleted(lpstg);
  347. return NOERROR;
  348. }
  349. /*
  350. * CTxtEdit::InPlaceDeactivate()
  351. *
  352. * @mfunc Deactivate
  353. */
  354. STDMETHODIMP CTxtEdit::InPlaceDeactivate()
  355. {
  356. COleObject *pobj;
  357. HRESULT hr = NOERROR;
  358. CCallMgr callmgr(this);
  359. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::InPlaceDeactivate");
  360. CObjectMgr *pobjmgr = GetObjectMgr();
  361. if(pobjmgr)
  362. {
  363. pobj = pobjmgr->GetInPlaceActiveObject();
  364. if(pobj)
  365. hr = pobj->DeActivateObj();
  366. }
  367. return hr;
  368. }
  369. /*
  370. * CTxtEdit::ContextSensitiveHelp(fEnterMode)
  371. *
  372. * @mfunc enter/leave ContextSensitiveHelp mode
  373. *
  374. * @rdesc
  375. * HRESULT Success code.
  376. */
  377. STDMETHODIMP CTxtEdit::ContextSensitiveHelp(
  378. BOOL fEnterMode) //@parm enter/exit mode
  379. {
  380. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ContextSensitiveHelp");
  381. HRESULT hr = NOERROR;
  382. CCallMgr callmgr(this);
  383. CObjectMgr * pobjmgr = GetObjectMgr();
  384. if(!pobjmgr)
  385. return E_OUTOFMEMORY;
  386. // If the mode changes
  387. if(pobjmgr->GetHelpMode() != fEnterMode)
  388. {
  389. pobjmgr->SetHelpMode(fEnterMode);
  390. COleObject * pobj = pobjmgr->GetInPlaceActiveObject();
  391. if(pobj)
  392. {
  393. IOleWindow *pow;
  394. hr = pobj->GetIUnknown()->QueryInterface(IID_IOleWindow,
  395. (void **)&pow);
  396. if(hr == NOERROR)
  397. {
  398. hr = pow->ContextSensitiveHelp(fEnterMode);
  399. pow->Release();
  400. }
  401. }
  402. }
  403. return hr;
  404. }
  405. /*
  406. * CTxtEdit::GetClipboardData(lpchrg, reco, lplpdataobj)
  407. *
  408. * @mfunc return an data transfer object for the indicated
  409. * range
  410. *
  411. * @rdesc
  412. * HRESULT Success code.
  413. */
  414. STDMETHODIMP CTxtEdit::GetClipboardData(
  415. CHARRANGE *lpchrg, //@parm the range of text to use
  416. DWORD reco, //@parm operation the data is for
  417. LPDATAOBJECT *lplpdataobj) //@parm where to put the data object
  418. {
  419. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::GetClipboardData");
  420. CCallMgr callmgr(this);
  421. HRESULT hr;
  422. LONG cpMin, cpMost;
  423. CLightDTEngine * pldte = GetDTE();
  424. //Make sure cpMin and cpMost are within the current text limits.
  425. //Interpret neg. value for cpMin as the beginning of the text,
  426. //and neg. value for cpMax as the end of the text. If a char range
  427. //is not given use the current selection.
  428. if(lpchrg)
  429. {
  430. LONG cchText = GetTextLength();
  431. cpMin = max(0, lpchrg->cpMin);
  432. cpMin = min(cchText, lpchrg->cpMin);
  433. cpMost = lpchrg->cpMost;
  434. if(lpchrg->cpMost < 0 || lpchrg->cpMost > cchText)
  435. cpMost = cchText;
  436. }
  437. else
  438. {
  439. CTxtSelection * psel = GetSel();
  440. psel->GetRange(cpMin, cpMost);
  441. }
  442. //Make sure this is a valid range.
  443. if(cpMin >= cpMost)
  444. {
  445. *lplpdataobj = NULL;
  446. return cpMin == cpMost
  447. ? NOERROR
  448. : ResultFromScode(E_INVALIDARG);
  449. }
  450. CTxtRange rg(this, cpMin, cpMin-cpMost);
  451. //We don't use reco for anything.
  452. hr = pldte->RangeToDataObject(&rg, SF_RTF, lplpdataobj);
  453. #if !defined(NOFULLDEBUG) && defined(DEBUG)
  454. if(hr != NOERROR)
  455. TRACEERRSZSC("GetClipboardData", E_OUTOFMEMORY);
  456. #endif
  457. return hr;
  458. }
  459. /*
  460. * CTxtEdit::ImportDataObject(lpdataobj, cf, hMetaPict)
  461. *
  462. * @mfunc morally equivalent to paste, but with a data object
  463. *
  464. * @rdesc
  465. * HRESULT Success code.
  466. */
  467. STDMETHODIMP CTxtEdit::ImportDataObject(
  468. LPDATAOBJECT lpdataobj, //@parm Data object to use
  469. CLIPFORMAT cf, //@parm Clibpoard format to use
  470. HGLOBAL hMetaPict) //@parm Metafile to use
  471. {
  472. TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEEXTERN, "CTxtEdit::ImportDataObject");
  473. CCallMgr callmgr(this);
  474. IUndoBuilder * publdr;
  475. REPASTESPECIAL rps = {DVASPECT_CONTENT, NULL};
  476. CGenUndoBuilder undobldr(this, UB_AUTOCOMMIT, &publdr);
  477. if(hMetaPict)
  478. {
  479. rps.dwAspect = DVASPECT_ICON;
  480. rps.dwParam = (DWORD_PTR) hMetaPict;
  481. }
  482. return PasteDataObjectToRange(lpdataobj, GetSel(), cf,
  483. &rps, publdr, PDOR_NOQUERY);
  484. }
  485. /*
  486. * CTxtEdit::ObjectFromIOB(iob)
  487. *
  488. * @mfunc Gets an object based on an IOB type index.
  489. *
  490. * @rdesc:
  491. * pointer to COleObject or NULL if none.
  492. */
  493. COleObject * CTxtEdit::ObjectFromIOB(
  494. LONG iob)
  495. {
  496. CObjectMgr * pobjmgr = GetObjectMgr();
  497. if(!pobjmgr)
  498. return NULL;
  499. COleObject * pobj = NULL;
  500. // Figure out the index of the selection
  501. if (iob == REO_IOB_SELECTION)
  502. {
  503. CTxtSelection * psel = GetSel();
  504. pobj = pobjmgr->GetFirstObjectInRange(psel->GetCpMin(),
  505. psel->GetCpMost());
  506. }
  507. else
  508. {
  509. // Make sure the IOB is in range
  510. if(0 <= iob && iob < GetObjectCount())
  511. pobj = pobjmgr->GetObjectFromIndex(iob);
  512. }
  513. return pobj;
  514. }