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.

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