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.

1697 lines
48 KiB

  1. // wordpvw.cpp : implementation of the CWordPadView class
  2. //
  3. // Copyright (C) 1992-1999 Microsoft Corporation
  4. #include "stdafx.h"
  5. #include "wordpad.h"
  6. #include "cntritem.h"
  7. #include "srvritem.h"
  8. #include "wordpdoc.h"
  9. #include "wordpvw.h"
  10. #include "formatta.h"
  11. #include "datedial.h"
  12. #include "formatpa.h"
  13. #include "formatba.h"
  14. #include "ruler.h"
  15. #include "strings.h"
  16. #include "colorlis.h"
  17. #include "pageset.h"
  18. #include <penwin.h>
  19. #include "fixhelp.h"
  20. #include <afxprntx.h>
  21. #include "dlgprnt2.cpp"
  22. #ifndef PD_CURRENTPAGE
  23. #define PD_CURRENTPAGE 0x00400000
  24. #define PD_NOCURRENTPAGE 0x00800000
  25. #endif
  26. extern CLIPFORMAT cfEmbeddedObject;
  27. extern CLIPFORMAT cfRTO;
  28. BOOL g_fInternalDragDrop = FALSE ;
  29. BOOL g_fRightButtonDrag = FALSE;
  30. #ifdef _DEBUG
  31. #undef THIS_FILE
  32. #endif
  33. BOOL CWordPadView::m_bIsMirrored = FALSE;
  34. BOOL CCharFormat::operator==(CCharFormat& cf)
  35. {
  36. return
  37. dwMask == cf.dwMask
  38. && dwEffects == cf.dwEffects
  39. && yHeight == cf.yHeight
  40. && yOffset == cf.yOffset
  41. && crTextColor == cf.crTextColor
  42. && bPitchAndFamily == cf.bPitchAndFamily
  43. && (lstrcmp(szFaceName, cf.szFaceName) == 0);
  44. }
  45. BOOL CParaFormat::operator==(PARAFORMAT& pf)
  46. {
  47. if(
  48. dwMask != pf.dwMask
  49. || wNumbering != pf.wNumbering
  50. || wReserved != pf.wReserved
  51. || dxStartIndent != pf.dxStartIndent
  52. || dxRightIndent != pf.dxRightIndent
  53. || dxOffset != pf.dxOffset
  54. || cTabCount != pf.cTabCount
  55. )
  56. {
  57. return FALSE;
  58. }
  59. for (int i=0;i<pf.cTabCount;i++)
  60. {
  61. if (rgxTabs[i] != pf.rgxTabs[i])
  62. return FALSE;
  63. }
  64. return TRUE;
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CWordPadView
  68. IMPLEMENT_DYNCREATE(CWordPadView, CRichEdit2View)
  69. //WM_WININICHANGE -- default printer might have changed
  70. //WM_FONTCHANGE -- pool of fonts changed
  71. //WM_DEVMODECHANGE -- printer settings changes
  72. BEGIN_MESSAGE_MAP(CWordPadView, CRichEdit2View)
  73. ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
  74. ON_COMMAND(ID_CANCEL_EDIT_CNTR, OnCancelEditCntr)
  75. ON_COMMAND(ID_CANCEL_EDIT_SRVR, OnCancelEditSrvr)
  76. //{{AFX_MSG_MAP(CWordPadView)
  77. ON_COMMAND(ID_PAGE_SETUP, OnPageSetup)
  78. ON_COMMAND(ID_CHAR_BOLD, OnCharBold)
  79. ON_UPDATE_COMMAND_UI(ID_CHAR_BOLD, OnUpdateCharBold)
  80. ON_COMMAND(ID_CHAR_ITALIC, OnCharItalic)
  81. ON_UPDATE_COMMAND_UI(ID_CHAR_ITALIC, OnUpdateCharItalic)
  82. ON_COMMAND(ID_CHAR_UNDERLINE, OnCharUnderline)
  83. ON_UPDATE_COMMAND_UI(ID_CHAR_UNDERLINE, OnUpdateCharUnderline)
  84. ON_COMMAND(ID_PARA_CENTER, OnParaCenter)
  85. ON_UPDATE_COMMAND_UI(ID_PARA_CENTER, OnUpdateParaCenter)
  86. ON_COMMAND(ID_PARA_LEFT, OnParaLeft)
  87. ON_UPDATE_COMMAND_UI(ID_PARA_LEFT, OnUpdateParaLeft)
  88. ON_COMMAND(ID_PARA_RIGHT, OnParaRight)
  89. ON_UPDATE_COMMAND_UI(ID_PARA_RIGHT, OnUpdateParaRight)
  90. ON_WM_CREATE()
  91. ON_COMMAND(ID_INSERT_DATE_TIME, OnInsertDateTime)
  92. ON_COMMAND(ID_FORMAT_PARAGRAPH, OnFormatParagraph)
  93. ON_COMMAND(ID_FORMAT_FONT, OnFormatFont)
  94. ON_COMMAND(ID_EDIT_PASTE_SPECIAL, OnEditPasteSpecial)
  95. ON_COMMAND(ID_OLE_EDIT_PROPERTIES, OnEditProperties)
  96. ON_COMMAND(ID_EDIT_FIND, OnEditFind)
  97. ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace)
  98. ON_COMMAND(ID_FORMAT_TABS, OnFormatTabs)
  99. ON_COMMAND(ID_COLOR16, OnColorDefault)
  100. ON_WM_TIMER()
  101. ON_WM_DESTROY()
  102. ON_WM_MEASUREITEM()
  103. ON_COMMAND(ID_PEN_BACKSPACE, OnPenBackspace)
  104. ON_COMMAND(ID_PEN_NEWLINE, OnPenNewline)
  105. ON_COMMAND(ID_PEN_PERIOD, OnPenPeriod)
  106. ON_COMMAND(ID_PEN_SPACE, OnPenSpace)
  107. ON_WM_SIZE()
  108. ON_WM_KEYDOWN()
  109. ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
  110. ON_COMMAND(ID_FILE_PRINT_DIRECT, OnFilePrint)
  111. ON_WM_DROPFILES()
  112. ON_COMMAND(ID_PEN_LENS, OnPenLens)
  113. ON_COMMAND(ID_PEN_TAB, OnPenTab)
  114. ON_COMMAND(ID_DELAYED_INVALIDATE, OnDelayedInvalidate)
  115. ON_WM_PALETTECHANGED()
  116. ON_WM_QUERYNEWPALETTE()
  117. ON_WM_WININICHANGE()
  118. //}}AFX_MSG_MAP
  119. // Standard printing commands
  120. ON_COMMAND(ID_INSERT_BULLET, CRichEdit2View::OnBullet)
  121. ON_UPDATE_COMMAND_UI(ID_INSERT_BULLET, CRichEdit2View::OnUpdateBullet)
  122. ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
  123. ON_COMMAND_RANGE(ID_COLOR0, ID_COLOR16, OnColorPick)
  124. ON_EN_CHANGE(AFX_IDW_PANE_FIRST, OnEditChange)
  125. ON_WM_MOUSEACTIVATE()
  126. ON_REGISTERED_MESSAGE(CWordPadApp::m_nPrinterChangedMsg, OnPrinterChangedMsg)
  127. ON_NOTIFY(FN_GETFORMAT, ID_VIEW_FORMATBAR, OnGetCharFormat)
  128. ON_NOTIFY(FN_SETFORMAT, ID_VIEW_FORMATBAR, OnSetCharFormat)
  129. ON_NOTIFY(NM_SETFOCUS, ID_VIEW_FORMATBAR, OnBarSetFocus)
  130. ON_NOTIFY(NM_KILLFOCUS, ID_VIEW_FORMATBAR, OnBarKillFocus)
  131. ON_NOTIFY(NM_RETURN, ID_VIEW_FORMATBAR, OnBarReturn)
  132. END_MESSAGE_MAP()
  133. /////////////////////////////////////////////////////////////////////////////
  134. // CWordPadView construction/destruction
  135. CWordPadView::CWordPadView()
  136. {
  137. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  138. m_uTimerID = 0;
  139. m_bDelayUpdateItems = FALSE;
  140. m_bOnBar = FALSE;
  141. m_bInPrint = FALSE;
  142. m_nPasteType = 0;
  143. m_rectMargin = theApp.m_rectPageMargin;
  144. }
  145. BOOL CWordPadView::PreCreateWindow(CREATESTRUCT& cs)
  146. {
  147. BOOL bRes = CRichEdit2View::PreCreateWindow(cs);
  148. cs.style |= ES_SELECTIONBAR;
  149. return bRes;
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. // CWordPadView attributes
  153. BOOL CWordPadView::IsFormatText()
  154. {
  155. // this function checks to see if any formatting is not default text
  156. BOOL bRes = FALSE;
  157. CHARRANGE cr;
  158. CCharFormat cf;
  159. CParaFormat pf;
  160. GetRichEditCtrl().GetSel(cr);
  161. GetRichEditCtrl().HideSelection(TRUE, FALSE);
  162. GetRichEditCtrl().SetSel(0,-1);
  163. if (!(GetRichEditCtrl().GetSelectionType() & (SEL_OBJECT|SEL_MULTIOBJECT)))
  164. {
  165. GetRichEditCtrl().GetSelectionCharFormat(cf);
  166. //
  167. // Richedit sometimes returns these masks which are not important to us
  168. //
  169. cf.dwMask &= ~(CFM_LINK | CFM_CHARSET) ;
  170. //
  171. // Richedit sometimes returns the wrong thing here. This is not that
  172. // important for the CHARFORMAT comparison, but it fouls things up if
  173. // we don't work around it.
  174. //
  175. CCharFormat defCF;
  176. GetDefaultFont(defCF, TRUE);
  177. cf.bPitchAndFamily = defCF.bPitchAndFamily ;
  178. if (cf == defCF)
  179. {
  180. GetRichEditCtrl().GetParaFormat(pf);
  181. // These get reset in SetDefaultFont so be symmetric.
  182. pf.dwMask &= ~ (PFM_RTLPARA | PFM_ALIGNMENT);
  183. if (pf == m_defParaFormat)
  184. bRes = TRUE;
  185. }
  186. }
  187. GetRichEditCtrl().SetSel(cr);
  188. GetRichEditCtrl().HideSelection(FALSE, FALSE);
  189. return bRes;
  190. }
  191. HMENU CWordPadView::GetContextMenu(WORD, LPOLEOBJECT, CHARRANGE* )
  192. {
  193. CRichEdit2CntrItem* pItem = GetSelectedItem();
  194. if (pItem == NULL || !pItem->IsInPlaceActive())
  195. {
  196. CMenu menuText;
  197. menuText.LoadMenu(IDR_TEXT_POPUP);
  198. CMenu* pMenuPopup = menuText.GetSubMenu(0);
  199. menuText.RemoveMenu(0, MF_BYPOSITION);
  200. if (!GetSystemMetrics(SM_PENWINDOWS))
  201. {
  202. //delete pen specific stuff
  203. // remove Insert Keystrokes
  204. pMenuPopup->DeleteMenu(ID_PEN_LENS, MF_BYCOMMAND);
  205. int nIndex = pMenuPopup->GetMenuItemCount()-1; //index of last item
  206. // remove Edit Text...
  207. pMenuPopup->DeleteMenu(nIndex, MF_BYPOSITION);
  208. // remove separator
  209. pMenuPopup->DeleteMenu(nIndex-1, MF_BYPOSITION);
  210. }
  211. return pMenuPopup->Detach();
  212. }
  213. return NULL;
  214. }
  215. /////////////////////////////////////////////////////////////////////////////
  216. // CWordPadView operations
  217. void CWordPadView::MirrorTheContainer(BOOL bMirror)
  218. {
  219. // if WordPad not mirrored, then don't do anything
  220. LONG lExStyle;
  221. if (!m_bIsMirrored)
  222. return;
  223. CWnd *pWnd = AfxGetMainWnd() ;
  224. if (NULL == pWnd)
  225. return ;
  226. lExStyle = (LONG)::GetWindowLongPtr(pWnd->m_hWnd , GWL_EXSTYLE);
  227. if (bMirror)
  228. lExStyle |= WS_EX_LAYOUTRTL;
  229. else
  230. lExStyle &= ~WS_EX_LAYOUTRTL;
  231. ::SetWindowLongPtr(pWnd->m_hWnd , GWL_EXSTYLE , lExStyle);
  232. }
  233. void CWordPadView::WrapChanged()
  234. {
  235. CWaitCursor wait;
  236. CFrameWnd* pFrameWnd = GetParentFrame();
  237. ASSERT(pFrameWnd != NULL);
  238. pFrameWnd->SetMessageText(IDS_FORMATTING);
  239. CWnd* pBarWnd = pFrameWnd->GetMessageBar();
  240. if (pBarWnd != NULL)
  241. pBarWnd->UpdateWindow();
  242. CRichEdit2View::WrapChanged();
  243. pFrameWnd->SetMessageText(AFX_IDS_IDLEMESSAGE);
  244. if (pBarWnd != NULL)
  245. pBarWnd->UpdateWindow();
  246. }
  247. void CWordPadView::SetUpdateTimer()
  248. {
  249. if (m_uTimerID != 0) // if outstanding timer kill it
  250. KillTimer(m_uTimerID);
  251. m_uTimerID = SetTimer(1, 1000, NULL); //set a timer for 1000 milliseconds
  252. if (m_uTimerID == 0) // no timer available so force update now
  253. GetDocument()->UpdateAllItems(NULL);
  254. else
  255. m_bDelayUpdateItems = TRUE;
  256. }
  257. void CWordPadView::DeleteContents()
  258. {
  259. ASSERT_VALID(this);
  260. ASSERT(m_hWnd != NULL);
  261. CRichEdit2View::DeleteContents();
  262. SetDefaultFont(IsTextType(GetDocument()->m_nNewDocType));
  263. }
  264. void CWordPadView::SetDefaultFont(BOOL bText)
  265. {
  266. ASSERT_VALID(this);
  267. ASSERT(m_hWnd != NULL);
  268. CCharFormat cf;
  269. m_bSyncCharFormat = m_bSyncParaFormat = TRUE;
  270. // set the default character format -- the FALSE makes it the default
  271. GetDefaultFont(cf, bText);
  272. GetRichEditCtrl().SetSel(0,-1);
  273. GetRichEditCtrl().SetDefaultCharFormat(cf);
  274. GetRichEditCtrl().SetSelectionCharFormat(cf);
  275. //
  276. // Setting the charformat with a NULL font name automagically sets
  277. // the reading direction and alignment. Don't muck with it.
  278. //
  279. m_defParaFormat.dwMask &= ~ (PFM_RTLPARA | PFM_ALIGNMENT);
  280. GetRichEditCtrl().SetParaFormat(m_defParaFormat);
  281. GetRichEditCtrl().SetSel(0,0);
  282. GetRichEditCtrl().EmptyUndoBuffer();
  283. GetRichEditCtrl().SetModify(FALSE);
  284. ASSERT_VALID(this);
  285. }
  286. /////////////////////////////////////////////////////////////////////////////
  287. // CWordPadView drawing
  288. /////////////////////////////////////////////////////////////////////////////
  289. // CWordPadView printing
  290. void CWordPadView::OnBeginPrinting(CDC* pDC, CPrintInfo* printInfo)
  291. {
  292. ASSERT_VALID(this);
  293. ASSERT_VALID(pDC);
  294. // initialize page start vector
  295. ASSERT(m_aPageStart.GetSize() == 0);
  296. ASSERT(NULL != printInfo);
  297. ASSERT(NULL != printInfo->m_pPD);
  298. OnPrinterChanged(*pDC);
  299. //
  300. // Copy some flags from PRINTDLGEX to PRINTDLG that mfc doesn't
  301. //
  302. C_PrintDialogEx *pPDEx = (C_PrintDialogEx *) printInfo->m_pPD;
  303. pPDEx->m_pd.Flags |= pPDEx->m_pdex.Flags & PD_SELECTION;
  304. m_aPageStart.Add(0);
  305. ASSERT(m_aPageStart.GetSize() > 0);
  306. if (printInfo->m_pPD->PrintSelection())
  307. {
  308. CHARRANGE range;
  309. GetRichEditCtrl().GetSel(range);
  310. m_aPageStart[0] = range.cpMin;
  311. }
  312. GetRichEditCtrl().FormatRange(NULL, FALSE); // required by RichEdit to clear out cache
  313. ASSERT_VALID(this);
  314. }
  315. void CWordPadView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
  316. {
  317. ASSERT_VALID(this);
  318. ASSERT_VALID(pDC);
  319. ASSERT(pInfo != NULL);
  320. ASSERT(pInfo->m_bContinuePrinting);
  321. ASSERT(NULL != pInfo->m_pPD);
  322. UINT nPage = pInfo->m_nCurPage;
  323. ASSERT(nPage <= (UINT)m_aPageStart.GetSize());
  324. long nIndex = (long) m_aPageStart[nPage-1];
  325. BOOL bPrintSelection = pInfo->m_pPD->PrintSelection();
  326. long nFinalCharIndex;
  327. if (bPrintSelection)
  328. {
  329. CHARRANGE range;
  330. GetRichEditCtrl().GetSel(range);
  331. nFinalCharIndex = range.cpMax;
  332. }
  333. else
  334. {
  335. GETTEXTLENGTHEX textlen;
  336. textlen.flags = GTL_DEFAULT;
  337. #ifdef UNICODE
  338. textlen.codepage = 1200; // Unicode code page
  339. #else
  340. textlen.codepage = CP_ACP;
  341. #endif
  342. nFinalCharIndex = (long)this->SendMessage(
  343. EM_GETTEXTLENGTHEX,
  344. (WPARAM) &textlen,
  345. 0);
  346. }
  347. // print as much as possible in the current page.
  348. nIndex = PrintPage(pDC, nIndex, nFinalCharIndex);
  349. if (nIndex >= nFinalCharIndex)
  350. {
  351. TRACE0("End of Document\n");
  352. pInfo->SetMaxPage(nPage);
  353. pInfo->m_bContinuePrinting = FALSE;
  354. }
  355. // update pagination information for page just printed
  356. if (nPage == (UINT)m_aPageStart.GetSize())
  357. {
  358. if (nIndex < nFinalCharIndex)
  359. m_aPageStart.Add(nIndex);
  360. }
  361. else
  362. {
  363. ASSERT(nPage+1 <= (UINT)m_aPageStart.GetSize());
  364. ASSERT(nIndex == (long)m_aPageStart[nPage+1-1]);
  365. }
  366. if (pInfo != NULL && pInfo->m_bPreview)
  367. DrawMargins(pDC);
  368. }
  369. void CWordPadView::DrawMargins(CDC* pDC)
  370. {
  371. if (pDC->m_hAttribDC != NULL)
  372. {
  373. CRect rect;
  374. rect.left = m_rectMargin.left;
  375. rect.right = m_sizePaper.cx - m_rectMargin.right;
  376. rect.top = m_rectMargin.top;
  377. rect.bottom = m_sizePaper.cy - m_rectMargin.bottom;
  378. //rect in twips
  379. int logx = ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSX);
  380. int logy = ::GetDeviceCaps(pDC->m_hDC, LOGPIXELSY);
  381. rect.left = MulDiv(rect.left, logx, 1440);
  382. rect.right = MulDiv(rect.right, logx, 1440);
  383. rect.top = MulDiv(rect.top, logy, 1440);
  384. rect.bottom = MulDiv(rect.bottom, logy, 1440);
  385. CPen pen(PS_DOT, 0, pDC->GetTextColor());
  386. CPen* ppen = pDC->SelectObject(&pen);
  387. pDC->MoveTo(0, rect.top);
  388. pDC->LineTo(10000, rect.top);
  389. pDC->MoveTo(rect.left, 0);
  390. pDC->LineTo(rect.left, 10000);
  391. pDC->MoveTo(0, rect.bottom);
  392. pDC->LineTo(10000, rect.bottom);
  393. pDC->MoveTo(rect.right, 0);
  394. pDC->LineTo(rect.right, 10000);
  395. pDC->SelectObject(ppen);
  396. }
  397. }
  398. BOOL CWordPadView::OnPreparePrinting(CPrintInfo* pInfo)
  399. {
  400. CWordPadApp *pApp = NULL ;
  401. //
  402. // Swap out the default print dialog with the new PrintDlgEx version.
  403. // Hopefully MFC will come up with a better way to do this sometime.
  404. //
  405. C_PrintDialogEx *pPDEx = new C_PrintDialogEx(FALSE, PD_RETURNDC | PD_ALLPAGES | PD_NOSELECTION | PD_NOCURRENTPAGE | PD_USEDEVMODECOPIESANDCOLLATE);
  406. if (NULL == pPDEx)
  407. return FALSE;
  408. m_oldprintdlg = pInfo->m_pPD;
  409. pInfo->m_pPD = pPDEx;
  410. pInfo->SetMinPage(1);
  411. pInfo->SetMaxPage(0xffff);
  412. pInfo->m_pPD->m_pd.nFromPage = 1;
  413. pInfo->m_pPD->m_pd.nToPage = 1;
  414. pApp = (CWordPadApp *) AfxGetApp() ;
  415. if (NULL != pApp)
  416. {
  417. if ( (pApp->cmdInfo.m_nShellCommand == CCommandLineInfo::FilePrintTo) ||
  418. (pApp->cmdInfo.m_nShellCommand == CCommandLineInfo::FilePrint) )
  419. {
  420. if (pInfo->m_pPD->m_pd.hDevNames == NULL)
  421. {
  422. HGLOBAL hDn = pApp->GetDevNames() ;
  423. if (hDn != NULL)
  424. {
  425. pInfo->m_pPD->m_pd.hDevNames = hDn ;
  426. }
  427. }
  428. }
  429. }
  430. if (SEL_EMPTY != GetRichEditCtrl().GetSelectionType())
  431. {
  432. pInfo->m_pPD->m_pd.Flags = pInfo->m_pPD->m_pd.Flags & ~PD_NOSELECTION;
  433. pPDEx->m_pdex.Flags = pPDEx->m_pdex.Flags & ~PD_NOSELECTION;
  434. }
  435. return DoPreparePrinting(pInfo);
  436. }
  437. void CWordPadView::OnEndPrinting(CDC*dc, CPrintInfo*pInfo)
  438. {
  439. ASSERT_VALID(this);
  440. //
  441. // Swap the original print dlg back
  442. //
  443. delete (C_PrintDialogEx *) pInfo->m_pPD;
  444. pInfo->m_pPD = m_oldprintdlg;
  445. m_oldprintdlg = NULL;
  446. CRichEdit2View::OnEndPrinting(dc, pInfo);
  447. }
  448. void CWordPadView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  449. {
  450. ASSERT_VALID(this);
  451. ASSERT_VALID(pDC);
  452. ASSERT(pInfo != NULL); // overriding OnPaint -- never get this.
  453. if (!pInfo->m_bContinuePrinting)
  454. return;
  455. pDC->SetMapMode(MM_TEXT);
  456. if (pInfo->m_nCurPage > (UINT)m_aPageStart.GetSize() &&
  457. !PaginateTo(pDC, pInfo))
  458. {
  459. // can't paginate to that page, thus cannot print it.
  460. pInfo->m_bContinuePrinting = FALSE;
  461. }
  462. ASSERT_VALID(this);
  463. }
  464. BOOL CWordPadView::PaginateTo(CDC* pDC, CPrintInfo* pInfo)
  465. // attempts pagination to pInfo->m_nCurPage, TRUE == success
  466. {
  467. ASSERT_VALID(this);
  468. ASSERT_VALID(pDC);
  469. CRect rectSave = pInfo->m_rectDraw;
  470. UINT nPageSave = pInfo->m_nCurPage;
  471. ASSERT(nPageSave > 1);
  472. ASSERT(nPageSave >= (UINT)m_aPageStart.GetSize());
  473. pDC->IntersectClipRect(0, 0, 0, 0);
  474. pInfo->m_nCurPage = (UINT)m_aPageStart.GetSize();
  475. while (pInfo->m_nCurPage < nPageSave)
  476. {
  477. ASSERT(pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize());
  478. OnPrepareDC(pDC, pInfo);
  479. ASSERT(pInfo->m_bContinuePrinting);
  480. pInfo->m_rectDraw.SetRect(0, 0,
  481. pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
  482. pDC->DPtoLP(&pInfo->m_rectDraw);
  483. OnPrint(pDC, pInfo);
  484. if (pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize())
  485. break;
  486. ++pInfo->m_nCurPage;
  487. }
  488. BOOL bResult = pInfo->m_nCurPage == nPageSave;
  489. pInfo->m_nCurPage = nPageSave;
  490. pInfo->m_rectDraw = rectSave;
  491. pDC->SelectClipRgn(NULL) ;
  492. ASSERT_VALID(this);
  493. return bResult;
  494. }
  495. /////////////////////////////////////////////////////////////////////////////
  496. // OLE Client support and commands
  497. inline int roundleast(int n)
  498. {
  499. int mod = n%10;
  500. n -= mod;
  501. if (mod >= 5)
  502. n += 10;
  503. else if (mod <= -5)
  504. n -= 10;
  505. return n;
  506. }
  507. static void RoundRect(FAR UNALIGNED RECT *r1)
  508. {
  509. r1->left = roundleast(r1->left);
  510. r1->right = roundleast(r1->right);
  511. r1->top = roundleast(r1->top);
  512. r1->bottom = roundleast(r1->bottom);
  513. }
  514. static void MulDivRect(FAR UNALIGNED RECT *r1, FAR UNALIGNED RECT * r2, int num, int div)
  515. {
  516. r1->left = MulDiv(r2->left, num, div);
  517. r1->top = MulDiv(r2->top, num, div);
  518. r1->right = MulDiv(r2->right, num, div);
  519. r1->bottom = MulDiv(r2->bottom, num, div);
  520. }
  521. void CWordPadView::OnPageSetup()
  522. {
  523. theApp.EnsurePrinterIsInitialized();
  524. CPageSetupDialog dlg;
  525. PAGESETUPDLG& psd = dlg.m_psd;
  526. BOOL bMetric = theApp.GetUnits() == 1; //centimeters
  527. BOOL fUpdateWrap = FALSE ;
  528. psd.Flags |= PSD_MARGINS | (bMetric ? PSD_INHUNDREDTHSOFMILLIMETERS :
  529. PSD_INTHOUSANDTHSOFINCHES);
  530. int nUnitsPerInch = bMetric ? 2540 : 1000;
  531. MulDivRect(&psd.rtMargin, m_rectMargin, nUnitsPerInch, 1440);
  532. RoundRect(&psd.rtMargin);
  533. // get the current device from the app
  534. PRINTDLG pd;
  535. pd.hDevNames = NULL;
  536. pd.hDevMode = NULL;
  537. theApp.GetPrinterDeviceDefaults(&pd);
  538. psd.hDevNames = pd.hDevNames;
  539. psd.hDevMode = pd.hDevMode;
  540. SetHelpFixHook() ;
  541. if (dlg.DoModal() == IDOK)
  542. {
  543. RoundRect(&psd.rtMargin);
  544. MulDivRect(m_rectMargin, &psd.rtMargin, 1440, nUnitsPerInch);
  545. theApp.m_rectPageMargin = m_rectMargin;
  546. //
  547. // SelectPrinter will free the existing devnames and devmodes if the
  548. // third parameter is TRUE. We don't want to do that because the
  549. // print dialog frees them and allocates new ones.
  550. //
  551. theApp.SelectPrinter(psd.hDevNames, psd.hDevMode, FALSE);
  552. theApp.NotifyPrinterChanged();
  553. fUpdateWrap = TRUE ;
  554. }
  555. RemoveHelpFixHook() ;
  556. // PageSetupDlg failed
  557. if (CommDlgExtendedError() != 0)
  558. {
  559. CPageSetupDlg dlg;
  560. dlg.m_nBottomMargin = m_rectMargin.bottom;
  561. dlg.m_nLeftMargin = m_rectMargin.left;
  562. dlg.m_nRightMargin = m_rectMargin.right;
  563. dlg.m_nTopMargin = m_rectMargin.top;
  564. if (dlg.DoModal() == IDOK)
  565. {
  566. m_rectMargin.SetRect(dlg.m_nLeftMargin, dlg.m_nTopMargin,
  567. dlg.m_nRightMargin, dlg.m_nBottomMargin);
  568. // m_page will be changed at this point
  569. theApp.m_rectPageMargin = m_rectMargin;
  570. theApp.NotifyPrinterChanged();
  571. fUpdateWrap = TRUE ;
  572. }
  573. }
  574. if (fUpdateWrap)
  575. {
  576. CRichEdit2View::WrapChanged();
  577. }
  578. }
  579. /////////////////////////////////////////////////////////////////////////////
  580. // OLE Server support
  581. // The following command handler provides the standard keyboard
  582. // user interface to cancel an in-place editing session. Here,
  583. // the server (not the container) causes the deactivation.
  584. void CWordPadView::OnCancelEditSrvr()
  585. {
  586. GetDocument()->OnDeactivateUI(FALSE);
  587. }
  588. /////////////////////////////////////////////////////////////////////////////
  589. // CWordPadView diagnostics
  590. #ifdef _DEBUG
  591. void CWordPadView::AssertValid() const
  592. {
  593. CRichEdit2View::AssertValid();
  594. }
  595. void CWordPadView::Dump(CDumpContext& dc) const
  596. {
  597. CRichEdit2View::Dump(dc);
  598. }
  599. CWordPadDoc* CWordPadView::GetDocument() // non-debug version is inline
  600. {
  601. return (CWordPadDoc*)m_pDocument;
  602. }
  603. #endif //_DEBUG
  604. /////////////////////////////////////////////////////////////////////////////
  605. // CWordPadView message helpers
  606. /////////////////////////////////////////////////////////////////////////////
  607. // CWordPadView message handlers
  608. int CWordPadView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  609. {
  610. if (CRichEdit2View::OnCreate(lpCreateStruct) == -1)
  611. return -1;
  612. theApp.m_listPrinterNotify.AddTail(m_hWnd);
  613. if (theApp.m_bWordSel)
  614. GetRichEditCtrl().SetOptions(ECOOP_OR, ECO_AUTOWORDSELECTION);
  615. else
  616. GetRichEditCtrl().SetOptions(ECOOP_AND, ~(DWORD)ECO_AUTOWORDSELECTION);
  617. // GetRichEditCtrl().SetOptions(ECOOP_OR, ECO_SELECTIONBAR);
  618. GetRichEditCtrl().GetParaFormat(m_defParaFormat);
  619. m_defParaFormat.cTabCount = 0;
  620. //
  621. // Insert our own wrapper interface callback here to get around MFC defaults
  622. //
  623. VERIFY(GetRichEditCtrl().SetOLECallback(&m_xWordPadRichEditOleCallback));
  624. if (::GetWindowLongPtr(::GetParent(m_hWnd) , GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
  625. m_bIsMirrored = TRUE;
  626. return 0;
  627. }
  628. void CWordPadView::GetDefaultFont(CCharFormat& cf, BOOL bText)
  629. {
  630. USES_CONVERSION;
  631. CString strDefFont;
  632. if (bText)
  633. VERIFY(strDefFont.LoadString(IDS_DEFAULTTEXTFONT));
  634. ASSERT(cf.cbSize == sizeof(CHARFORMAT));
  635. cf.dwMask = CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_SIZE|
  636. CFM_COLOR|CFM_OFFSET|CFM_PROTECTED;
  637. cf.dwEffects = CFE_AUTOCOLOR;
  638. cf.yHeight = 200; //10pt
  639. cf.yOffset = 0;
  640. cf.crTextColor = RGB(0, 0, 0);
  641. cf.bCharSet = 0;
  642. cf.bPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  643. EVAL(StringCchCopy(cf.szFaceName, ARRAYSIZE(cf.szFaceName), strDefFont) == S_OK);
  644. cf.dwMask |= CFM_FACE;
  645. }
  646. void CWordPadView::OnInsertDateTime()
  647. {
  648. // When changing the paragraph direction by Ctrl+Shift the m_bSyncParaFormat
  649. // will not reset. we reset it to force GetParaFormatSelection read current
  650. // paragraph direction by calling GetRichEditCtrl().GetParaFormat()
  651. m_bSyncParaFormat = TRUE;
  652. CDateDialog dlg(NULL , GetParaFormatSelection());
  653. if (dlg.DoModal() == IDOK)
  654. {
  655. GetRichEditCtrl().ReplaceSel(dlg.m_strSel, TRUE);
  656. }
  657. }
  658. void CWordPadView::OnFormatParagraph()
  659. {
  660. CFormatParaDlg dlg(GetParaFormatSelection());
  661. dlg.m_nWordWrap = m_nWordWrap;
  662. if (dlg.DoModal() == IDOK)
  663. SetParaFormat(dlg.m_pf);
  664. }
  665. void CWordPadView::OnFormatTabs()
  666. {
  667. CFormatTabDlg dlg(GetParaFormatSelection());
  668. if (dlg.DoModal() == IDOK)
  669. SetParaFormat(dlg.m_pf);
  670. }
  671. void CWordPadView::OnTextNotFound(LPCTSTR /* UNREF lpStr */)
  672. {
  673. ASSERT_VALID(this);
  674. // HACKHACK:
  675. //
  676. // When AfxMessageBox is called MFC disables the find dialog and pops up
  677. // the message box. After the user dismisses it, User tries to set the
  678. // focus back to the window that had it before the message box, however
  679. // this window is disabled so eventually what ends up happening is that
  680. // the find dialog, and not any control in it, has the focus. This screws
  681. // up alt hotkeys for buttons and such.
  682. HWND h = ::GetFocus();
  683. AfxMessageBox(IDS_FINISHED_SEARCH,MB_OK|MB_ICONINFORMATION);
  684. ::SetFocus(h);
  685. }
  686. void CWordPadView::OnColorPick(UINT nID)
  687. {
  688. CRichEdit2View::OnColorPick(CColorMenu::GetColor(nID));
  689. }
  690. void CWordPadView::OnTimer(UINT_PTR nIDEvent)
  691. {
  692. if (m_uTimerID != nIDEvent) // not our timer
  693. CRichEdit2View::OnTimer(nIDEvent);
  694. else
  695. {
  696. KillTimer(m_uTimerID); // kill one-shot timer
  697. m_uTimerID = 0;
  698. if (m_bDelayUpdateItems)
  699. GetDocument()->UpdateAllItems(NULL);
  700. m_bDelayUpdateItems = FALSE;
  701. }
  702. }
  703. void CWordPadView::OnEditChange()
  704. {
  705. SetUpdateTimer();
  706. }
  707. void CWordPadView::OnDestroy()
  708. {
  709. POSITION pos = theApp.m_listPrinterNotify.Find(m_hWnd);
  710. ASSERT(pos != NULL);
  711. theApp.m_listPrinterNotify.RemoveAt(pos);
  712. if (m_uTimerID != 0) // if outstanding timer kill it
  713. OnTimer(m_uTimerID);
  714. ASSERT(m_uTimerID == 0);
  715. CRichEdit2View::OnDestroy();
  716. CWnd *pWnd = AfxGetMainWnd() ;
  717. if (NULL == pWnd)
  718. {
  719. return ;
  720. }
  721. pWnd = pWnd->GetTopLevelParent() ;
  722. if (NULL == pWnd)
  723. {
  724. return ;
  725. }
  726. ::WinHelp(pWnd->m_hWnd, WORDPAD_HELP_FILE, HELP_QUIT, 0) ;
  727. }
  728. void CWordPadView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
  729. {
  730. CRichEdit2View::CalcWindowRect(lpClientRect, nAdjustType);
  731. if (theApp.m_bWin4 && nAdjustType != 0 && (GetStyle() & WS_VSCROLL))
  732. lpClientRect->right--;
  733. // if the ruler is visible then slide the view up under the ruler to avoid
  734. // showing the top border of the view
  735. if (GetExStyle() & WS_EX_CLIENTEDGE)
  736. {
  737. CFrameWnd* pFrame = GetParentFrame();
  738. if (pFrame != NULL)
  739. {
  740. CRulerBar* pBar = (CRulerBar*)pFrame->GetControlBar(ID_VIEW_RULER);
  741. if (pBar != NULL)
  742. {
  743. BOOL bVis = pBar->IsVisible();
  744. if (pBar->m_bDeferInProgress)
  745. bVis = !bVis;
  746. if (bVis)
  747. lpClientRect->top -= 2;
  748. }
  749. }
  750. }
  751. }
  752. void CWordPadView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMIS)
  753. {
  754. lpMIS->itemID = (UINT)(WORD)lpMIS->itemID;
  755. CRichEdit2View::OnMeasureItem(nIDCtl, lpMIS);
  756. }
  757. void CWordPadView::OnPenBackspace()
  758. {
  759. SendMessage(WM_KEYDOWN, VK_BACK, 0);
  760. SendMessage(WM_KEYUP, VK_BACK, 0);
  761. }
  762. void CWordPadView::OnPenNewline()
  763. {
  764. SendMessage(WM_CHAR, '\n', 0);
  765. }
  766. void CWordPadView::OnPenPeriod()
  767. {
  768. SendMessage(WM_CHAR, '.', 0);
  769. }
  770. void CWordPadView::OnPenSpace()
  771. {
  772. SendMessage(WM_CHAR, ' ', 0);
  773. }
  774. void CWordPadView::OnPenTab()
  775. {
  776. SendMessage(WM_CHAR, VK_TAB, 0);
  777. }
  778. void CWordPadView::OnDelayedInvalidate()
  779. {
  780. Invalidate() ;
  781. }
  782. void CWordPadView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  783. {
  784. if (nChar == VK_F10 && GetKeyState(VK_SHIFT) < 0)
  785. {
  786. long nStart, nEnd;
  787. GetRichEditCtrl().GetSel(nStart, nEnd);
  788. CPoint pt = GetRichEditCtrl().GetCharPos(nEnd);
  789. SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, MAKELPARAM(pt.x, pt.y));
  790. }
  791. CRichEdit2View::OnKeyDown(nChar, nRepCnt, nFlags);
  792. }
  793. HRESULT CWordPadView::GetClipboardData(CHARRANGE* lpchrg, DWORD /*reco*/,
  794. LPDATAOBJECT lpRichDataObj, LPDATAOBJECT* lplpdataobj)
  795. {
  796. CHARRANGE& cr = *lpchrg;
  797. if (NULL == lpRichDataObj)
  798. return E_INVALIDARG;
  799. if ((cr.cpMax - cr.cpMin == 1) &&
  800. GetRichEditCtrl().GetSelectionType() == SEL_OBJECT)
  801. {
  802. return E_NOTIMPL;
  803. }
  804. BeginWaitCursor();
  805. //create the data source
  806. COleDataSource* pDataSource = new COleDataSource;
  807. // put the formats into the data source
  808. LPENUMFORMATETC lpEnumFormatEtc;
  809. lpRichDataObj->EnumFormatEtc(DATADIR_GET, &lpEnumFormatEtc);
  810. if (lpEnumFormatEtc != NULL)
  811. {
  812. FORMATETC etc;
  813. while (lpEnumFormatEtc->Next(1, &etc, NULL) == S_OK)
  814. {
  815. STGMEDIUM stgMedium;
  816. lpRichDataObj->GetData(&etc, &stgMedium);
  817. pDataSource->CacheData(etc.cfFormat, &stgMedium, &etc);
  818. }
  819. lpEnumFormatEtc->Release();
  820. }
  821. CEmbeddedItem item(GetDocument(), cr.cpMin, cr.cpMax);
  822. item.m_lpRichDataObj = lpRichDataObj;
  823. // get wordpad formats
  824. item.GetClipboardData(pDataSource);
  825. // get the IDataObject from the data source
  826. *lplpdataobj = (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject);
  827. EndWaitCursor();
  828. return S_OK;
  829. }
  830. HRESULT CWordPadView::PasteHDROPFormat(HDROP hDrop)
  831. {
  832. HRESULT hr = S_OK ;
  833. UINT i ;
  834. TCHAR szFile[MAX_PATH + 1] ;
  835. CHARRANGE cr ;
  836. LONG tmp ;
  837. UINT cFiles ;
  838. cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0) ;
  839. GetRichEditCtrl().GetSel(cr);
  840. tmp = cr.cpMin ;
  841. for (i=0; i<cFiles; i++)
  842. {
  843. ::DragQueryFile(hDrop, i, szFile, MAX_PATH) ;
  844. if (FILE_ATTRIBUTE_DIRECTORY == GetFileAttributes(szFile))
  845. {
  846. continue ;
  847. }
  848. //
  849. // Fix the selection state up so that multiple objects insert
  850. // at the right spot
  851. //
  852. cr.cpMin = cr.cpMax ;
  853. GetRichEditCtrl().SetSel(cr);
  854. //
  855. // Insert from file
  856. //
  857. InsertFileAsObject(szFile) ;
  858. }
  859. GetRichEditCtrl().SetSel(cr);
  860. return hr ;
  861. }
  862. HRESULT CWordPadView::QueryAcceptData(LPDATAOBJECT lpdataobj,
  863. CLIPFORMAT* lpcfFormat, DWORD reco, BOOL bReally,
  864. HGLOBAL hMetaPict)
  865. {
  866. HRESULT hr = S_OK ;
  867. if (!bReally)
  868. {
  869. g_fRightButtonDrag = 0x8000 & GetAsyncKeyState(
  870. GetSystemMetrics(SM_SWAPBUTTON)
  871. ? VK_LBUTTON
  872. : VK_RBUTTON);
  873. }
  874. //
  875. // If we are doing an inproc drag-drop, we want our drop
  876. // effect to be DROPEFFECT_MOVE but if we are drag-dropping
  877. // from another application, we want our effect to be
  878. // DROPEFFECT_COPY -- in particular so that we don't delete
  879. // icons dragged from the explorer or text dragged from Word!
  880. //
  881. // The reason for this hack is that richedit doesn't supply
  882. // any mechanism for us to determine whether or not we are
  883. // both the drop source and the drop target.
  884. //
  885. if (!bReally)
  886. {
  887. LPUNKNOWN pUnk = NULL ;
  888. if (S_OK == lpdataobj->QueryInterface(
  889. IID_IProxyManager,
  890. (LPVOID *) &pUnk))
  891. {
  892. //
  893. // We got an IProxyManager pointer, so we are NOT doing an
  894. // inproc drag drop
  895. //
  896. pUnk->Release() ;
  897. g_fInternalDragDrop = FALSE ;
  898. }
  899. else
  900. {
  901. g_fInternalDragDrop = TRUE ;
  902. }
  903. }
  904. else
  905. {
  906. g_fInternalDragDrop = FALSE ;
  907. }
  908. //
  909. // Check for native data first
  910. //
  911. if (bReally && *lpcfFormat == 0 && (m_nPasteType == 0))
  912. {
  913. COleDataObject dataobj;
  914. dataobj.Attach(lpdataobj, FALSE);
  915. if (!dataobj.IsDataAvailable(cfRTO)) // native avail, let richedit do as it wants
  916. {
  917. if (dataobj.IsDataAvailable(cfEmbeddedObject))
  918. {
  919. if (PasteNative(lpdataobj))
  920. {
  921. hr = S_FALSE ;
  922. goto errRet ;
  923. }
  924. }
  925. }
  926. }
  927. //
  928. // We need to support HDROP format from the explorer
  929. // and the desktop
  930. //
  931. if (bReally)
  932. {
  933. FORMATETC fe ;
  934. fe.cfFormat = CF_HDROP ;
  935. fe.ptd = NULL ;
  936. fe.dwAspect = DVASPECT_CONTENT ;
  937. fe.lindex = -1 ;
  938. fe.tymed = TYMED_HGLOBAL ;
  939. if (S_OK == lpdataobj->QueryGetData(&fe))
  940. {
  941. STGMEDIUM sm ;
  942. sm.tymed = TYMED_NULL ;
  943. sm.hGlobal = (HGLOBAL) 0 ;
  944. sm.pUnkForRelease = NULL ;
  945. if (S_OK == lpdataobj->GetData(&fe, &sm))
  946. {
  947. //
  948. // If we have a single file in our HDROP data then
  949. // embed source might *also* be available in which case we
  950. // should just use the default richedit logic and
  951. // skip PasteHDROPFormat(). We should not ever get
  952. // embed source AND an HDROP data block containing
  953. // multiple files because OLE only supports one drop
  954. // source per drag-drop operation. The default richedit
  955. // logic should handle all cases while dropping a single
  956. // file, we just have to special case things while dropping
  957. // multiple files.
  958. //
  959. if (DragQueryFile((HDROP) sm.hGlobal, (UINT) -1, NULL, 0) > 1)
  960. {
  961. PasteHDROPFormat((HDROP) sm.hGlobal) ;
  962. hr = S_FALSE ;
  963. }
  964. else
  965. {
  966. hr = S_OK ;
  967. }
  968. ::ReleaseStgMedium(&sm) ;
  969. if (S_FALSE == hr)
  970. {
  971. goto errRet ;
  972. }
  973. }
  974. }
  975. }
  976. //
  977. // If all else fails, let richedit give it a try
  978. //
  979. hr = CRichEdit2View::QueryAcceptData(lpdataobj, lpcfFormat, reco, bReally,
  980. hMetaPict);
  981. errRet:
  982. if (bReally)
  983. {
  984. //
  985. // We post a message to ourselves here instead of just calling
  986. // ::Invalidate() because the richedit control doesn't always
  987. // repaint unless it is completely done with the data transfer operation.
  988. //
  989. PostMessage(WM_COMMAND, ID_DELAYED_INVALIDATE, 0) ;
  990. }
  991. return hr ;
  992. }
  993. BOOL CWordPadView::PasteNative(LPDATAOBJECT lpdataobj)
  994. {
  995. // check data object for wordpad object
  996. // if true, pull out RTF directly
  997. FORMATETC etc = {NULL, NULL, DVASPECT_CONTENT, -1, TYMED_ISTORAGE};
  998. etc.cfFormat = (CLIPFORMAT)cfEmbeddedObject;
  999. STGMEDIUM stgMedium = {TYMED_ISTORAGE, 0, NULL};
  1000. // create an IStorage to transfer the data in
  1001. LPLOCKBYTES lpLockBytes;
  1002. if (FAILED(::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes)))
  1003. return FALSE;
  1004. ASSERT(lpLockBytes != NULL);
  1005. HRESULT hr = ::StgCreateDocfileOnILockBytes(lpLockBytes,
  1006. STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &stgMedium.pstg);
  1007. lpLockBytes->Release(); //storage addref'd
  1008. if (FAILED(hr))
  1009. return FALSE;
  1010. ASSERT(stgMedium.pstg != NULL);
  1011. CLSID clsid;
  1012. BOOL bRes = FALSE; //let richedit do what it wants
  1013. if (SUCCEEDED(lpdataobj->GetDataHere(&etc, &stgMedium)) &&
  1014. SUCCEEDED(ReadClassStg(stgMedium.pstg, &clsid)) &&
  1015. clsid == GetDocument()->GetClassID())
  1016. {
  1017. //pull out RTF now
  1018. // open Contents stream
  1019. COleStreamFile file;
  1020. CFileException fe;
  1021. if (file.OpenStream(stgMedium.pstg, szContents,
  1022. CFile::modeReadWrite|CFile::shareExclusive, &fe))
  1023. {
  1024. CRichEdit2Doc *doc = GetDocument();
  1025. BOOL bRTF = doc->m_bRTF;
  1026. BOOL bUnicode = doc->m_bUnicode;
  1027. // Force the "current" stream type to be rtf
  1028. doc->m_bRTF = TRUE;
  1029. doc->m_bUnicode = FALSE;
  1030. // load it with CArchive (loads from Contents stream)
  1031. CArchive loadArchive(&file, CArchive::load |
  1032. CArchive::bNoFlushOnDelete);
  1033. Stream(loadArchive, TRUE); //stream in selection
  1034. // Restore the "current" stream type
  1035. doc->m_bRTF = bRTF;
  1036. doc->m_bUnicode = bUnicode;
  1037. bRes = TRUE; // don't let richedit do anything
  1038. }
  1039. }
  1040. ::ReleaseStgMedium(&stgMedium);
  1041. return bRes;
  1042. }
  1043. // things to fix
  1044. // if format==0 we are doing a straight EM_PASTE
  1045. // look for native formats
  1046. // richedit specific -- allow richedit to handle (these will be first)
  1047. // look for RTF, CF_TEXT. If there paste special as these
  1048. // Do standard OLE scenario
  1049. // if pasting a particular format (format != 0)
  1050. // if richedit specific, allow through
  1051. // if RTF, CF_TEXT. paste special
  1052. // if OLE format, do standard OLE scenario
  1053. void CWordPadView::OnFilePrint()
  1054. {
  1055. theApp.EnsurePrinterIsInitialized();
  1056. // don't allow winini changes to occur while printing
  1057. m_bInPrint = TRUE;
  1058. SetHelpFixHook() ;
  1059. CRichEdit2View::OnFilePrint();
  1060. RemoveHelpFixHook() ;
  1061. // printer may have changed
  1062. theApp.NotifyPrinterChanged(); // this will cause a GetDocument()->PrinterChanged();
  1063. m_bInPrint = FALSE;
  1064. }
  1065. void CWordPadView::OnFilePrintPreview()
  1066. {
  1067. theApp.EnsurePrinterIsInitialized();
  1068. CRichEdit2View::OnFilePrintPreview();
  1069. }
  1070. int CWordPadView::OnMouseActivate(CWnd* pWnd, UINT nHitTest, UINT message)
  1071. {
  1072. if (m_bOnBar)
  1073. {
  1074. SetFocus();
  1075. return MA_ACTIVATEANDEAT;
  1076. }
  1077. else
  1078. return CRichEdit2View::OnMouseActivate(pWnd, nHitTest, message);
  1079. }
  1080. typedef BOOL (WINAPI *PCWPROC)(HWND, LPSTR, UINT, LPVOID, DWORD, DWORD);
  1081. void CWordPadView::OnPenLens()
  1082. {
  1083. USES_CONVERSION;
  1084. HINSTANCE hLib = LoadLibrary(L"PENWIN32.DLL");
  1085. if (hLib == NULL)
  1086. return;
  1087. PCWPROC pCorrectWriting = (PCWPROC)GetProcAddress(hLib, "CorrectWriting");
  1088. ASSERT(pCorrectWriting != NULL);
  1089. if (pCorrectWriting != NULL)
  1090. {
  1091. CHARRANGE cr;
  1092. GetRichEditCtrl().GetSel(cr);
  1093. int nCnt = 2*(cr.cpMax-cr.cpMin);
  1094. BOOL bSel = (nCnt != 0);
  1095. nCnt = max(1024, nCnt);
  1096. char* pBuf = new char[nCnt];
  1097. if (pBuf)
  1098. {
  1099. pBuf[0] = 0;
  1100. if (bSel)
  1101. {
  1102. GetRichEditCtrl().GetSelText(pBuf);
  1103. }
  1104. if (pCorrectWriting(m_hWnd, pBuf, nCnt, 0, bSel ? 0 : CWR_INSERT, 0))
  1105. {
  1106. LPWSTR pwszBuf = AnsiToWideNewArray(pBuf);
  1107. if (pwszBuf)
  1108. {
  1109. GetRichEditCtrl().ReplaceSel(pwszBuf);
  1110. delete [] pwszBuf;
  1111. }
  1112. }
  1113. delete [] pBuf;
  1114. }
  1115. }
  1116. FreeLibrary(hLib);
  1117. }
  1118. LONG CWordPadView::OnPrinterChangedMsg(UINT, LONG)
  1119. {
  1120. CDC dc;
  1121. AfxGetApp()->CreatePrinterDC(dc);
  1122. OnPrinterChanged(dc);
  1123. return 0;
  1124. }
  1125. static void ForwardPaletteChanged(HWND hWndParent, HWND hWndFocus)
  1126. {
  1127. // this is a quick and dirty hack to send the WM_QUERYNEWPALETTE to a window that is interested
  1128. HWND hWnd = NULL;
  1129. for (hWnd = ::GetWindow(hWndParent, GW_CHILD); hWnd != NULL; hWnd = ::GetWindow(hWnd, GW_HWNDNEXT))
  1130. {
  1131. if (hWnd != hWndFocus)
  1132. {
  1133. ::SendMessage(hWnd, WM_PALETTECHANGED, (WPARAM)hWndFocus, 0L);
  1134. ForwardPaletteChanged(hWnd, hWndFocus);
  1135. }
  1136. }
  1137. }
  1138. void CWordPadView::OnPaletteChanged(CWnd* pFocusWnd)
  1139. {
  1140. ForwardPaletteChanged(m_hWnd, pFocusWnd->GetSafeHwnd());
  1141. // allow the richedit control to realize its palette
  1142. // remove this if if richedit fixes their code so that
  1143. // they don't realize their palette into foreground
  1144. if (::GetWindow(m_hWnd, GW_CHILD) == NULL)
  1145. CRichEdit2View::OnPaletteChanged(pFocusWnd);
  1146. }
  1147. static BOOL FindQueryPalette(HWND hWndParent)
  1148. {
  1149. // this is a quick and dirty hack to send the WM_QUERYNEWPALETTE to a window that is interested
  1150. HWND hWnd = NULL;
  1151. for (hWnd = ::GetWindow(hWndParent, GW_CHILD); hWnd != NULL; hWnd = ::GetWindow(hWnd, GW_HWNDNEXT))
  1152. {
  1153. if (::SendMessage(hWnd, WM_QUERYNEWPALETTE, 0, 0L))
  1154. return TRUE;
  1155. else if (FindQueryPalette(hWnd))
  1156. return TRUE;
  1157. }
  1158. return FALSE;
  1159. }
  1160. BOOL CWordPadView::OnQueryNewPalette()
  1161. {
  1162. if(FindQueryPalette(m_hWnd))
  1163. return TRUE;
  1164. return CRichEdit2View::OnQueryNewPalette();
  1165. }
  1166. void CWordPadView::OnWinIniChange(LPCTSTR lpszSection)
  1167. {
  1168. CRichEdit2View::OnWinIniChange(lpszSection);
  1169. //printer might have changed
  1170. if (!m_bInPrint)
  1171. {
  1172. if (lstrcmpi(lpszSection, _T("windows")) == 0)
  1173. theApp.NotifyPrinterChanged(TRUE); // force update to defaults
  1174. }
  1175. }
  1176. void CWordPadView::OnSize(UINT nType, int cx, int cy)
  1177. {
  1178. CRichEdit2View::OnSize(nType, cx, cy);
  1179. CRect rect(HORZ_TEXTOFFSET, VERT_TEXTOFFSET, cx, cy);
  1180. GetRichEditCtrl().SetRect(rect);
  1181. }
  1182. void CWordPadView::OnGetCharFormat(NMHDR* pNMHDR, LRESULT* pRes)
  1183. {
  1184. ASSERT(pNMHDR != NULL);
  1185. ASSERT(pRes != NULL);
  1186. ((CHARHDR*)pNMHDR)->cf = GetCharFormatSelection();
  1187. *pRes = 1;
  1188. }
  1189. void CWordPadView::OnSetCharFormat(NMHDR* pNMHDR, LRESULT* pRes)
  1190. {
  1191. ASSERT(pNMHDR != NULL);
  1192. ASSERT(pRes != NULL);
  1193. SetCharFormat(((CHARHDR*)pNMHDR)->cf);
  1194. *pRes = 1;
  1195. }
  1196. void CWordPadView::OnBarSetFocus(NMHDR*, LRESULT*)
  1197. {
  1198. m_bOnBar = TRUE;
  1199. }
  1200. void CWordPadView::OnBarKillFocus(NMHDR*, LRESULT*)
  1201. {
  1202. m_bOnBar = FALSE;
  1203. }
  1204. void CWordPadView::OnBarReturn(NMHDR*, LRESULT* )
  1205. {
  1206. SetFocus();
  1207. }
  1208. void CWordPadView::OnFormatFont()
  1209. {
  1210. SetHelpFixHook() ;
  1211. CRichEdit2View::OnFormatFont() ;
  1212. RemoveHelpFixHook() ;
  1213. }
  1214. void CWordPadView::OnInsertObject()
  1215. {
  1216. g_fDisableStandardHelp = TRUE ;
  1217. SetHelpFixHook() ;
  1218. CRichEdit2View::OnInsertObject() ;
  1219. RemoveHelpFixHook() ;
  1220. g_fDisableStandardHelp = FALSE ;
  1221. }
  1222. void CWordPadView::OnEditPasteSpecial()
  1223. {
  1224. g_fDisableStandardHelp = TRUE ;
  1225. SetHelpFixHook() ;
  1226. CRichEdit2View::OnEditPasteSpecial() ;
  1227. RemoveHelpFixHook() ;
  1228. g_fDisableStandardHelp = FALSE ;
  1229. }
  1230. void CWordPadView::OnEditFind()
  1231. {
  1232. SetHelpFixHook() ;
  1233. CRichEdit2View::OnEditFind() ;
  1234. RemoveHelpFixHook() ;
  1235. }
  1236. void CWordPadView::OnEditReplace()
  1237. {
  1238. SetHelpFixHook() ;
  1239. CRichEdit2View::OnEditReplace() ;
  1240. RemoveHelpFixHook() ;
  1241. }
  1242. void CWordPadView::OnEditProperties()
  1243. {
  1244. g_fDisableStandardHelp = TRUE ;
  1245. SetHelpFixHook() ;
  1246. CRichEdit2View::OnEditProperties() ;
  1247. RemoveHelpFixHook() ;
  1248. g_fDisableStandardHelp = FALSE ;
  1249. }
  1250. /////////////////////////////////////////////////////////////////////////////
  1251. // CWordPadView::XRichEditOleCallback
  1252. //
  1253. // We implement this so we can override the defaults that MFC has set up. For
  1254. // the most part, we just delegate to MFC.
  1255. //
  1256. BEGIN_INTERFACE_MAP(CWordPadView, CCtrlView)
  1257. // we use IID_IUnknown because richedit doesn't define an IID
  1258. INTERFACE_PART(CWordPadView, IID_IUnknown, WordPadRichEditOleCallback)
  1259. END_INTERFACE_MAP()
  1260. STDMETHODIMP_(ULONG) CWordPadView::XWordPadRichEditOleCallback::AddRef()
  1261. {
  1262. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1263. return pThis->m_xRichEditOleCallback.AddRef() ;
  1264. }
  1265. STDMETHODIMP_(ULONG) CWordPadView::XWordPadRichEditOleCallback::Release()
  1266. {
  1267. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1268. return pThis->m_xRichEditOleCallback.Release() ;
  1269. }
  1270. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::QueryInterface(
  1271. REFIID iid, LPVOID* ppvObj)
  1272. {
  1273. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1274. return pThis->m_xRichEditOleCallback.QueryInterface(iid, ppvObj) ;
  1275. }
  1276. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::GetNewStorage(LPSTORAGE* ppstg)
  1277. {
  1278. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1279. return pThis->m_xRichEditOleCallback.GetNewStorage(ppstg) ;
  1280. }
  1281. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::GetInPlaceContext(
  1282. LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
  1283. LPOLEINPLACEFRAMEINFO lpFrameInfo)
  1284. {
  1285. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1286. // Turn off the mirroring so the server can do the caculation without any problem.
  1287. // We turn it on again in ShowContainerUI
  1288. MirrorTheContainer(FALSE);
  1289. return pThis->m_xRichEditOleCallback.GetInPlaceContext(lplpFrame, lplpDoc, lpFrameInfo) ;
  1290. }
  1291. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::ShowContainerUI(BOOL fShow)
  1292. {
  1293. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1294. // Turn on the mirroring if object UI gonna deactivate.
  1295. if (fShow)
  1296. MirrorTheContainer(fShow);
  1297. return pThis->m_xRichEditOleCallback.ShowContainerUI(fShow) ;
  1298. }
  1299. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::QueryInsertObject(
  1300. LPCLSID lpclsid, LPSTORAGE pstg, LONG cp)
  1301. {
  1302. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1303. return pThis->m_xRichEditOleCallback.QueryInsertObject(lpclsid, pstg, cp) ;
  1304. }
  1305. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::DeleteObject(LPOLEOBJECT lpoleobj)
  1306. {
  1307. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1308. return pThis->m_xRichEditOleCallback.DeleteObject(lpoleobj) ;
  1309. }
  1310. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::QueryAcceptData(
  1311. LPDATAOBJECT lpdataobj, CLIPFORMAT* lpcfFormat, DWORD reco,
  1312. BOOL fReally, HGLOBAL hMetaPict)
  1313. {
  1314. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1315. return pThis->m_xRichEditOleCallback.QueryAcceptData(lpdataobj, lpcfFormat, reco,
  1316. fReally, hMetaPict) ;
  1317. }
  1318. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::ContextSensitiveHelp(BOOL fEnterMode)
  1319. {
  1320. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1321. return pThis->m_xRichEditOleCallback.ContextSensitiveHelp(fEnterMode) ;
  1322. }
  1323. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::GetClipboardData(
  1324. CHARRANGE* lpchrg, DWORD reco, LPDATAOBJECT* lplpdataobj)
  1325. {
  1326. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1327. return pThis->m_xRichEditOleCallback.GetClipboardData(lpchrg, reco, lplpdataobj) ;
  1328. }
  1329. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::GetDragDropEffect(
  1330. BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
  1331. {
  1332. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1333. if (!fDrag) // allowable dest effects
  1334. {
  1335. DWORD dwEffect;
  1336. // check for force link
  1337. #ifndef _MAC
  1338. if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
  1339. #else
  1340. if ((grfKeyState & (MK_OPTION|MK_SHIFT)) == (MK_OPTION|MK_SHIFT))
  1341. #endif
  1342. dwEffect = DROPEFFECT_LINK;
  1343. // check for force copy
  1344. #ifndef _MAC
  1345. else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  1346. #else
  1347. else if ((grfKeyState & MK_OPTION) == MK_OPTION)
  1348. #endif
  1349. dwEffect = DROPEFFECT_COPY;
  1350. // check for force move
  1351. else if ((grfKeyState & MK_ALT) == MK_ALT)
  1352. dwEffect = DROPEFFECT_MOVE;
  1353. // default -- recommended action is 'copy' (overridden from MFC default)
  1354. else
  1355. {
  1356. if (g_fInternalDragDrop)
  1357. {
  1358. dwEffect = DROPEFFECT_MOVE ;
  1359. }
  1360. else
  1361. {
  1362. dwEffect = DROPEFFECT_COPY;
  1363. }
  1364. }
  1365. pThis->m_nPasteType = 0;
  1366. if (dwEffect & *pdwEffect) // make sure allowed type
  1367. {
  1368. *pdwEffect = dwEffect;
  1369. if (DROPEFFECT_LINK == dwEffect)
  1370. pThis->m_nPasteType = COlePasteSpecialDialog::pasteLink;
  1371. }
  1372. }
  1373. return S_OK;
  1374. }
  1375. STDMETHODIMP CWordPadView::XWordPadRichEditOleCallback::GetContextMenu(
  1376. WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE* lpchrg,
  1377. HMENU* lphmenu)
  1378. {
  1379. METHOD_PROLOGUE_EX_(CWordPadView, WordPadRichEditOleCallback)
  1380. HRESULT hr;
  1381. if (g_fRightButtonDrag)
  1382. hr = E_FAIL;
  1383. else
  1384. hr = pThis->m_xRichEditOleCallback.GetContextMenu(
  1385. seltype,
  1386. lpoleobj,
  1387. lpchrg,
  1388. lphmenu);
  1389. g_fRightButtonDrag = FALSE;
  1390. return hr;
  1391. }