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.

2446 lines
70 KiB

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1995 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include "stdafx2.h"
  12. #include "wordpad.h"
  13. // See Win98 HACKHACK below
  14. #ifdef _CHICAGO_
  15. #include <initguid.h>
  16. #include <tom.h>
  17. #pragma comment (lib, "oleaut32.lib")
  18. #endif // _CHICAGO_
  19. // Hack multimon to work with NT4 headers but NT5 libs
  20. #if _WIN32_WINNT < 0x0500
  21. #include <multimon.h>
  22. #undef GetSystemMetrics
  23. #undef MonitorFromWindow
  24. #undef MonitorFromRect
  25. #undef MonitorFromPoint
  26. #undef GetMonitorInfo
  27. #undef EnumDisplayMonitors
  28. #undef EnumDisplayDevices
  29. extern "C"
  30. {
  31. WINUSERAPI
  32. HMONITOR
  33. WINAPI
  34. MonitorFromWindow( IN HWND hwnd, IN DWORD dwFlags);
  35. WINUSERAPI BOOL WINAPI GetMonitorInfoA( IN HMONITOR hMonitor, OUT LPMONITORINFO lpmi);
  36. WINUSERAPI BOOL WINAPI GetMonitorInfoW( IN HMONITOR hMonitor, OUT LPMONITORINFO lpmi);
  37. #ifdef UNICODE
  38. #define GetMonitorInfo GetMonitorInfoW
  39. #else
  40. #define GetMonitorInfo GetMonitorInfoA
  41. #endif // !UNICODE
  42. }
  43. #endif
  44. #ifdef AFX_CORE4_SEG
  45. #pragma code_seg(AFX_CORE4_SEG)
  46. #endif
  47. #ifdef _DEBUG
  48. #undef THIS_FILE
  49. static char THIS_FILE[] = __FILE__;
  50. #endif
  51. #define new DEBUG_NEW
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CRe2Object
  54. class CRe2Object : public _reobject
  55. {
  56. public:
  57. CRe2Object();
  58. CRe2Object(CRichEdit2CntrItem* pItem);
  59. ~CRe2Object();
  60. };
  61. CRe2Object::CRe2Object()
  62. {
  63. cbStruct = sizeof(REOBJECT);
  64. poleobj = NULL;
  65. pstg = NULL;
  66. polesite = NULL;
  67. }
  68. CRe2Object::CRe2Object(CRichEdit2CntrItem* pItem)
  69. {
  70. ASSERT(pItem != NULL);
  71. cbStruct = sizeof(REOBJECT);
  72. pItem->GetClassID(&clsid);
  73. poleobj = pItem->m_lpObject;
  74. pstg = pItem->m_lpStorage;
  75. polesite = pItem->m_lpClientSite;
  76. ASSERT(poleobj != NULL);
  77. ASSERT(pstg != NULL);
  78. ASSERT(polesite != NULL);
  79. poleobj->AddRef();
  80. pstg->AddRef();
  81. polesite->AddRef();
  82. sizel.cx = sizel.cy = 0; // let richedit determine initial size
  83. dvaspect = pItem->GetDrawAspect();
  84. dwFlags = REO_RESIZABLE;
  85. dwUser = 0;
  86. }
  87. CRe2Object::~CRe2Object()
  88. {
  89. if (poleobj != NULL)
  90. poleobj->Release();
  91. if (pstg != NULL)
  92. pstg->Release();
  93. if (polesite != NULL)
  94. polesite->Release();
  95. }
  96. //+-------------------------------------------------------------------------
  97. //
  98. // HACKHACK:
  99. //
  100. // The Richedit2 control is Unicode internally so it needs to convert
  101. // strings from Ansi to Unicode when it recieves a EM_FINDTEXTEX message.
  102. // Unfortunately it seems to set the code page for the conversion based
  103. // on the current keyboard layout. This breaks in the following scenario:
  104. //
  105. // Start Wordpad on FE Win98 and type some DBCS chars. Pull up the find
  106. // dialog and enter one of the DBCS chars that you typed before. Set the
  107. // keyboard layout to US and try to find the character - it will fail.
  108. // Now set it to non-US and try the find - it will work.
  109. //
  110. // The hack is to do the conversion ourselves using the system default
  111. // codepage and then do the find using the TOM interfaces.
  112. //
  113. // Richedit3 is supposed to be smarter about this whole issue and hopefully
  114. // this hack can be removed then.
  115. //
  116. //--------------------------------------------------------------------------
  117. #ifdef _CHICAGO_
  118. long CRichEdit2Ctrl::FindText(DWORD dwFlags, FINDTEXTEX* pFindText) const
  119. {
  120. long index = -1;
  121. ITextRange *range = NULL;
  122. HRESULT hr = S_OK;
  123. UINT cchFind = _tcslen(pFindText->lpstrText) + 1;
  124. LPWSTR lpwszFind = NULL;
  125. long length;
  126. //
  127. // Get the base richedit ole interface
  128. //
  129. IUnknown *unk = GetIRichEditOle();
  130. if (NULL == unk)
  131. hr = E_NOINTERFACE;
  132. //
  133. // Get a range object
  134. //
  135. if (S_OK == hr)
  136. {
  137. ITextDocument *doc;
  138. hr = unk->QueryInterface(IID_ITextDocument, (void **) &doc);
  139. if (S_OK == hr)
  140. {
  141. hr = doc->Range(
  142. pFindText->chrg.cpMin,
  143. pFindText->chrg.cpMax,
  144. &range);
  145. doc->Release();
  146. }
  147. unk->Release();
  148. }
  149. //
  150. // Convert the text-to-find to Unicode using the system default code page
  151. //
  152. if (S_OK == hr)
  153. {
  154. try
  155. {
  156. lpwszFind = (LPWSTR) alloca(cchFind * sizeof(WCHAR));
  157. }
  158. catch (...)
  159. {
  160. _resetstkoflw();
  161. hr = E_OUTOFMEMORY; // alloca failed
  162. }
  163. if (S_OK == hr)
  164. {
  165. int error = MultiByteToWideChar(
  166. CP_ACP,
  167. MB_ERR_INVALID_CHARS,
  168. pFindText->lpstrText,
  169. -1,
  170. lpwszFind,
  171. cchFind);
  172. if (0 != error)
  173. lpwszFind = SysAllocString(lpwszFind);
  174. else
  175. hr = E_FAIL;
  176. if (S_OK == hr && NULL == lpwszFind)
  177. hr = E_OUTOFMEMORY;
  178. }
  179. }
  180. //
  181. // Try to find the text
  182. //
  183. if (S_OK == hr)
  184. {
  185. long flags = 0;
  186. flags |= (dwFlags & FR_MATCHCASE) ? tomMatchCase : 0;
  187. flags |= (dwFlags & FR_WHOLEWORD) ? tomMatchWord : 0;
  188. hr = range->FindText((BSTR) lpwszFind, 0, flags, &length);
  189. SysFreeString(lpwszFind);
  190. if (S_OK == hr)
  191. {
  192. hr = range->GetIndex(tomCharacter, &index);
  193. if (S_OK == hr)
  194. {
  195. // GetIndex returns 1-based indices, EM_FINDTEXTEX returns
  196. // 0-based indices.
  197. --index;
  198. pFindText->chrgText.cpMin = index;
  199. pFindText->chrgText.cpMax = index + length;
  200. }
  201. }
  202. }
  203. if (NULL != range)
  204. range->Release();
  205. //
  206. // If all else fails, fall back to EM_FINDTEXTEX
  207. //
  208. if (S_OK != hr)
  209. index = (long)::SendMessage(
  210. m_hWnd,
  211. EM_FINDTEXTEX,
  212. dwFlags,
  213. (LPARAM)pFindText);
  214. return index;
  215. }
  216. #endif // _CHICAGO
  217. /////////////////////////////////////////////////////////////////////////////
  218. // CRichEdit2View
  219. static const UINT nMsgFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
  220. BEGIN_MESSAGE_MAP(CRichEdit2View, CCtrlView)
  221. //{{AFX_MSG_MAP(CRichEdit2View)
  222. ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateNeedSel)
  223. ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateNeedClip)
  224. ON_UPDATE_COMMAND_UI(ID_EDIT_FIND, OnUpdateNeedText)
  225. ON_UPDATE_COMMAND_UI(ID_EDIT_REPEAT, OnUpdateNeedFind)
  226. ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
  227. ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_SPECIAL, OnUpdateEditPasteSpecial)
  228. ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_PROPERTIES, OnUpdateEditProperties)
  229. ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateNeedSel)
  230. ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateNeedSel)
  231. ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateNeedText)
  232. ON_UPDATE_COMMAND_UI(ID_EDIT_REPLACE, OnUpdateNeedText)
  233. ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  234. ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  235. ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  236. ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
  237. ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
  238. ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
  239. ON_COMMAND(ID_EDIT_FIND, OnEditFind)
  240. ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace)
  241. ON_COMMAND(ID_EDIT_REPEAT, OnEditRepeat)
  242. ON_COMMAND(ID_EDIT_PASTE_SPECIAL, OnEditPasteSpecial)
  243. ON_COMMAND(ID_OLE_EDIT_PROPERTIES, OnEditProperties)
  244. ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
  245. ON_COMMAND(ID_FORMAT_FONT, OnFormatFont)
  246. ON_WM_SIZE()
  247. ON_WM_CREATE()
  248. ON_WM_DESTROY()
  249. //}}AFX_MSG_MAP
  250. ON_NOTIFY_REFLECT(EN_SELCHANGE, OnSelChange)
  251. ON_REGISTERED_MESSAGE(nMsgFindReplace, OnFindReplaceCmd)
  252. END_MESSAGE_MAP()
  253. // richedit buffer limit -- let's set it at 16M
  254. AFX_DATADEF ULONG CRichEdit2View::lMaxSize = 0xffffff;
  255. /////////////////////////////////////////////////////////////////////////////
  256. // CRichEdit2View construction/destruction
  257. CRichEdit2View::CRichEdit2View() : CCtrlView(MSFTEDIT_CLASS, AFX_WS_DEFAULT_VIEW |
  258. WS_HSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
  259. ES_MULTILINE | ES_NOHIDESEL | ES_SAVESEL | ES_SELECTIONBAR)
  260. {
  261. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  262. m_lpRichEditOle = NULL;
  263. m_nBulletIndent = 720; // 1/2 inch
  264. m_nWordWrap = WrapToWindow;
  265. m_nPasteType = 0;
  266. SetPaperSize(CSize(8*1440+720, 11*1440));
  267. SetMargins(CRect(0,0,0,0));
  268. m_charformat.cbSize = sizeof(CHARFORMAT);
  269. m_paraformat.cbSize = sizeof(PARAFORMAT);
  270. }
  271. BOOL CRichEdit2View::PreCreateWindow(CREATESTRUCT& cs)
  272. {
  273. _AFX_RICHEDIT2_STATE* pState = AfxGetRichEdit2State();
  274. BOOL bRet = TRUE;
  275. if (pState->m_hInstRichEdit == NULL)
  276. {
  277. bRet = FALSE;
  278. pState->m_hInstRichEdit = LoadLibrary(L"MSFTEDIT.DLL");
  279. if (!pState->m_hInstRichEdit)
  280. {
  281. pState->m_hInstRichEdit = LoadLibrary(L"RICHED20.DLL");
  282. }
  283. if (pState->m_hInstRichEdit)
  284. {
  285. bRet = TRUE;
  286. }
  287. }
  288. CCtrlView::PreCreateWindow(cs);
  289. cs.lpszName = &afxChNil;
  290. cs.cx = cs.cy = 100; // necessary to avoid bug with ES_SELECTIONBAR and zero for cx and cy
  291. cs.style |= WS_CLIPSIBLINGS;
  292. return bRet;
  293. }
  294. int CRichEdit2View::OnCreate(LPCREATESTRUCT lpcs)
  295. {
  296. if (CCtrlView::OnCreate(lpcs) != 0)
  297. return -1;
  298. GetRichEditCtrl().LimitText(lMaxSize);
  299. GetRichEditCtrl().SetEventMask(ENM_SELCHANGE | ENM_CHANGE | ENM_SCROLL);
  300. VERIFY(GetRichEditCtrl().SetOLECallback(&m_xRichEditOleCallback));
  301. m_lpRichEditOle = GetRichEditCtrl().GetIRichEditOle();
  302. DragAcceptFiles();
  303. GetRichEditCtrl().SetOptions(ECOOP_OR, ECO_AUTOWORDSELECTION);
  304. WrapChanged();
  305. ASSERT(m_lpRichEditOle != NULL);
  306. DWORD_PTR dwOptions = GetRichEditCtrl().SendMessage(EM_GETLANGOPTIONS, 0, 0);
  307. dwOptions &= ~IMF_DUALFONT;
  308. GetRichEditCtrl().SendMessage(EM_SETLANGOPTIONS, 0, dwOptions);
  309. dwOptions = (SES_USECTF | SES_CTFALLOWEMBED | SES_CTFALLOWSMARTTAG | SES_CTFALLOWPROOFING);
  310. GetRichEditCtrl().SendMessage(EM_SETEDITSTYLE, dwOptions, dwOptions);
  311. return 0;
  312. }
  313. void CRichEdit2View::OnInitialUpdate()
  314. {
  315. CCtrlView::OnInitialUpdate();
  316. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  317. }
  318. /////////////////////////////////////////////////////////////////////////////
  319. // CRichEdit2View document like functions
  320. void CRichEdit2View::DeleteContents()
  321. {
  322. ASSERT_VALID(this);
  323. ASSERT(m_hWnd != NULL);
  324. SetWindowText(_T(""));
  325. GetRichEditCtrl().EmptyUndoBuffer();
  326. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  327. ASSERT_VALID(this);
  328. }
  329. void CRichEdit2View::WrapChanged()
  330. {
  331. CWaitCursor wait;
  332. CRichEdit2Ctrl& ctrl = GetRichEditCtrl();
  333. if (m_nWordWrap == WrapNone)
  334. ctrl.SetTargetDevice(NULL, 1);
  335. else if (m_nWordWrap == WrapToWindow)
  336. ctrl.SetTargetDevice(NULL, 0);
  337. else if (m_nWordWrap == WrapToTargetDevice) // wrap to ruler
  338. {
  339. AfxGetApp()->CreatePrinterDC(m_dcTarget);
  340. if (m_dcTarget.m_hDC == NULL)
  341. m_dcTarget.CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  342. ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());
  343. }
  344. }
  345. /////////////////////////////////////////////////////////////////////////////
  346. // CRichEdit2View serialization support
  347. class _afxRichEditCookie
  348. {
  349. public:
  350. CArchive& m_ar;
  351. DWORD m_dwError;
  352. _afxRichEditCookie(CArchive& ar) : m_ar(ar) {m_dwError=0;}
  353. };
  354. void CRichEdit2View::Serialize(CArchive& ar)
  355. // Read and write CRichEdit2View object to archive, with length prefix.
  356. {
  357. ASSERT_VALID(this);
  358. ASSERT(m_hWnd != NULL);
  359. Stream(ar, FALSE);
  360. ASSERT_VALID(this);
  361. }
  362. void CRichEdit2View::Stream(CArchive& ar, BOOL bSelection)
  363. {
  364. EDITSTREAM es = {0, 0, EditStreamCallBack};
  365. _afxRichEditCookie cookie(ar);
  366. es.dwCookie = (DWORD_PTR)&cookie;
  367. int nFormat = GetDocument()->GetStreamFormat();
  368. if (bSelection)
  369. nFormat |= SFF_SELECTION;
  370. if (GetDocument()->IsUnicode())
  371. nFormat |= SF_UNICODE;
  372. if (ar.IsStoring())
  373. GetRichEditCtrl().StreamOut(nFormat, es);
  374. else
  375. {
  376. GetRichEditCtrl().StreamIn(nFormat, es);
  377. Invalidate();
  378. }
  379. if (cookie.m_dwError != 0)
  380. AfxThrowFileException(cookie.m_dwError);
  381. }
  382. // return 0 for no error, otherwise return error code
  383. DWORD CALLBACK CRichEdit2View::EditStreamCallBack(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
  384. {
  385. _afxRichEditCookie* pCookie = (_afxRichEditCookie*)dwCookie;
  386. CArchive& ar = pCookie->m_ar;
  387. ar.Flush();
  388. DWORD dw = 0;
  389. *pcb = cb;
  390. TRY
  391. {
  392. if (ar.IsStoring())
  393. ar.GetFile()->WriteHuge(pbBuff, cb);
  394. else
  395. *pcb = ar.GetFile()->ReadHuge(pbBuff, cb);
  396. }
  397. CATCH(CFileException, e)
  398. {
  399. *pcb = 0;
  400. pCookie->m_dwError = (DWORD)e->m_cause;
  401. dw = 1;
  402. DELETE_EXCEPTION(e);
  403. }
  404. AND_CATCH_ALL(e)
  405. {
  406. *pcb = 0;
  407. pCookie->m_dwError = (DWORD)CFileException::generic;
  408. dw = 1;
  409. DELETE_EXCEPTION(e);
  410. }
  411. END_CATCH_ALL
  412. return dw;
  413. }
  414. /////////////////////////////////////////////////////////////////////////////
  415. // CRichEdit2View Printing support
  416. void CRichEdit2View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo*)
  417. {
  418. ASSERT_VALID(this);
  419. // ASSERT_VALID(pDC);
  420. // initialize page start vector
  421. ASSERT(m_aPageStart.GetSize() == 0);
  422. m_aPageStart.Add(0);
  423. ASSERT(m_aPageStart.GetSize() > 0);
  424. GetRichEditCtrl().FormatRange(NULL, FALSE); // required by RichEdit to clear out cache
  425. ASSERT_VALID(this);
  426. }
  427. BOOL CRichEdit2View::PaginateTo(CDC* pDC, CPrintInfo* pInfo)
  428. // attempts pagination to pInfo->m_nCurPage, TRUE == success
  429. {
  430. ASSERT_VALID(this);
  431. ASSERT_VALID(pDC);
  432. CRect rectSave = pInfo->m_rectDraw;
  433. UINT nPageSave = pInfo->m_nCurPage;
  434. ASSERT(nPageSave > 1);
  435. ASSERT(nPageSave >= (UINT)m_aPageStart.GetSize());
  436. VERIFY(pDC->SaveDC() != 0);
  437. pDC->IntersectClipRect(0, 0, 0, 0);
  438. pInfo->m_nCurPage = (UINT)m_aPageStart.GetSize();
  439. while (pInfo->m_nCurPage < nPageSave)
  440. {
  441. ASSERT(pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize());
  442. OnPrepareDC(pDC, pInfo);
  443. ASSERT(pInfo->m_bContinuePrinting);
  444. pInfo->m_rectDraw.SetRect(0, 0,
  445. pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
  446. pDC->DPtoLP(&pInfo->m_rectDraw);
  447. OnPrint(pDC, pInfo);
  448. if (pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize())
  449. break;
  450. ++pInfo->m_nCurPage;
  451. }
  452. BOOL bResult = pInfo->m_nCurPage == nPageSave;
  453. pDC->RestoreDC(-1);
  454. pInfo->m_nCurPage = nPageSave;
  455. pInfo->m_rectDraw = rectSave;
  456. ASSERT_VALID(this);
  457. return bResult;
  458. }
  459. void CRichEdit2View::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  460. {
  461. ASSERT_VALID(this);
  462. ASSERT_VALID(pDC);
  463. ASSERT(pInfo != NULL); // overriding OnPaint -- never get this.
  464. pDC->SetMapMode(MM_TEXT);
  465. if (pInfo->m_nCurPage > (UINT)m_aPageStart.GetSize() &&
  466. !PaginateTo(pDC, pInfo))
  467. {
  468. // can't paginate to that page, thus cannot print it.
  469. pInfo->m_bContinuePrinting = FALSE;
  470. }
  471. ASSERT_VALID(this);
  472. }
  473. long CRichEdit2View::PrintPage(CDC* pDC, long nIndexStart, long nIndexStop)
  474. // worker function for laying out text in a rectangle.
  475. {
  476. ASSERT_VALID(this);
  477. ASSERT_VALID(pDC);
  478. FORMATRANGE fr;
  479. // offset by printing offset
  480. pDC->SetViewportOrg(-pDC->GetDeviceCaps(PHYSICALOFFSETX),
  481. -pDC->GetDeviceCaps(PHYSICALOFFSETY));
  482. // adjust DC because richedit doesn't do things like MFC
  483. if (::GetDeviceCaps(pDC->m_hDC, TECHNOLOGY) != DT_METAFILE && pDC->m_hAttribDC != NULL)
  484. {
  485. ::ScaleWindowExtEx(pDC->m_hDC,
  486. ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSX),
  487. ::GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSX),
  488. ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY),
  489. ::GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSY), NULL);
  490. }
  491. fr.hdcTarget = pDC->m_hAttribDC;
  492. fr.hdc = pDC->m_hDC;
  493. fr.rcPage = GetPageRect();
  494. fr.rc = GetPrintRect();
  495. fr.chrg.cpMin = nIndexStart;
  496. fr.chrg.cpMax = nIndexStop;
  497. long lRes = GetRichEditCtrl().FormatRange(&fr,TRUE);
  498. return lRes;
  499. }
  500. long CRichEdit2View::PrintInsideRect(CDC* pDC, RECT& rectLayout,
  501. long nIndexStart, long nIndexStop, BOOL bOutput)
  502. {
  503. ASSERT_VALID(this);
  504. ASSERT_VALID(pDC);
  505. FORMATRANGE fr;
  506. // adjust DC because richedit doesn't do things like MFC
  507. if (::GetDeviceCaps(pDC->m_hDC, TECHNOLOGY) != DT_METAFILE && pDC->m_hAttribDC != NULL)
  508. {
  509. ::ScaleWindowExtEx(pDC->m_hDC,
  510. ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSX),
  511. ::GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSX),
  512. ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY),
  513. ::GetDeviceCaps(pDC->m_hAttribDC, LOGPIXELSY), NULL);
  514. }
  515. fr.hdcTarget = pDC->m_hAttribDC;
  516. fr.hdc = pDC->m_hDC;
  517. // convert rect to twips
  518. fr.rcPage = rectLayout;
  519. fr.rc = rectLayout;
  520. fr.chrg.cpMin = nIndexStart;
  521. fr.chrg.cpMax = nIndexStop;
  522. GetRichEditCtrl().FormatRange(NULL, FALSE); // required by RichEdit to clear out cache
  523. // if bOutput is FALSE, we only measure
  524. long lres = GetRichEditCtrl().FormatRange(&fr, bOutput);
  525. GetRichEditCtrl().FormatRange(NULL, FALSE); // required by RichEdit to clear out cache
  526. rectLayout = fr.rc;
  527. return lres;
  528. }
  529. void CRichEdit2View::OnPrint(CDC* pDC, CPrintInfo* pInfo)
  530. {
  531. ASSERT_VALID(this);
  532. ASSERT_VALID(pDC);
  533. ASSERT(pInfo != NULL);
  534. ASSERT(pInfo->m_bContinuePrinting);
  535. UINT nPage = pInfo->m_nCurPage;
  536. ASSERT(nPage <= (UINT)m_aPageStart.GetSize());
  537. long nIndex = (long) m_aPageStart[nPage-1];
  538. // print as much as possible in the current page.
  539. nIndex = PrintPage(pDC, nIndex, 0xFFFFFFFF);
  540. if (nIndex >= GetTextLength())
  541. {
  542. TRACE0("End of Document\n");
  543. pInfo->SetMaxPage(nPage);
  544. }
  545. // update pagination information for page just printed
  546. if (nPage == (UINT)m_aPageStart.GetSize())
  547. {
  548. if (nIndex < GetTextLength())
  549. m_aPageStart.Add(nIndex);
  550. }
  551. else
  552. {
  553. ASSERT(nPage+1 <= (UINT)m_aPageStart.GetSize());
  554. ASSERT(nIndex == (long)m_aPageStart[nPage+1-1]);
  555. }
  556. }
  557. void CRichEdit2View::OnEndPrinting(CDC*, CPrintInfo*)
  558. {
  559. ASSERT_VALID(this);
  560. GetRichEditCtrl().FormatRange(NULL, FALSE); // required by RichEdit to clear out cache
  561. m_aPageStart.RemoveAll();
  562. }
  563. /////////////////////////////////////////////////////////////////////////////
  564. // CRichEdit2View::XRichEditOleCallback
  565. BEGIN_INTERFACE_MAP(CRichEdit2View, CCtrlView)
  566. // we use IID_IUnknown because richedit doesn't define an IID
  567. INTERFACE_PART(CRichEdit2View, IID_IUnknown, RichEditOleCallback)
  568. END_INTERFACE_MAP()
  569. STDMETHODIMP_(ULONG) CRichEdit2View::XRichEditOleCallback::AddRef()
  570. {
  571. METHOD_PROLOGUE_EX_(CRichEdit2View, RichEditOleCallback)
  572. return (ULONG)pThis->InternalAddRef();
  573. }
  574. STDMETHODIMP_(ULONG) CRichEdit2View::XRichEditOleCallback::Release()
  575. {
  576. METHOD_PROLOGUE_EX_(CRichEdit2View, RichEditOleCallback)
  577. return (ULONG)pThis->InternalRelease();
  578. }
  579. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::QueryInterface(
  580. REFIID iid, LPVOID* ppvObj)
  581. {
  582. METHOD_PROLOGUE_EX_(CRichEdit2View, RichEditOleCallback)
  583. return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  584. }
  585. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::GetNewStorage(LPSTORAGE* ppstg)
  586. {
  587. METHOD_PROLOGUE_EX_(CRichEdit2View, RichEditOleCallback)
  588. // Create a flat storage and steal it from the client item
  589. // the client item is only used for creating the storage
  590. COleClientItem item;
  591. item.GetItemStorageFlat();
  592. *ppstg = item.m_lpStorage;
  593. HRESULT hRes = E_OUTOFMEMORY;
  594. if (item.m_lpStorage != NULL)
  595. {
  596. item.m_lpStorage = NULL;
  597. hRes = S_OK;
  598. }
  599. pThis->GetDocument()->InvalidateObjectCache();
  600. return hRes;
  601. }
  602. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::GetInPlaceContext(
  603. LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
  604. LPOLEINPLACEFRAMEINFO lpFrameInfo)
  605. {
  606. METHOD_PROLOGUE_EX(CRichEdit2View, RichEditOleCallback)
  607. return pThis->GetWindowContext(lplpFrame, lplpDoc, lpFrameInfo);
  608. }
  609. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::ShowContainerUI(BOOL fShow)
  610. {
  611. METHOD_PROLOGUE_EX(CRichEdit2View, RichEditOleCallback)
  612. return pThis->ShowContainerUI(fShow);
  613. }
  614. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::QueryInsertObject(
  615. LPCLSID /*lpclsid*/, LPSTORAGE /*pstg*/, LONG /*cp*/)
  616. {
  617. METHOD_PROLOGUE_EX(CRichEdit2View, RichEditOleCallback)
  618. pThis->GetDocument()->InvalidateObjectCache();
  619. return S_OK;
  620. }
  621. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::DeleteObject(LPOLEOBJECT /*lpoleobj*/)
  622. {
  623. METHOD_PROLOGUE_EX_(CRichEdit2View, RichEditOleCallback)
  624. pThis->GetDocument()->InvalidateObjectCache();
  625. return S_OK;
  626. }
  627. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::QueryAcceptData(
  628. LPDATAOBJECT lpdataobj, CLIPFORMAT* lpcfFormat, DWORD reco,
  629. BOOL fReally, HGLOBAL hMetaPict)
  630. {
  631. METHOD_PROLOGUE_EX(CRichEdit2View, RichEditOleCallback)
  632. return pThis->QueryAcceptData(lpdataobj, lpcfFormat, reco,
  633. fReally, hMetaPict);
  634. }
  635. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::ContextSensitiveHelp(BOOL /*fEnterMode*/)
  636. {
  637. return E_NOTIMPL;
  638. }
  639. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::GetClipboardData(
  640. CHARRANGE* lpchrg, DWORD reco, LPDATAOBJECT* lplpdataobj)
  641. {
  642. METHOD_PROLOGUE_EX(CRichEdit2View, RichEditOleCallback)
  643. LPDATAOBJECT lpOrigDataObject = NULL;
  644. // get richedit's data object
  645. if (FAILED(pThis->m_lpRichEditOle->GetClipboardData(lpchrg, reco,
  646. &lpOrigDataObject)))
  647. {
  648. return E_NOTIMPL;
  649. }
  650. // allow changes
  651. HRESULT hRes = pThis->GetClipboardData(lpchrg, reco, lpOrigDataObject,
  652. lplpdataobj);
  653. // if changed then free original object
  654. if (SUCCEEDED(hRes))
  655. {
  656. if (lpOrigDataObject!=NULL)
  657. lpOrigDataObject->Release();
  658. return hRes;
  659. }
  660. else
  661. {
  662. // use richedit's data object
  663. *lplpdataobj = lpOrigDataObject;
  664. return S_OK;
  665. }
  666. }
  667. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::GetDragDropEffect(
  668. BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
  669. {
  670. if (!fDrag) // allowable dest effects
  671. {
  672. DWORD dwEffect;
  673. // check for force link
  674. if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
  675. dwEffect = DROPEFFECT_LINK;
  676. // check for force copy
  677. else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  678. dwEffect = DROPEFFECT_COPY;
  679. // check for force move
  680. else if ((grfKeyState & MK_ALT) == MK_ALT)
  681. dwEffect = DROPEFFECT_MOVE;
  682. // default -- recommended action is move
  683. else
  684. dwEffect = DROPEFFECT_MOVE;
  685. if (dwEffect & *pdwEffect) // make sure allowed type
  686. *pdwEffect = dwEffect;
  687. }
  688. return S_OK;
  689. }
  690. STDMETHODIMP CRichEdit2View::XRichEditOleCallback::GetContextMenu(
  691. WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE* lpchrg,
  692. HMENU* lphmenu)
  693. {
  694. METHOD_PROLOGUE_EX(CRichEdit2View, RichEditOleCallback)
  695. HMENU hMenu = pThis->GetContextMenu(seltype, lpoleobj, lpchrg);
  696. if (hMenu == NULL)
  697. return E_NOTIMPL;
  698. *lphmenu = hMenu;
  699. return S_OK;
  700. }
  701. /////////////////////////////////////////////////////////////////////////////
  702. // CRichEdit2View command helpers
  703. void CRichEdit2View::OnCharEffect(DWORD dwMask, DWORD dwEffect)
  704. {
  705. GetCharFormatSelection();
  706. if (m_charformat.dwMask & dwMask) // selection is all the same
  707. m_charformat.dwEffects ^= dwEffect;
  708. else
  709. m_charformat.dwEffects |= dwEffect;
  710. m_charformat.dwMask = dwMask;
  711. SetCharFormat(m_charformat);
  712. }
  713. void CRichEdit2View::OnUpdateCharEffect(CCmdUI* pCmdUI, DWORD dwMask, DWORD dwEffect)
  714. {
  715. GetCharFormatSelection();
  716. pCmdUI->SetCheck((m_charformat.dwMask & dwMask) ?
  717. ((m_charformat.dwEffects & dwEffect) ? 1 : 0) : 2);
  718. }
  719. void CRichEdit2View::OnParaAlign(WORD wAlign)
  720. {
  721. GetParaFormatSelection();
  722. m_paraformat.dwMask = PFM_ALIGNMENT;
  723. m_paraformat.wAlignment = wAlign;
  724. SetParaFormat(m_paraformat);
  725. }
  726. void CRichEdit2View::OnUpdateParaAlign(CCmdUI* pCmdUI, WORD wAlign)
  727. {
  728. GetParaFormatSelection();
  729. // disable if no word wrap since alignment is meaningless
  730. pCmdUI->Enable( (m_nWordWrap == WrapNone) ?
  731. FALSE : TRUE);
  732. pCmdUI->SetCheck( (m_paraformat.dwMask & PFM_ALIGNMENT) ?
  733. ((m_paraformat.wAlignment == wAlign) ? 1 : 0) : 2);
  734. }
  735. /////////////////////////////////////////////////////////////////////////////
  736. // CRichEdit2View commands
  737. void CRichEdit2View::OnUpdateNeedSel(CCmdUI* pCmdUI)
  738. {
  739. ASSERT_VALID(this);
  740. long nStartChar, nEndChar;
  741. GetRichEditCtrl().GetSel(nStartChar, nEndChar);
  742. pCmdUI->Enable(nStartChar != nEndChar);
  743. ASSERT_VALID(this);
  744. }
  745. void CRichEdit2View::OnUpdateNeedClip(CCmdUI* pCmdUI)
  746. {
  747. ASSERT_VALID(this);
  748. pCmdUI->Enable(CanPaste());
  749. }
  750. void CRichEdit2View::OnUpdateNeedText(CCmdUI* pCmdUI)
  751. {
  752. ASSERT_VALID(this);
  753. pCmdUI->Enable(GetTextLength() != 0);
  754. }
  755. void CRichEdit2View::OnUpdateNeedFind(CCmdUI* pCmdUI)
  756. {
  757. ASSERT_VALID(this);
  758. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  759. pCmdUI->Enable(GetTextLength() != 0 &&
  760. !pEditState->strFind.IsEmpty());
  761. }
  762. void CRichEdit2View::OnUpdateEditUndo(CCmdUI* pCmdUI)
  763. {
  764. ASSERT_VALID(this);
  765. pCmdUI->Enable(GetRichEditCtrl().CanUndo());
  766. }
  767. void CRichEdit2View::OnEditCut()
  768. {
  769. ASSERT_VALID(this);
  770. GetRichEditCtrl().Cut();
  771. }
  772. void CRichEdit2View::OnEditCopy()
  773. {
  774. ASSERT_VALID(this);
  775. GetRichEditCtrl().Copy();
  776. }
  777. void CRichEdit2View::OnEditPaste()
  778. {
  779. ASSERT_VALID(this);
  780. m_nPasteType = 0;
  781. GetRichEditCtrl().Paste();
  782. }
  783. void CRichEdit2View::OnEditClear()
  784. {
  785. ASSERT_VALID(this);
  786. GetRichEditCtrl().Clear();
  787. }
  788. void CRichEdit2View::OnEditUndo()
  789. {
  790. ASSERT_VALID(this);
  791. GetRichEditCtrl().Undo();
  792. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  793. }
  794. void CRichEdit2View::OnEditSelectAll()
  795. {
  796. ASSERT_VALID(this);
  797. GetRichEditCtrl().SetSel(0, -1);
  798. }
  799. void CRichEdit2View::OnEditFind()
  800. {
  801. ASSERT_VALID(this);
  802. OnEditFindReplace(TRUE);
  803. }
  804. void CRichEdit2View::OnEditReplace()
  805. {
  806. ASSERT_VALID(this);
  807. OnEditFindReplace(FALSE);
  808. }
  809. void CRichEdit2View::OnEditRepeat()
  810. {
  811. ASSERT_VALID(this);
  812. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  813. if (!FindText(pEditState))
  814. TextNotFound(pEditState->strFind);
  815. }
  816. void CRichEdit2View::OnCancelEditCntr()
  817. {
  818. m_lpRichEditOle->InPlaceDeactivate();
  819. }
  820. void CRichEdit2View::OnInsertObject()
  821. {
  822. // Invoke the standard Insert Object dialog box to obtain information
  823. COleInsertDialog dlg;
  824. if (dlg.DoModal() != IDOK)
  825. return;
  826. CWaitCursor wait;
  827. CRichEdit2CntrItem* pItem = NULL;
  828. TRY
  829. {
  830. // create item from dialog results
  831. pItem = GetDocument()->CreateClientItem();
  832. pItem->m_bLock = TRUE;
  833. if (!dlg.CreateItem(pItem))
  834. {
  835. pItem->m_bLock = FALSE;
  836. AfxThrowMemoryException(); // any exception will do
  837. }
  838. HRESULT hr = InsertItem(pItem);
  839. pItem->UpdateItemType();
  840. pItem->m_bLock = FALSE;
  841. if (hr != NOERROR)
  842. AfxThrowOleException(hr);
  843. // if insert new object -- initially show the object
  844. if (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
  845. pItem->DoVerb(OLEIVERB_SHOW, this);
  846. }
  847. CATCH(CException, e)
  848. {
  849. if (pItem != NULL)
  850. {
  851. ASSERT_VALID(pItem);
  852. pItem->Delete();
  853. }
  854. AfxMessageBox(AFX_IDP_FAILED_TO_CREATE);
  855. }
  856. END_CATCH
  857. }
  858. void CRichEdit2View::OnSelChange(NMHDR* pNMHDR, LRESULT* pResult)
  859. {
  860. ASSERT(pNMHDR->code == EN_SELCHANGE);
  861. UNUSED(pNMHDR); // not used in release builds
  862. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  863. *pResult = 0;
  864. }
  865. void CRichEdit2View::OnDestroy()
  866. {
  867. if (m_lpRichEditOle != NULL)
  868. m_lpRichEditOle->Release();
  869. CCtrlView::OnDestroy();
  870. }
  871. void CRichEdit2View::OnEditProperties()
  872. {
  873. ASSERT(m_lpRichEditOle != NULL);
  874. CRichEdit2CntrItem* pSelection = GetSelectedItem();
  875. // make sure item is in sync with richedit's item
  876. CRe2Object reo;
  877. m_lpRichEditOle->GetObject(REO_IOB_SELECTION, &reo, REO_GETOBJ_NO_INTERFACES);
  878. pSelection->SyncToRichEditObject(reo);
  879. //
  880. // HACKHACK: Due to a mismatch between the NT build environment and MFC
  881. // wrt to the setting of _WIN32_IE, Wordpad and MFC have
  882. // different views of how large a COlePropertiesDialog is. The
  883. // result is that MFC ends up wiping part of the stack in it's
  884. // initialization code. Hack some extra space until the
  885. // mismatch is resolved.
  886. //
  887. // COlePropertiesDialog dlg(pSelection);
  888. struct Hack
  889. {
  890. COlePropertiesDialog dlg;
  891. BYTE space[128];
  892. Hack(CRichEdit2CntrItem *pSelection) : dlg(pSelection) {}
  893. }
  894. hack(pSelection);
  895. COlePropertiesDialog &dlg = hack.dlg;
  896. //
  897. // The Object Properties dialog doesn't display a help button even if
  898. // you tell it to. The dialogs under it (e.g. Change Icon) will display
  899. // the help button though. We never want a help button but MFC turns it
  900. // on by default. If the Ole dialogs are fixed to not display the help
  901. // button then this can be removed.
  902. //
  903. dlg.m_op.dwFlags &= ~OPF_SHOWHELP;
  904. dlg.DoModal();
  905. }
  906. void CRichEdit2View::OnUpdateEditProperties(CCmdUI* pCmdUI)
  907. {
  908. pCmdUI->Enable(GetSelectedItem() != NULL);
  909. }
  910. void CRichEdit2View::OnCharBold()
  911. {
  912. OnCharEffect(CFM_BOLD, CFE_BOLD);
  913. }
  914. void CRichEdit2View::OnUpdateCharBold(CCmdUI* pCmdUI)
  915. {
  916. OnUpdateCharEffect(pCmdUI, CFM_BOLD, CFE_BOLD);
  917. }
  918. void CRichEdit2View::OnCharItalic()
  919. {
  920. OnCharEffect(CFM_ITALIC, CFE_ITALIC);
  921. }
  922. void CRichEdit2View::OnUpdateCharItalic(CCmdUI* pCmdUI)
  923. {
  924. OnUpdateCharEffect(pCmdUI, CFM_ITALIC, CFE_ITALIC);
  925. }
  926. void CRichEdit2View::OnCharUnderline()
  927. {
  928. OnCharEffect(CFM_UNDERLINE, CFE_UNDERLINE);
  929. }
  930. void CRichEdit2View::OnUpdateCharUnderline(CCmdUI* pCmdUI)
  931. {
  932. OnUpdateCharEffect(pCmdUI, CFM_UNDERLINE, CFE_UNDERLINE);
  933. }
  934. void CRichEdit2View::OnParaCenter()
  935. {
  936. OnParaAlign(PFA_CENTER);
  937. }
  938. void CRichEdit2View::OnUpdateParaCenter(CCmdUI* pCmdUI)
  939. {
  940. OnUpdateParaAlign(pCmdUI, PFA_CENTER);
  941. }
  942. void CRichEdit2View::OnParaLeft()
  943. {
  944. OnParaAlign(PFA_LEFT);
  945. }
  946. void CRichEdit2View::OnUpdateParaLeft(CCmdUI* pCmdUI)
  947. {
  948. OnUpdateParaAlign(pCmdUI, PFA_LEFT);
  949. }
  950. void CRichEdit2View::OnParaRight()
  951. {
  952. OnParaAlign(PFA_RIGHT);
  953. }
  954. void CRichEdit2View::OnUpdateParaRight(CCmdUI* pCmdUI)
  955. {
  956. OnUpdateParaAlign(pCmdUI, PFA_RIGHT);
  957. }
  958. void CRichEdit2View::OnBullet()
  959. {
  960. GetParaFormatSelection();
  961. if (m_paraformat.dwMask & PFM_NUMBERING && m_paraformat.wNumbering == PFN_BULLET)
  962. {
  963. m_paraformat.wNumbering = 0;
  964. m_paraformat.dxOffset = 0;
  965. m_paraformat.dxStartIndent = 0;
  966. m_paraformat.dwMask = PFM_NUMBERING | PFM_STARTINDENT | PFM_OFFSET;
  967. }
  968. else
  969. {
  970. m_paraformat.wNumbering = PFN_BULLET;
  971. m_paraformat.dwMask = PFM_NUMBERING;
  972. if (m_paraformat.dxOffset == 0)
  973. {
  974. m_paraformat.dxOffset = m_nBulletIndent;
  975. m_paraformat.dwMask = PFM_NUMBERING | PFM_STARTINDENT | PFM_OFFSET;
  976. }
  977. }
  978. SetParaFormat(m_paraformat);
  979. }
  980. void CRichEdit2View::OnUpdateBullet(CCmdUI* pCmdUI)
  981. {
  982. GetParaFormatSelection();
  983. pCmdUI->SetCheck( (m_paraformat.dwMask & PFM_NUMBERING) ? ((m_paraformat.wNumbering & PFN_BULLET) ? 1 : 0) : 2);
  984. }
  985. void CRichEdit2View::OnFormatFont()
  986. {
  987. GetCharFormatSelection();
  988. CFontDialog2 dlg(m_charformat, CF_BOTH|CF_NOOEMFONTS);
  989. if (dlg.DoModal() == IDOK)
  990. {
  991. dlg.GetCharFormat(m_charformat);
  992. SetCharFormat(m_charformat);
  993. }
  994. }
  995. void CRichEdit2View::OnColorPick(COLORREF cr)
  996. {
  997. GetCharFormatSelection();
  998. m_charformat.dwMask = CFM_COLOR;
  999. m_charformat.dwEffects = NULL;
  1000. m_charformat.crTextColor = cr;
  1001. SetCharFormat(m_charformat);
  1002. }
  1003. void CRichEdit2View::OnColorDefault()
  1004. {
  1005. GetCharFormatSelection();
  1006. m_charformat.dwMask = CFM_COLOR;
  1007. m_charformat.dwEffects = CFE_AUTOCOLOR;
  1008. SetCharFormat(m_charformat);
  1009. }
  1010. void CRichEdit2View::OnEditPasteSpecial()
  1011. {
  1012. COlePasteSpecialDialog dlg;
  1013. dlg.AddStandardFormats();
  1014. dlg.AddFormat(_oleData.cfRichTextFormat, TYMED_HGLOBAL, AFX_IDS_RTF_FORMAT, FALSE, FALSE);
  1015. dlg.AddFormat(CF_TEXT, TYMED_HGLOBAL, AFX_IDS_TEXT_FORMAT, FALSE, FALSE);
  1016. if (dlg.DoModal() != IDOK)
  1017. return;
  1018. DVASPECT dv = dlg.GetDrawAspect();
  1019. HMETAFILE hMF = (HMETAFILE)dlg.GetIconicMetafile();
  1020. CLIPFORMAT cf =
  1021. dlg.m_ps.arrPasteEntries[dlg.m_ps.nSelectedIndex].fmtetc.cfFormat;
  1022. CWaitCursor wait;
  1023. SetCapture();
  1024. // we set the target type so that QueryAcceptData know what to paste
  1025. m_nPasteType = dlg.GetSelectionType();
  1026. GetRichEditCtrl().PasteSpecial(cf, dv, hMF);
  1027. m_nPasteType = 0;
  1028. ReleaseCapture();
  1029. }
  1030. void CRichEdit2View::OnUpdateEditPasteSpecial(CCmdUI* pCmdUI)
  1031. {
  1032. pCmdUI->Enable(CanPaste());
  1033. }
  1034. void CRichEdit2View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1035. {
  1036. if (nChar == VK_F10 && GetKeyState(VK_SHIFT) < 0)
  1037. {
  1038. CRect rect;
  1039. GetClientRect(rect);
  1040. CPoint pt = rect.CenterPoint();
  1041. SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, MAKELPARAM(pt.x, pt.y));
  1042. }
  1043. else
  1044. CCtrlView::OnKeyDown(nChar, nRepCnt, nFlags);
  1045. }
  1046. void CRichEdit2View::OnDropFiles(HDROP hDropInfo)
  1047. {
  1048. TCHAR szFileName[_MAX_PATH];
  1049. UINT nFileCount = ::DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
  1050. ASSERT(nFileCount != 0);
  1051. CHARRANGE cr;
  1052. GetRichEditCtrl().GetSel(cr);
  1053. int nMin = cr.cpMin;
  1054. for (UINT i=0;i<nFileCount;i++)
  1055. {
  1056. ::DragQueryFile(hDropInfo, i, szFileName, ARRAYSIZE(szFileName));
  1057. InsertFileAsObject(szFileName);
  1058. GetRichEditCtrl().GetSel(cr);
  1059. cr.cpMin = cr.cpMax;
  1060. GetRichEditCtrl().SetSel(cr);
  1061. UpdateWindow();
  1062. }
  1063. cr.cpMin = nMin;
  1064. GetRichEditCtrl().SetSel(cr);
  1065. ::DragFinish(hDropInfo);
  1066. }
  1067. void CRichEdit2View::OnDevModeChange(LPTSTR /*lpDeviceName*/)
  1068. {
  1069. // WM_DEVMODECHANGE forwarded by the main window of the app
  1070. CDC dc;
  1071. AfxGetApp()->CreatePrinterDC(dc);
  1072. OnPrinterChanged(dc);
  1073. }
  1074. /////////////////////////////////////////////////////////////////////////////
  1075. // CRichEdit2View attributes
  1076. BOOL AFX_CDECL CRichEdit2View::IsRichEdit2Format(CLIPFORMAT cf)
  1077. {
  1078. return ((cf == _oleData.cfRichTextFormat) ||
  1079. (cf == _oleData.cfRichTextAndObjects) ||
  1080. (cf == CF_TEXT) ||
  1081. (cf == CF_UNICODETEXT));
  1082. }
  1083. BOOL CRichEdit2View::CanPaste() const
  1084. {
  1085. return (CountClipboardFormats() != 0) &&
  1086. (IsClipboardFormatAvailable(CF_TEXT) ||
  1087. IsClipboardFormatAvailable(_oleData.cfRichTextFormat) ||
  1088. IsClipboardFormatAvailable(_oleData.cfEmbedSource) ||
  1089. IsClipboardFormatAvailable(_oleData.cfEmbeddedObject) ||
  1090. IsClipboardFormatAvailable(_oleData.cfFileName) ||
  1091. IsClipboardFormatAvailable(_oleData.cfFileNameW) ||
  1092. IsClipboardFormatAvailable(CF_METAFILEPICT) ||
  1093. IsClipboardFormatAvailable(CF_DIB) ||
  1094. IsClipboardFormatAvailable(CF_BITMAP) ||
  1095. GetRichEditCtrl().CanPaste());
  1096. }
  1097. CHARFORMAT& CRichEdit2View::GetCharFormatSelection()
  1098. {
  1099. if (m_bSyncCharFormat)
  1100. {
  1101. GetRichEditCtrl().GetSelectionCharFormat(m_charformat);
  1102. m_bSyncCharFormat = FALSE;
  1103. }
  1104. return m_charformat;
  1105. }
  1106. PARAFORMAT& CRichEdit2View::GetParaFormatSelection()
  1107. {
  1108. if (m_bSyncParaFormat)
  1109. {
  1110. GetRichEditCtrl().GetParaFormat(m_paraformat);
  1111. m_bSyncParaFormat = FALSE;
  1112. }
  1113. return m_paraformat;
  1114. }
  1115. void CRichEdit2View::SetCharFormat(CHARFORMAT cf)
  1116. {
  1117. CWaitCursor wait;
  1118. GetRichEditCtrl().SetSelectionCharFormat(cf);
  1119. m_bSyncCharFormat = TRUE;
  1120. }
  1121. void CRichEdit2View::SetParaFormat(PARAFORMAT& pf)
  1122. {
  1123. CWaitCursor wait;
  1124. GetRichEditCtrl().SetParaFormat(pf);
  1125. m_bSyncParaFormat = TRUE;
  1126. }
  1127. CRichEdit2CntrItem* CRichEdit2View::GetSelectedItem() const
  1128. {
  1129. ASSERT(m_lpRichEditOle != NULL);
  1130. CRichEdit2Doc* pDoc = GetDocument();
  1131. CRichEdit2CntrItem* pItem = NULL;
  1132. CRe2Object reo;
  1133. HRESULT hr = m_lpRichEditOle->GetObject(REO_IOB_SELECTION, &reo,
  1134. REO_GETOBJ_ALL_INTERFACES);
  1135. //reo's interfaces are all in UNICODE
  1136. if (GetScode(hr) == S_OK)
  1137. {
  1138. pItem = pDoc->LookupItem(reo.poleobj);
  1139. if (pItem == NULL)
  1140. pItem = pDoc->CreateClientItem(&reo);
  1141. ASSERT(pItem != NULL);
  1142. }
  1143. return pItem;
  1144. }
  1145. CRichEdit2CntrItem* CRichEdit2View::GetInPlaceActiveItem() const
  1146. {
  1147. ASSERT(m_lpRichEditOle != NULL);
  1148. CRichEdit2Doc* pDoc = GetDocument();
  1149. CRichEdit2CntrItem* pItem = NULL;
  1150. CRe2Object reo;
  1151. HRESULT hr = m_lpRichEditOle->GetObject(REO_IOB_SELECTION, &reo,
  1152. REO_GETOBJ_ALL_INTERFACES);
  1153. //reo's interfaces are all in UNICODE
  1154. if (GetScode(hr) == S_OK && (reo.dwFlags & REO_INPLACEACTIVE))
  1155. {
  1156. pItem = pDoc->LookupItem(reo.poleobj);
  1157. if (pItem == NULL)
  1158. pItem = pDoc->CreateClientItem(&reo);
  1159. ASSERT(pItem != NULL);
  1160. }
  1161. return pItem;
  1162. }
  1163. /////////////////////////////////////////////////////////////////////////////
  1164. // CRichEdit2View operations
  1165. HRESULT CRichEdit2View::InsertItem(CRichEdit2CntrItem* pItem)
  1166. {
  1167. ASSERT(m_lpRichEditOle != NULL);
  1168. CRe2Object reo(pItem);
  1169. reo.cp = REO_CP_SELECTION;
  1170. HRESULT hr = m_lpRichEditOle->InsertObject(&reo);
  1171. CHARRANGE cr;
  1172. GetRichEditCtrl().GetSel(cr);
  1173. cr.cpMin = cr.cpMax -1;
  1174. GetRichEditCtrl().SetSel(cr);
  1175. return hr;
  1176. }
  1177. void CRichEdit2View::InsertFileAsObject(LPCTSTR lpszFileName)
  1178. {
  1179. CString str = lpszFileName;
  1180. CWaitCursor wait;
  1181. CRichEdit2CntrItem* pItem = NULL;
  1182. TRY
  1183. {
  1184. // create item from dialog results
  1185. pItem = GetDocument()->CreateClientItem();
  1186. pItem->m_bLock = TRUE;
  1187. if (!pItem->CreateFromFile(str))
  1188. AfxThrowMemoryException(); // any exception will do
  1189. pItem->UpdateLink();
  1190. InsertItem(pItem);
  1191. pItem->m_bLock = FALSE;
  1192. }
  1193. CATCH(CException, e)
  1194. {
  1195. if (pItem != NULL)
  1196. {
  1197. pItem->m_bLock = FALSE;
  1198. ASSERT_VALID(pItem);
  1199. pItem->Delete();
  1200. }
  1201. }
  1202. END_CATCH
  1203. }
  1204. //
  1205. // CRichEditView::DoPaste doesn't return an error but we need it to...
  1206. //
  1207. HRESULT g_hrPaste;
  1208. void CRichEdit2View::DoPaste(COleDataObject& dataobj, CLIPFORMAT cf, HMETAFILEPICT hMetaPict)
  1209. {
  1210. CWaitCursor wait;
  1211. g_hrPaste = S_FALSE;
  1212. CRichEdit2CntrItem* pItem = NULL;
  1213. TRY
  1214. {
  1215. // create item from dialog results
  1216. pItem = GetDocument()->CreateClientItem();
  1217. pItem->m_bLock = TRUE;
  1218. if (m_nPasteType == COlePasteSpecialDialog::pasteLink) // paste link
  1219. {
  1220. if (!pItem->CreateLinkFromData(&dataobj))
  1221. AfxThrowMemoryException(); // any exception will do
  1222. }
  1223. else if (m_nPasteType == COlePasteSpecialDialog::pasteNormal)
  1224. {
  1225. if (!pItem->CreateFromData(&dataobj))
  1226. AfxThrowMemoryException(); // any exception will do
  1227. }
  1228. else if (m_nPasteType == COlePasteSpecialDialog::pasteStatic)
  1229. {
  1230. if (!pItem->CreateStaticFromData(&dataobj))
  1231. AfxThrowMemoryException(); // any exception will do
  1232. }
  1233. else
  1234. {
  1235. // paste embedded
  1236. if (!pItem->CreateFromData(&dataobj) &&
  1237. !pItem->CreateStaticFromData(&dataobj))
  1238. {
  1239. AfxThrowMemoryException(); // any exception will do
  1240. }
  1241. }
  1242. if (cf == 0)
  1243. {
  1244. // copy the current iconic representation
  1245. FORMATETC fmtetc;
  1246. fmtetc.cfFormat = CF_METAFILEPICT;
  1247. fmtetc.dwAspect = DVASPECT_ICON;
  1248. fmtetc.ptd = NULL;
  1249. fmtetc.tymed = TYMED_MFPICT;
  1250. fmtetc.lindex = 1;
  1251. HGLOBAL hObj = dataobj.GetGlobalData(CF_METAFILEPICT, &fmtetc);
  1252. if (hObj != NULL)
  1253. {
  1254. pItem->SetIconicMetafile(hObj);
  1255. // the following code is an easy way to free a metafile pict
  1256. STGMEDIUM stgMed;
  1257. memset(&stgMed, 0, sizeof(stgMed));
  1258. stgMed.tymed = TYMED_MFPICT;
  1259. stgMed.hGlobal = hObj;
  1260. ReleaseStgMedium(&stgMed);
  1261. }
  1262. // set the current drawing aspect
  1263. hObj = dataobj.GetGlobalData((CLIPFORMAT)_oleData.cfObjectDescriptor);
  1264. if (hObj != NULL)
  1265. {
  1266. ASSERT(hObj != NULL);
  1267. // got CF_OBJECTDESCRIPTOR ok. Lock it down and extract size.
  1268. LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObj);
  1269. ASSERT(pObjDesc != NULL);
  1270. ((COleClientItem*)pItem)->SetDrawAspect((DVASPECT)pObjDesc->dwDrawAspect);
  1271. GlobalUnlock(hObj);
  1272. GlobalFree(hObj);
  1273. }
  1274. }
  1275. else
  1276. {
  1277. if (hMetaPict != NULL)
  1278. {
  1279. pItem->SetIconicMetafile(hMetaPict);
  1280. ((COleClientItem*)pItem)->SetDrawAspect(DVASPECT_ICON);
  1281. }
  1282. else
  1283. ((COleClientItem*)pItem)->SetDrawAspect(DVASPECT_CONTENT);
  1284. }
  1285. /////////
  1286. HRESULT hr = InsertItem(pItem);
  1287. pItem->UpdateItemType();
  1288. pItem->m_bLock = FALSE;
  1289. if (hr != NOERROR)
  1290. AfxThrowOleException(hr);
  1291. }
  1292. CATCH(CException, e)
  1293. {
  1294. if (pItem != NULL)
  1295. {
  1296. pItem->m_bLock = FALSE;
  1297. ASSERT_VALID(pItem);
  1298. pItem->Delete();
  1299. }
  1300. g_hrPaste = E_FAIL;
  1301. }
  1302. END_CATCH
  1303. }
  1304. /////////////////////////////////////////////////////////////////////////////
  1305. // CRichEdit2View virtuals
  1306. void CRichEdit2View::OnPrinterChanged(const CDC& dcPrinter)
  1307. {
  1308. // this is typically called by the view when it gets a WM_DEVMODECHANGE
  1309. // also called during page setup
  1310. CSize size;
  1311. if (dcPrinter.m_hDC != NULL)
  1312. {
  1313. // this will fill in the page size
  1314. size.cx = MulDiv(dcPrinter.GetDeviceCaps(PHYSICALWIDTH), 1440,
  1315. dcPrinter.GetDeviceCaps(LOGPIXELSX));
  1316. size.cy = MulDiv(dcPrinter.GetDeviceCaps(PHYSICALHEIGHT), 1440,
  1317. dcPrinter.GetDeviceCaps(LOGPIXELSY));
  1318. }
  1319. else
  1320. size = CSize(8*1440+720, 11*1440); // 8.5" by 11"
  1321. if (GetPaperSize() != size)
  1322. {
  1323. SetPaperSize(size);
  1324. if (m_nWordWrap == WrapToTargetDevice) //wrap to ruler
  1325. WrapChanged();
  1326. }
  1327. }
  1328. BOOL CRichEdit2View::OnPasteNativeObject(LPSTORAGE)
  1329. {
  1330. // use this function to pull out native data from an embedded object
  1331. // one would typically do this by create a COleStreamFile and attaching it
  1332. // to an archive
  1333. return FALSE;
  1334. }
  1335. HMENU CRichEdit2View::GetContextMenu(WORD, LPOLEOBJECT, CHARRANGE* )
  1336. {
  1337. return NULL;
  1338. }
  1339. HRESULT CRichEdit2View::GetClipboardData(CHARRANGE* /*lpchrg*/, DWORD /*reco*/,
  1340. LPDATAOBJECT /*lpRichDataObj*/, LPDATAOBJECT* /*lplpdataobj*/)
  1341. {
  1342. return E_NOTIMPL;
  1343. }
  1344. HRESULT CRichEdit2View::QueryAcceptData(LPDATAOBJECT lpdataobj,
  1345. CLIPFORMAT* lpcfFormat, DWORD /*dwReco*/, BOOL bReally, HGLOBAL hMetaPict)
  1346. {
  1347. ASSERT(lpcfFormat != NULL);
  1348. if (!bReally) // not actually pasting
  1349. return S_OK;
  1350. // if direct pasting a particular native format allow it
  1351. if (IsRichEdit2Format(*lpcfFormat))
  1352. return S_OK;
  1353. COleDataObject dataobj;
  1354. dataobj.Attach(lpdataobj, FALSE);
  1355. // if format is 0, then force particular formats if available
  1356. if (*lpcfFormat == 0 && (m_nPasteType == 0))
  1357. {
  1358. if (dataobj.IsDataAvailable((CLIPFORMAT)_oleData.cfRichTextAndObjects)) // native avail, let richedit do as it wants
  1359. return S_OK;
  1360. else if (dataobj.IsDataAvailable((CLIPFORMAT)_oleData.cfRichTextFormat))
  1361. {
  1362. *lpcfFormat = (CLIPFORMAT)_oleData.cfRichTextFormat;
  1363. return S_OK;
  1364. }
  1365. else if (dataobj.IsDataAvailable(CF_UNICODETEXT))
  1366. {
  1367. *lpcfFormat = CF_UNICODETEXT;
  1368. return S_OK;
  1369. }
  1370. else if (dataobj.IsDataAvailable(CF_TEXT))
  1371. {
  1372. *lpcfFormat = CF_TEXT;
  1373. return S_OK;
  1374. }
  1375. }
  1376. // paste OLE formats
  1377. DoPaste(dataobj, *lpcfFormat, hMetaPict);
  1378. return g_hrPaste;
  1379. }
  1380. HRESULT CRichEdit2View::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame,
  1381. LPOLEINPLACEUIWINDOW* lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  1382. {
  1383. CRichEdit2CntrItem* pItem = GetSelectedItem();
  1384. if (pItem == NULL)
  1385. return E_FAIL;
  1386. pItem->m_pView = this;
  1387. HRESULT hr = pItem->GetWindowContext(lplpFrame, lplpDoc, lpFrameInfo);
  1388. pItem->m_pView = NULL;
  1389. return hr;
  1390. }
  1391. HRESULT CRichEdit2View::ShowContainerUI(BOOL b)
  1392. {
  1393. CRichEdit2CntrItem* pItem = GetSelectedItem();
  1394. if (pItem == NULL)
  1395. return E_FAIL;
  1396. if (b)
  1397. pItem->m_pView = this;
  1398. HRESULT hr = pItem->ShowContainerUI(b);
  1399. if (FAILED(hr) || !b)
  1400. pItem->m_pView = NULL;
  1401. return hr;
  1402. }
  1403. /////////////////////////////////////////////////////////////////////////////
  1404. // CRichEdit2View Find & Replace
  1405. void CRichEdit2View::AdjustDialogPosition(CDialog* pDlg)
  1406. {
  1407. ASSERT(pDlg != NULL);
  1408. long lStart, lEnd;
  1409. GetRichEditCtrl().GetSel(lStart, lEnd);
  1410. CPoint point = GetRichEditCtrl().GetCharPos(lStart);
  1411. ClientToScreen(&point);
  1412. CRect rectDlg;
  1413. pDlg->GetWindowRect(&rectDlg);
  1414. if (rectDlg.PtInRect(point))
  1415. {
  1416. if (point.y > rectDlg.Height())
  1417. rectDlg.OffsetRect(0, point.y - rectDlg.bottom - 20);
  1418. else
  1419. {
  1420. HMONITOR hMonitor = MonitorFromWindow(*pDlg, MONITOR_DEFAULTTONEAREST);
  1421. MONITORINFO monitorInfo;
  1422. monitorInfo.cbSize = sizeof(monitorInfo);
  1423. GetMonitorInfo(hMonitor, &monitorInfo);
  1424. int nVertExt = monitorInfo.rcMonitor.bottom
  1425. - monitorInfo.rcMonitor.top;
  1426. if (point.y + rectDlg.Height() < nVertExt)
  1427. rectDlg.OffsetRect(0, 40 + point.y - rectDlg.top);
  1428. }
  1429. pDlg->MoveWindow(&rectDlg);
  1430. }
  1431. }
  1432. void CRichEdit2View::OnEditFindReplace(BOOL bFindOnly)
  1433. {
  1434. ASSERT_VALID(this);
  1435. m_bFirstSearch = TRUE;
  1436. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1437. if (pEditState->pFindReplaceDlg != NULL)
  1438. {
  1439. if (pEditState->bFindOnly == bFindOnly)
  1440. {
  1441. pEditState->pFindReplaceDlg->SetActiveWindow();
  1442. pEditState->pFindReplaceDlg->ShowWindow(SW_SHOW);
  1443. return;
  1444. }
  1445. else
  1446. {
  1447. ASSERT(pEditState->bFindOnly != bFindOnly);
  1448. pEditState->pFindReplaceDlg->SendMessage(WM_CLOSE);
  1449. ASSERT(pEditState->pFindReplaceDlg == NULL);
  1450. ASSERT_VALID(this);
  1451. }
  1452. }
  1453. CString strFind = GetRichEditCtrl().GetSelText();
  1454. // if selection is empty or spans multiple lines use old find text
  1455. if (strFind.IsEmpty() || (strFind.FindOneOf(_T("\n\r")) != -1))
  1456. strFind = pEditState->strFind;
  1457. CString strReplace = pEditState->strReplace;
  1458. pEditState->pFindReplaceDlg = new CFindReplaceDialog;
  1459. ASSERT(pEditState->pFindReplaceDlg != NULL);
  1460. DWORD dwFlags = NULL;
  1461. if (pEditState->bNext)
  1462. dwFlags |= FR_DOWN;
  1463. if (pEditState->bCase)
  1464. dwFlags |= FR_MATCHCASE;
  1465. if (pEditState->bWord)
  1466. dwFlags |= FR_WHOLEWORD;
  1467. // hide stuff that RichEdit doesn't support
  1468. dwFlags |= FR_HIDEUPDOWN;
  1469. if (!pEditState->pFindReplaceDlg->Create(bFindOnly, strFind,
  1470. strReplace, dwFlags, this))
  1471. {
  1472. pEditState->pFindReplaceDlg = NULL;
  1473. ASSERT_VALID(this);
  1474. return;
  1475. }
  1476. ASSERT(pEditState->pFindReplaceDlg != NULL);
  1477. pEditState->bFindOnly = bFindOnly;
  1478. pEditState->pFindReplaceDlg->SetActiveWindow();
  1479. pEditState->pFindReplaceDlg->ShowWindow(SW_SHOW);
  1480. ASSERT_VALID(this);
  1481. }
  1482. void CRichEdit2View::OnFindNext(LPCTSTR lpszFind, BOOL bNext, BOOL bCase, BOOL bWord)
  1483. {
  1484. ASSERT_VALID(this);
  1485. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1486. pEditState->strFind = lpszFind;
  1487. pEditState->bCase = bCase;
  1488. pEditState->bWord = bWord;
  1489. pEditState->bNext = bNext;
  1490. if (!FindText(pEditState))
  1491. TextNotFound(pEditState->strFind);
  1492. else
  1493. AdjustDialogPosition(pEditState->pFindReplaceDlg);
  1494. ASSERT_VALID(this);
  1495. }
  1496. void CRichEdit2View::OnReplaceSel(LPCTSTR lpszFind, BOOL bNext, BOOL bCase,
  1497. BOOL bWord, LPCTSTR lpszReplace)
  1498. {
  1499. ASSERT_VALID(this);
  1500. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1501. pEditState->strFind = lpszFind;
  1502. pEditState->strReplace = lpszReplace;
  1503. pEditState->bCase = bCase;
  1504. pEditState->bWord = bWord;
  1505. pEditState->bNext = bNext;
  1506. if (!SameAsSelected(pEditState->strFind, pEditState->bCase, pEditState->bWord))
  1507. {
  1508. if (!FindText(pEditState))
  1509. TextNotFound(pEditState->strFind);
  1510. else
  1511. AdjustDialogPosition(pEditState->pFindReplaceDlg);
  1512. return;
  1513. }
  1514. long start;
  1515. long end;
  1516. long length1;
  1517. long length2;
  1518. GetRichEditCtrl().GetSel(start, end);
  1519. length1 = end - start;
  1520. GetRichEditCtrl().ReplaceSel(pEditState->strReplace, TRUE);
  1521. if (!FindText(pEditState))
  1522. {
  1523. TextNotFound(pEditState->strFind);
  1524. }
  1525. else
  1526. {
  1527. GetRichEditCtrl().GetSel(start, end);
  1528. length2 = end - start;
  1529. if (m_lInitialSearchPos < 0)
  1530. m_lInitialSearchPos += (length2 - length1);
  1531. AdjustDialogPosition(pEditState->pFindReplaceDlg);
  1532. }
  1533. ASSERT_VALID(this);
  1534. }
  1535. void CRichEdit2View::OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bCase, BOOL bWord)
  1536. {
  1537. ASSERT_VALID(this);
  1538. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1539. pEditState->strFind = lpszFind;
  1540. pEditState->strReplace = lpszReplace;
  1541. pEditState->bCase = bCase;
  1542. pEditState->bWord = bWord;
  1543. pEditState->bNext = TRUE;
  1544. CWaitCursor wait;
  1545. // no selection or different than what looking for
  1546. if (!SameAsSelected(pEditState->strFind, pEditState->bCase, pEditState->bWord))
  1547. {
  1548. if (!FindText(pEditState))
  1549. {
  1550. TextNotFound(pEditState->strFind);
  1551. return;
  1552. }
  1553. }
  1554. GetRichEditCtrl().HideSelection(TRUE, FALSE);
  1555. do
  1556. {
  1557. GetRichEditCtrl().ReplaceSel(pEditState->strReplace, TRUE);
  1558. } while (FindTextSimple(pEditState));
  1559. TextNotFound(pEditState->strFind);
  1560. GetRichEditCtrl().HideSelection(FALSE, FALSE);
  1561. ASSERT_VALID(this);
  1562. }
  1563. LRESULT CRichEdit2View::OnFindReplaceCmd(WPARAM, LPARAM lParam)
  1564. {
  1565. ASSERT_VALID(this);
  1566. CFindReplaceDialog* pDialog = CFindReplaceDialog::GetNotifier(lParam);
  1567. ASSERT(pDialog != NULL);
  1568. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1569. ASSERT(pDialog == pEditState->pFindReplaceDlg);
  1570. if (pDialog->IsTerminating())
  1571. pEditState->pFindReplaceDlg = NULL;
  1572. else if (pDialog->FindNext())
  1573. {
  1574. OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(),
  1575. pDialog->MatchCase(), pDialog->MatchWholeWord());
  1576. }
  1577. else if (pDialog->ReplaceCurrent())
  1578. {
  1579. ASSERT(!pEditState->bFindOnly);
  1580. OnReplaceSel(pDialog->GetFindString(),
  1581. pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(),
  1582. pDialog->GetReplaceString());
  1583. }
  1584. else if (pDialog->ReplaceAll())
  1585. {
  1586. ASSERT(!pEditState->bFindOnly);
  1587. OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(),
  1588. pDialog->MatchCase(), pDialog->MatchWholeWord());
  1589. }
  1590. ASSERT_VALID(this);
  1591. return 0;
  1592. }
  1593. BOOL CRichEdit2View::SameAsSelected(LPCTSTR lpszCompare, BOOL bCase, BOOL /*bWord*/)
  1594. {
  1595. CString strSelect = GetRichEditCtrl().GetSelText();
  1596. return (bCase && lstrcmp(lpszCompare, strSelect) == 0) ||
  1597. (!bCase && lstrcmpi(lpszCompare, strSelect) == 0);
  1598. }
  1599. BOOL CRichEdit2View::FindText(_AFX_RICHEDIT2_STATE* pEditState)
  1600. {
  1601. ASSERT(pEditState != NULL);
  1602. return FindText(pEditState->strFind, pEditState->bCase, pEditState->bWord);
  1603. }
  1604. BOOL CRichEdit2View::FindText(LPCTSTR lpszFind, BOOL bCase, BOOL bWord)
  1605. {
  1606. ASSERT_VALID(this);
  1607. CWaitCursor wait;
  1608. return FindTextSimple(lpszFind, bCase, bWord);
  1609. }
  1610. BOOL CRichEdit2View::FindTextSimple(_AFX_RICHEDIT2_STATE* pEditState)
  1611. {
  1612. ASSERT(pEditState != NULL);
  1613. return FindTextSimple(pEditState->strFind, pEditState->bCase, pEditState->bWord);
  1614. }
  1615. BOOL CRichEdit2View::FindTextSimple(LPCTSTR lpszFind, BOOL bCase, BOOL bWord)
  1616. {
  1617. USES_CONVERSION;
  1618. ASSERT(lpszFind != NULL);
  1619. FINDTEXTEX ft;
  1620. long cchText;
  1621. GETTEXTLENGTHEX textlen;
  1622. textlen.flags = GTL_NUMCHARS;
  1623. #ifdef UNICODE
  1624. textlen.codepage = 1200; // Unicode code page
  1625. #else
  1626. textlen.codepage = CP_ACP;
  1627. #endif
  1628. cchText = (long)GetRichEditCtrl().SendMessage(
  1629. EM_GETTEXTLENGTHEX,
  1630. (WPARAM) &textlen,
  1631. 0);
  1632. GetRichEditCtrl().GetSel(ft.chrg);
  1633. if (m_bFirstSearch)
  1634. {
  1635. m_lInitialSearchPos = ft.chrg.cpMin;
  1636. m_bFirstSearch = FALSE;
  1637. }
  1638. //REVIEW: Is this cast safe?
  1639. ft.lpstrText = (LPTSTR)lpszFind;
  1640. if (ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection
  1641. ft.chrg.cpMin++;
  1642. DWORD dwFlags = bCase ? FR_MATCHCASE : 0;
  1643. dwFlags |= bWord ? FR_WHOLEWORD : 0;
  1644. dwFlags |= FR_DOWN;
  1645. ft.chrg.cpMax = cchText;
  1646. long index = GetRichEditCtrl().FindText(dwFlags, &ft);
  1647. if (-1 == index && m_lInitialSearchPos > 0)
  1648. {
  1649. //
  1650. // m_lInitialSearchPos pulls double duty as the point at which we
  1651. // started searching and a flag which says if we've wrapped back
  1652. // to the beginning of the text during a search. If it's negative
  1653. // (biased by the number of characters) then we've already wrapped
  1654. //
  1655. m_lInitialSearchPos = m_lInitialSearchPos - cchText;
  1656. ft.chrg.cpMin = 0;
  1657. ft.chrg.cpMax = cchText;
  1658. index = GetRichEditCtrl().FindText(dwFlags, &ft);
  1659. }
  1660. if (-1 != index && m_lInitialSearchPos < 0)
  1661. if (index >= (m_lInitialSearchPos + cchText) )
  1662. index = -1;
  1663. if (-1 != index)
  1664. GetRichEditCtrl().SetSel(ft.chrgText);
  1665. return (-1 != index);
  1666. }
  1667. long CRichEdit2View::FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft)
  1668. {
  1669. long index = GetRichEditCtrl().FindText(dwFlags, &ft);
  1670. if (index != -1) // i.e. we found something
  1671. GetRichEditCtrl().SetSel(ft.chrgText);
  1672. return index;
  1673. }
  1674. void CRichEdit2View::TextNotFound(LPCTSTR lpszFind)
  1675. {
  1676. ASSERT_VALID(this);
  1677. m_bFirstSearch = TRUE;
  1678. OnTextNotFound(lpszFind);
  1679. }
  1680. void CRichEdit2View::OnTextNotFound(LPCTSTR)
  1681. {
  1682. }
  1683. /////////////////////////////////////////////////////////////////////////////
  1684. // CRichEdit2View diagnostics
  1685. #ifdef _DEBUG
  1686. void CRichEdit2View::AssertValid() const
  1687. {
  1688. CCtrlView::AssertValid();
  1689. ASSERT_VALID(&m_aPageStart);
  1690. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1691. if (pEditState->pFindReplaceDlg != NULL)
  1692. ASSERT_VALID(pEditState->pFindReplaceDlg);
  1693. }
  1694. void CRichEdit2View::Dump(CDumpContext& dc) const
  1695. {
  1696. CCtrlView::Dump(dc);
  1697. AFX_DUMP1(dc, "\nm_aPageStart ", &m_aPageStart);
  1698. AFX_DUMP0(dc, "\n Static Member Data:");
  1699. _AFX_RICHEDIT2_STATE* pEditState = _afxRichEdit2State;
  1700. if (pEditState->pFindReplaceDlg != NULL)
  1701. {
  1702. AFX_DUMP1(dc, "\npFindReplaceDlg = ",
  1703. (void*)pEditState->pFindReplaceDlg);
  1704. AFX_DUMP1(dc, "\nbFindOnly = ", pEditState->bFindOnly);
  1705. }
  1706. AFX_DUMP1(dc, "\nstrFind = ", pEditState->strFind);
  1707. AFX_DUMP1(dc, "\nstrReplace = ", pEditState->strReplace);
  1708. AFX_DUMP1(dc, "\nbCase = ", pEditState->bCase);
  1709. AFX_DUMP1(dc, "\nbWord = ", pEditState->bWord);
  1710. AFX_DUMP1(dc, "\nbNext = ", pEditState->bNext);
  1711. }
  1712. #endif //_DEBUG
  1713. /////////////////////////////////////////////////////////////////////////////
  1714. // OLE Client support and commands
  1715. BOOL CRichEdit2View::IsSelected(const CObject* pDocItem) const
  1716. {
  1717. return (pDocItem == GetSelectedItem());
  1718. }
  1719. /////////////////////////////////////////////////////////////////////////////
  1720. // CRichEdit2Doc
  1721. CRichEdit2Doc::CRichEdit2Doc()
  1722. {
  1723. m_bRTF = TRUE;
  1724. m_bUnicode = FALSE;
  1725. m_bUpdateObjectCache = FALSE;
  1726. ASSERT_VALID(this);
  1727. }
  1728. CRichEdit2View* CRichEdit2Doc::GetView() const
  1729. {
  1730. // find the first view - if there are no views
  1731. // we must return NULL
  1732. POSITION pos = GetFirstViewPosition();
  1733. if (pos == NULL)
  1734. return NULL;
  1735. // find the first view that is a CRichEdit2View
  1736. CView* pView;
  1737. while (pos != NULL)
  1738. {
  1739. pView = GetNextView(pos);
  1740. if (pView->IsKindOf(RUNTIME_CLASS(CRichEdit2View)))
  1741. return (CRichEdit2View*) pView;
  1742. }
  1743. // can't find one--return NULL
  1744. return NULL;
  1745. }
  1746. BOOL CRichEdit2Doc::IsModified()
  1747. {
  1748. return GetView()->GetRichEditCtrl().GetModify();
  1749. }
  1750. void CRichEdit2Doc::SetModifiedFlag(BOOL bModified)
  1751. {
  1752. GetView()->GetRichEditCtrl().SetModify(bModified);
  1753. ASSERT(!!GetView()->GetRichEditCtrl().GetModify() == !!bModified);
  1754. }
  1755. COleClientItem* CRichEdit2Doc::GetInPlaceActiveItem(CWnd* pWnd)
  1756. {
  1757. ASSERT_KINDOF(CRichEdit2View, pWnd);
  1758. CRichEdit2View* pView = (CRichEdit2View*)pWnd;
  1759. return pView->GetInPlaceActiveItem();
  1760. }
  1761. void CRichEdit2Doc::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
  1762. {
  1763. // we call CDocument and not COleServerDoc because we don't want to do the
  1764. // SetHostNames stuff here. The richedit will do it. And we tell the richedit
  1765. // in SetTitle
  1766. CDocument::SetPathName(lpszPathName, bAddToMRU);
  1767. }
  1768. void CRichEdit2Doc::SetTitle(LPCTSTR pwszTitle)
  1769. {
  1770. USES_CONVERSION;
  1771. COleServerDoc::SetTitle(pwszTitle);
  1772. CRichEdit2View *pView = GetView();
  1773. ASSERT(pView != NULL);
  1774. ASSERT(pView->m_lpRichEditOle != NULL);
  1775. LPCSTR pszAppName = WideToAnsiNewArray(AfxGetAppName());
  1776. if (pszAppName)
  1777. {
  1778. LPCSTR pszTitle = WideToAnsiNewArray(pwszTitle);
  1779. if (pszTitle)
  1780. {
  1781. pView->m_lpRichEditOle->SetHostNames(pszAppName, pszTitle);
  1782. delete [] pszTitle;
  1783. }
  1784. delete [] pszAppName;
  1785. }
  1786. }
  1787. CRichEdit2CntrItem* CRichEdit2Doc::LookupItem(LPOLEOBJECT lpobj) const
  1788. {
  1789. POSITION pos = COleServerDoc::GetStartPosition();
  1790. CRichEdit2CntrItem* pItem;
  1791. while (pos != NULL)
  1792. {
  1793. pItem = (CRichEdit2CntrItem*) COleServerDoc::GetNextItem(pos);
  1794. // delete item is right type and not under construction
  1795. if (pItem->IsKindOf(RUNTIME_CLASS(CRichEdit2CntrItem)) &&
  1796. pItem->m_lpObject == lpobj)
  1797. {
  1798. return pItem;
  1799. }
  1800. }
  1801. return NULL;
  1802. }
  1803. CRichEdit2CntrItem* CRichEdit2Doc::CreateClientItem(REOBJECT* preo) const
  1804. {
  1805. // cast away constness of this
  1806. return new CRichEdit2CntrItem(preo, (CRichEdit2Doc*)this);
  1807. // a derived class typically needs to return its own item of a class
  1808. // derived from CRichEdit2CntrItem
  1809. }
  1810. void CRichEdit2Doc::MarkItemsClear() const
  1811. {
  1812. POSITION pos = COleServerDoc::GetStartPosition();
  1813. CRichEdit2CntrItem* pItem;
  1814. while (pos != NULL)
  1815. {
  1816. pItem = (CRichEdit2CntrItem*) COleServerDoc::GetNextItem(pos);
  1817. // Mark item as not in use unless under construction (i.e. m_lpObject == NULL)
  1818. if (pItem->IsKindOf(RUNTIME_CLASS(CRichEdit2CntrItem)))
  1819. pItem->Mark( (pItem->m_lpObject == NULL) ? TRUE : FALSE);
  1820. }
  1821. }
  1822. void CRichEdit2Doc::DeleteUnmarkedItems() const
  1823. {
  1824. POSITION pos = COleServerDoc::GetStartPosition();
  1825. CRichEdit2CntrItem* pItem;
  1826. while (pos != NULL)
  1827. {
  1828. pItem = (CRichEdit2CntrItem*) COleServerDoc::GetNextItem(pos);
  1829. // Mark item as not in use unless under construction (i.e. m_lpObject == NULL)
  1830. if (pItem->IsKindOf(RUNTIME_CLASS(CRichEdit2CntrItem)) && !pItem->IsMarked())
  1831. delete pItem;
  1832. }
  1833. }
  1834. POSITION CRichEdit2Doc::GetStartPosition() const
  1835. {
  1836. if (m_bUpdateObjectCache)
  1837. ((CRichEdit2Doc*)this)->UpdateObjectCache(); //cast away const
  1838. return COleServerDoc::GetStartPosition();
  1839. }
  1840. void CRichEdit2Doc::UpdateObjectCache()
  1841. {
  1842. CRichEdit2View* pView = GetView();
  1843. CRichEdit2CntrItem* pItem;
  1844. if (pView != NULL)
  1845. {
  1846. ASSERT(pView->m_lpRichEditOle != NULL);
  1847. MarkItemsClear();
  1848. long i,nCount = pView->m_lpRichEditOle->GetObjectCount();
  1849. for (i=0;i<nCount;i++)
  1850. {
  1851. CRe2Object reo; // needs to be in here so destructor called to release interfaces
  1852. HRESULT hr = pView->m_lpRichEditOle->GetObject(i, &reo, REO_GETOBJ_ALL_INTERFACES);
  1853. //reo interfaces are UNICODE
  1854. ASSERT(SUCCEEDED(hr));
  1855. if (GetScode(hr) == S_OK)
  1856. {
  1857. pItem = LookupItem(reo.poleobj);
  1858. if (pItem == NULL)
  1859. {
  1860. pItem = ((CRichEdit2Doc*)this)->CreateClientItem(&reo);
  1861. pItem->UpdateItemType();
  1862. }
  1863. ASSERT(pItem != NULL);
  1864. pItem->Mark(TRUE);
  1865. }
  1866. }
  1867. DeleteUnmarkedItems();
  1868. }
  1869. m_bUpdateObjectCache = FALSE;
  1870. }
  1871. /////////////////////////////////////////////////////////////////////////////
  1872. // CRichEdit2Doc Attributes
  1873. COleClientItem* CRichEdit2Doc::GetPrimarySelectedItem(CView* pView)
  1874. {
  1875. ASSERT(pView->IsKindOf(RUNTIME_CLASS(CRichEdit2View)));
  1876. return ((CRichEdit2View*)pView)->GetSelectedItem();
  1877. }
  1878. /////////////////////////////////////////////////////////////////////////////
  1879. // CRichEdit2Doc Operations
  1880. void CRichEdit2Doc::DeleteContents()
  1881. {
  1882. COleServerDoc::DeleteContents();
  1883. CWaitCursor wait;
  1884. CRichEdit2View *pView = GetView();
  1885. if (pView != NULL)
  1886. {
  1887. pView->DeleteContents();
  1888. pView->GetRichEditCtrl().SetModify(FALSE);
  1889. ASSERT(pView->GetRichEditCtrl().GetModify() == FALSE);
  1890. }
  1891. }
  1892. /////////////////////////////////////////////////////////////////////////////
  1893. // CRichEdit2Doc serialization
  1894. void CRichEdit2Doc::Serialize(CArchive& ar)
  1895. {
  1896. CRichEdit2View *pView = GetView();
  1897. if (pView != NULL)
  1898. pView->Serialize(ar);
  1899. // we don't call the base class COleServerDoc::Serialize
  1900. // because we don't want the client items serialized
  1901. // the client items are handled directly by the RichEdit control
  1902. }
  1903. /////////////////////////////////////////////////////////////////////////////
  1904. // CRichEdit2Doc diagnostics
  1905. #ifdef _DEBUG
  1906. void CRichEdit2Doc::AssertValid() const
  1907. {
  1908. COleServerDoc::AssertValid();
  1909. }
  1910. void CRichEdit2Doc::Dump(CDumpContext& dc) const
  1911. {
  1912. COleServerDoc::Dump(dc);
  1913. }
  1914. #endif //_DEBUG
  1915. /////////////////////////////////////////////////////////////////////////////
  1916. // CRichEdit2Doc commands
  1917. void CRichEdit2Doc::PreCloseFrame(CFrameWnd* pFrameArg)
  1918. {
  1919. ASSERT_VALID(this);
  1920. ASSERT_VALID(pFrameArg);
  1921. // turn off redraw so the user doesn't see the deactivation happening
  1922. BOOL bSetRedraw = FALSE;
  1923. if (pFrameArg->GetStyle() & WS_VISIBLE)
  1924. {
  1925. pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)FALSE);
  1926. bSetRedraw = TRUE;
  1927. }
  1928. // deactivate any inplace active items on this frame
  1929. GetView()->m_lpRichEditOle->InPlaceDeactivate();
  1930. POSITION pos = GetStartPosition();
  1931. CRichEdit2CntrItem* pItem;
  1932. while (pos != NULL)
  1933. {
  1934. pItem = (CRichEdit2CntrItem*) GetNextClientItem(pos);
  1935. if (pItem == NULL)
  1936. break;
  1937. ASSERT(pItem->IsKindOf(RUNTIME_CLASS(CRichEdit2CntrItem)));
  1938. pItem->Close();
  1939. }
  1940. // turn redraw back on
  1941. if (bSetRedraw)
  1942. pFrameArg->SendMessage(WM_SETREDRAW, (WPARAM)TRUE);
  1943. }
  1944. void CRichEdit2Doc::UpdateModifiedFlag()
  1945. {
  1946. // don't do anything here
  1947. // let the richedit handle all of this
  1948. }
  1949. COleServerItem* CRichEdit2Doc::OnGetEmbeddedItem()
  1950. {
  1951. ASSERT(FALSE);
  1952. return NULL;
  1953. }
  1954. /////////////////////////////////////////////////////////////////////////////
  1955. // CRichEdit2CntrItem implementation
  1956. CRichEdit2CntrItem::CRichEdit2CntrItem(REOBJECT *preo, CRichEdit2Doc* pContainer)
  1957. : COleClientItem(pContainer)
  1958. {
  1959. m_bMark = FALSE;
  1960. m_bLock = FALSE;
  1961. if (preo != NULL)
  1962. {
  1963. ASSERT(preo->poleobj != NULL);
  1964. ASSERT(preo->pstg != NULL);
  1965. ASSERT(preo->polesite != NULL);
  1966. m_lpObject = preo->poleobj;
  1967. m_lpStorage = preo->pstg;
  1968. m_lpClientSite = preo->polesite;
  1969. m_lpObject->AddRef();
  1970. m_lpStorage->AddRef();
  1971. m_lpClientSite->AddRef();
  1972. }
  1973. else
  1974. {
  1975. m_lpObject = NULL;
  1976. m_lpStorage = NULL;
  1977. m_lpClientSite = NULL;
  1978. }
  1979. }
  1980. CRichEdit2CntrItem::~CRichEdit2CntrItem()
  1981. {
  1982. if (m_lpClientSite != NULL)
  1983. m_lpClientSite->Release();
  1984. }
  1985. void CRichEdit2CntrItem::OnDeactivateUI(BOOL bUndoable)
  1986. {
  1987. CView* pView = GetActiveView();
  1988. if (pView != NULL)
  1989. {
  1990. ASSERT(pView->GetParentFrame() != NULL);
  1991. pView->GetParentFrame()->SendMessage(WM_SETMESSAGESTRING,
  1992. (WPARAM)AFX_IDS_IDLEMESSAGE);
  1993. }
  1994. COleClientItem::OnDeactivateUI(bUndoable);
  1995. }
  1996. HRESULT CRichEdit2CntrItem::ShowContainerUI(BOOL b)
  1997. {
  1998. if (!CanActivate())
  1999. return E_NOTIMPL;
  2000. if (b)
  2001. {
  2002. OnDeactivateUI(FALSE);
  2003. OnDeactivate();
  2004. }
  2005. else
  2006. {
  2007. OnActivate();
  2008. OnActivateUI();
  2009. }
  2010. return S_OK;
  2011. }
  2012. BOOL CRichEdit2CntrItem::OnChangeItemPosition(const CRect& /*rectPos*/)
  2013. {
  2014. ASSERT_VALID(this);
  2015. // richedit handles this
  2016. return FALSE;
  2017. }
  2018. BOOL CRichEdit2CntrItem::CanActivate()
  2019. {
  2020. // Editing in-place while the server itself is being edited in-place
  2021. // does not work and is not supported. So, disable in-place
  2022. // activation in this case.
  2023. COleServerDoc* pDoc = DYNAMIC_DOWNCAST(COleServerDoc, GetDocument());
  2024. if (pDoc != NULL && pDoc->IsInPlaceActive())
  2025. return FALSE;
  2026. // otherwise, rely on default behavior
  2027. return COleClientItem::CanActivate();
  2028. }
  2029. HRESULT CRichEdit2CntrItem::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame,
  2030. LPOLEINPLACEUIWINDOW* lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
  2031. {
  2032. CRect rc1,rc2;
  2033. if (!CanActivate())
  2034. return E_NOTIMPL;
  2035. return m_xOleIPSite.GetWindowContext(lplpFrame, lplpDoc, &rc1, &rc2, lpFrameInfo);
  2036. }
  2037. BOOL CRichEdit2CntrItem::ConvertTo(REFCLSID clsidNew)
  2038. {
  2039. USES_CONVERSION;
  2040. LPRICHEDITOLE preole = GetDocument()->GetView()->m_lpRichEditOle;
  2041. LPOLESTR lpOleStr;
  2042. OleRegGetUserType(clsidNew, USERCLASSTYPE_FULL, &lpOleStr);
  2043. LPCTSTR pwsz = OLE2CT(lpOleStr);
  2044. BOOL bRet;
  2045. LPSTR psz = WideToAnsiNewArray(pwsz);
  2046. if (psz)
  2047. {
  2048. bRet = SUCCEEDED(preole->ConvertObject(REO_IOB_SELECTION, clsidNew, psz));
  2049. delete [] psz;
  2050. }
  2051. else
  2052. {
  2053. bRet = FALSE;
  2054. }
  2055. CoTaskMemFree(lpOleStr);
  2056. return (bRet);
  2057. }
  2058. BOOL CRichEdit2CntrItem::ActivateAs(LPCTSTR, REFCLSID clsidOld,
  2059. REFCLSID clsidNew)
  2060. {
  2061. LPRICHEDITOLE preole = GetDocument()->GetView()->m_lpRichEditOle;
  2062. HRESULT hRes = preole->ActivateAs(clsidOld, clsidNew);
  2063. return (SUCCEEDED(hRes));
  2064. }
  2065. void CRichEdit2CntrItem::SetDrawAspect(DVASPECT nDrawAspect)
  2066. {
  2067. LPRICHEDITOLE preole = GetDocument()->GetView()->m_lpRichEditOle;
  2068. preole->SetDvaspect(REO_IOB_SELECTION, nDrawAspect);
  2069. COleClientItem::SetDrawAspect(nDrawAspect);
  2070. }
  2071. void CRichEdit2CntrItem::SyncToRichEditObject(REOBJECT& reo)
  2072. {
  2073. COleClientItem::SetDrawAspect((DVASPECT)reo.dvaspect);
  2074. }
  2075. /////////////////////////////////////////////////////////////////////////////
  2076. // CRichEdit2CntrItem diagnostics
  2077. #ifdef _DEBUG
  2078. void CRichEdit2CntrItem::AssertValid() const
  2079. {
  2080. COleClientItem::AssertValid();
  2081. }
  2082. void CRichEdit2CntrItem::Dump(CDumpContext& dc) const
  2083. {
  2084. COleClientItem::Dump(dc);
  2085. }
  2086. #endif
  2087. /////////////////////////////////////////////////////////////////////////////
  2088. LPOLECLIENTSITE CRichEdit2CntrItem::GetClientSite()
  2089. {
  2090. if (m_lpClientSite == NULL)
  2091. {
  2092. CRichEdit2Doc* pDoc = DYNAMIC_DOWNCAST(CRichEdit2Doc, GetDocument());
  2093. CRichEdit2View* pView = DYNAMIC_DOWNCAST(CRichEdit2View, pDoc->GetView());
  2094. ASSERT(pView->m_lpRichEditOle != NULL);
  2095. HRESULT hr = pView->m_lpRichEditOle->GetClientSite(&m_lpClientSite);
  2096. if (hr != S_OK)
  2097. AfxThrowOleException(hr);
  2098. }
  2099. ASSERT(m_lpClientSite != NULL);
  2100. return m_lpClientSite;
  2101. }
  2102. /////////////////////////////////////////////////////////////////////////////
  2103. #ifndef _AFX_ENABLE_INLINES
  2104. static const char _szAfxWinInl[] = "afxrich2.inl";
  2105. #undef THIS_FILE
  2106. #define THIS_FILE _szAfxWinInl
  2107. #define _AFXRICH_INLINE
  2108. #include "afxrich2.inl"
  2109. #endif //_AFX_ENABLE_INLINES
  2110. /////////////////////////////////////////////////////////////////////////////
  2111. #ifdef AFX_INIT_SEG
  2112. #pragma code_seg(AFX_INIT_SEG)
  2113. #endif
  2114. IMPLEMENT_SERIAL(CRichEdit2CntrItem, COleClientItem, 0)
  2115. IMPLEMENT_DYNAMIC(CRichEdit2Doc, COleServerDoc)
  2116. IMPLEMENT_DYNCREATE(CRichEdit2View, CCtrlView)
  2117. /////////////////////////////////////////////////////////////////////////////