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.

691 lines
17 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module PROPCHG.CPP -- Property Change Notification Routines |
  5. *
  6. * Original Author: <nl>
  7. * Rick Sailor
  8. *
  9. * History: <nl>
  10. * 9/5/95 ricksa Created and documented
  11. *
  12. * Documentation is generated straight from the code. The following
  13. * date/time stamp indicates the version of code from which the
  14. * the documentation was generated.
  15. *
  16. * Copyright (c) 1995-1997 Microsoft Corporation. All rights reserved.
  17. */
  18. #include "_common.h"
  19. #include "_edit.h"
  20. #include "_dispprt.h"
  21. #include "_dispml.h"
  22. #include "_dispsl.h"
  23. #include "_select.h"
  24. #include "_text.h"
  25. #include "_runptr.h"
  26. #include "_font.h"
  27. #include "_measure.h"
  28. #include "_render.h"
  29. #include "_urlsup.h"
  30. ASSERTDATA
  31. CTxtEdit::FNPPROPCHG CTxtEdit::_fnpPropChg[MAX_PROPERTY_BITS];
  32. /*
  33. * CTxtEdit::UpdateAccelerator()
  34. *
  35. * @mfunc
  36. * Get accelerator cp from host
  37. *
  38. * @rdesc
  39. * HRESULT
  40. *
  41. * @devnote:
  42. * The point of this is to leave the accelerator offset unchanged
  43. * in the face of an error from the host.
  44. */
  45. HRESULT CTxtEdit::UpdateAccelerator()
  46. {
  47. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::UpdateAccelerator");
  48. LONG cpAccel;
  49. HRESULT hr = _phost->TxGetAcceleratorPos(&cpAccel);
  50. if(SUCCEEDED(hr))
  51. {
  52. // It worked so reset our value
  53. AssertSz(cpAccel < 32768,
  54. "CTxtEdit::UpdateAccelerator: cp too large");
  55. _cpAccelerator = cpAccel;
  56. }
  57. return hr;
  58. }
  59. /*
  60. * CTxtEdit::HandleRichToPlainConversion()
  61. *
  62. * @mfunc
  63. * Convert a rich text object to a plain text object
  64. */
  65. void CTxtEdit::HandleRichToPlainConversion()
  66. {
  67. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::HandleRichToPlainConversion");
  68. // Notify every interested party that they should dump their formatting
  69. _nm.NotifyPreReplaceRange(NULL, CONVERT_TO_PLAIN, 0, 0, 0, 0);
  70. // Set _fRich to false so we can delete the final CRLF.
  71. _fRich = 0;
  72. _fSelChangeCharFormat = 0;
  73. // if(_pdetecturl)
  74. // {
  75. // delete _pdetecturl;
  76. // _pdetecturl = NULL;
  77. // }
  78. // Tell document to dump its format runs
  79. _story.DeleteFormatRuns();
  80. // Clear out the ending CRLF
  81. CRchTxtPtr rtp(this, 0);
  82. rtp.ReplaceRange(GetTextLength(), 0, NULL, NULL, -1);
  83. }
  84. /*
  85. * CTxtEdit::OnRichEditChange (fPropertyFlag)
  86. *
  87. * @mfunc
  88. * Notify text services that rich-text property changed
  89. *
  90. * @rdesc
  91. * S_OK - Notification successfully processed.
  92. */
  93. HRESULT CTxtEdit::OnRichEditChange(
  94. BOOL fPropertyFlag) //@parm New state of richedit flag
  95. {
  96. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnRichEditChange");
  97. // Calculate length of empty document. Remember that multiline rich text
  98. // controls always have and end of paragraph marker.
  99. LONG cchEmptyDoc = cchCR;
  100. CFreezeDisplay fd(_pdp); // defer screen update until we finish the change.
  101. if(!_fRich)
  102. cchEmptyDoc = 0;
  103. else if(_f10Mode)
  104. cchEmptyDoc = cchCRLF;
  105. // This can only be changed if there is no text and nothing to undo.
  106. // It makes no sense to change when there is already text. This is
  107. // particularly true of going from rich to plain. Further, what would
  108. // you do with the undo state?
  109. if(GetTextLength() == cchEmptyDoc && (!_pundo || !_pundo->CanUndo()))
  110. {
  111. #ifdef DEBUG
  112. // Make sure that document is in a sensible state.
  113. if(_fRich)
  114. {
  115. CTxtPtr tp(this, 0);
  116. WCHAR szBuf[cchCRLF];
  117. tp.GetText(cchCRLF, &szBuf[0]);
  118. AssertSz(szBuf[0] == CR && (!_f10Mode || szBuf[1] == LF),
  119. "CTxtEdit::OnRichEditChange: invalid document terminator");
  120. }
  121. #endif // DEBUG
  122. if(_fRich && !fPropertyFlag)
  123. {
  124. // Going from rich text to plain text. Need to dump
  125. // format runs.
  126. HandleRichToPlainConversion();
  127. _fAutoFontSizeAdjust = TRUE;
  128. }
  129. else if (!_fRich && fPropertyFlag)
  130. {
  131. // Going from plain text to rich text. Need to add the
  132. // appropriate EOP at the end of the document.
  133. SetRichDocEndEOP(0);
  134. _fAutoFontSizeAdjust = FALSE;
  135. }
  136. _fRich = fPropertyFlag;
  137. return S_OK;
  138. }
  139. return E_FAIL; // Flag was not updated
  140. }
  141. /*
  142. * CTxtEdit::OnTxMultiLineChange (fMultiline)
  143. *
  144. * @mfunc
  145. * Notify text services that the display changed.
  146. *
  147. * @rdesc
  148. * S_OK - Notification successfully processed.
  149. */
  150. HRESULT CTxtEdit::OnTxMultiLineChange(
  151. BOOL fMultiLine)
  152. {
  153. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxMultiLineChange");
  154. BOOL fHadSelection = (_psel != NULL);
  155. CDisplay * pSavedDisplay;
  156. BOOL fOldShowSelection = FALSE;
  157. // Remember the old value for show selection
  158. if (fHadSelection)
  159. fOldShowSelection = _psel->GetShowSelection();
  160. // Save the current display away and null it out
  161. pSavedDisplay = _pdp;
  162. _pdp = NULL;
  163. // Attempt to create the new display
  164. if (fMultiLine)
  165. _pdp = new CDisplayML(this);
  166. else
  167. _pdp = new CDisplaySL(this);
  168. Assert(_pdp);
  169. if(!_pdp)
  170. {
  171. Assert(pSavedDisplay);
  172. _pdp = pSavedDisplay;
  173. return E_OUTOFMEMORY;
  174. }
  175. // Attempt to init the new display
  176. if(pSavedDisplay)
  177. _pdp->InitFromDisplay(pSavedDisplay);
  178. if(!_pdp->Init())
  179. {
  180. delete _pdp;
  181. Assert(pSavedDisplay);
  182. _pdp = pSavedDisplay;
  183. return E_FAIL;
  184. }
  185. // Ok to now kill the old display
  186. delete pSavedDisplay;
  187. // Is there are selection?
  188. if(_psel)
  189. {
  190. // Need to tell it there is a new display to talk to.
  191. _psel->SetDisplay(_pdp);
  192. }
  193. // Is this a switch to Single Line? If this is we need to
  194. // make sure we truncate the text to the first EOP. We wait
  195. // till this point to do this check to make sure that everything
  196. // is in sync before doing something which potentially affects
  197. // the display and the selection.
  198. if(!fMultiLine)
  199. {
  200. // Set up for finding an EOP
  201. CTxtPtr tp(this, 0);
  202. tp.FindEOP(tomForward);
  203. // Is there any EOP and text beyond?
  204. if (tp.GetCp() < GetAdjustedTextLength())
  205. {
  206. // FindEOP places the text after the EOP if there
  207. // is one. Since we want to delete the EOP as well
  208. // we need to back up to the EOP.
  209. tp.BackupCpCRLF();
  210. // Sync up the cp's of all the ranges before deleting
  211. // the text.
  212. CRchTxtPtr rtp(this, tp.GetCp());
  213. // Truncate from the EOP to the end of the document
  214. rtp.ReplaceRange(GetAdjustedTextLength() - tp.GetCp(), 0, NULL, NULL, -1);
  215. }
  216. }
  217. _pdp->UpdateView();
  218. if(fHadSelection && _fFocus && fOldShowSelection)
  219. _psel->ShowSelection(TRUE);
  220. return S_OK;
  221. }
  222. /*
  223. * CTxtEdit::OnTxReadOnlyChange (fReadOnly)
  224. *
  225. * @mfunc
  226. * Notify text services that read-only property changed
  227. *
  228. * @rdesc
  229. * S_OK - Notification successfully processed.
  230. */
  231. HRESULT CTxtEdit::OnTxReadOnlyChange(
  232. BOOL fReadOnly) //@parm TRUE = read only, FALSE = not read only
  233. {
  234. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxReadOnlyChange");
  235. if (fReadOnly)
  236. _ldte.ReleaseDropTarget();
  237. _fReadOnly = fReadOnly; // Cache bit
  238. return S_OK;
  239. }
  240. /*
  241. * CTxtEdit::OnShowAccelerator (fPropertyFlag)
  242. *
  243. * @mfunc
  244. * Update accelerator based on change
  245. *
  246. * @rdesc
  247. * S_OK - Notification successfully processed.
  248. */
  249. HRESULT CTxtEdit::OnShowAccelerator(
  250. BOOL fPropertyFlag) //@parm TRUE = show accelerator
  251. {
  252. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnShowAccelerator");
  253. // Get the new accelerator character
  254. HRESULT hr = UpdateAccelerator();
  255. // Update the view - we update even in the face of an error return.
  256. // The point is that errors will be rare (non-existent?) and the update
  257. // will work even in the face of the error so why bother conditionalizing
  258. // the execution.
  259. NeedViewUpdate(TRUE);
  260. return hr;
  261. }
  262. /*
  263. * CTxtEdit::OnUsePassword (fPropertyFlag)
  264. *
  265. * @mfunc
  266. * Update use-password property
  267. *
  268. * @rdesc
  269. * S_OK - Notification successfully processed.
  270. */
  271. HRESULT CTxtEdit::OnUsePassword(
  272. BOOL fPropertyFlag) //@parm TRUE = use password character
  273. {
  274. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnUsePassword");
  275. Assert((DWORD)fPropertyFlag <= 1); // Be sure it's C boolean
  276. _fUsePassword = fPropertyFlag;
  277. _pdp->UpdateView(); // State changed so update view
  278. return S_OK;
  279. }
  280. /*
  281. * CTxtEdit::OnTxHideSelectionChange (fHideSelection)
  282. *
  283. * @mfunc
  284. * Notify text services that hide-selection property changed
  285. *
  286. * @rdesc
  287. * S_OK - Notification successfully processed.
  288. */
  289. HRESULT CTxtEdit::OnTxHideSelectionChange(
  290. BOOL fHideSelection) //@parm TRUE = hide selection
  291. {
  292. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxHideSelectionChange");
  293. // update internal flag if selection is to be hidden
  294. _fHideSelection = fHideSelection;
  295. if (!_fFocus)
  296. OnHideSelectionChange(fHideSelection);
  297. return S_OK;
  298. }
  299. /*
  300. * CTxtEdit::OnHideSelectionChange (fHideSelection)
  301. *
  302. * @mfunc
  303. * Performs the actual hide selection. Helper to OnTxHideSelectionChange
  304. *
  305. * @rdesc
  306. * S_OK - Notification successfully processed.
  307. */
  308. HRESULT CTxtEdit::OnHideSelectionChange(
  309. BOOL fHideSelection) //@parm TRUE = hide selection
  310. {
  311. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnHideSelectionChange");
  312. _fHideSelection = fHideSelection;
  313. CTxtSelection * psel = GetSel();
  314. if(psel)
  315. {
  316. psel->ShowSelection(!fHideSelection);
  317. // In the case where we don't have focus we don't want to allow the user to display the caret but it's okay
  318. // to hide the caret.
  319. if (_fFocus || fHideSelection)
  320. psel->ShowCaret(!fHideSelection);
  321. }
  322. if(!_fInPlaceActive)
  323. {
  324. TxInvalidateRect(NULL, FALSE); // Since _fInPlaceActive = FALSE,
  325. TxUpdateWindow(); // this only tells user.exe to
  326. } // send a WM_PAINT message
  327. return S_OK;
  328. }
  329. /*
  330. * CTxtEdit::OnSaveSelection (fPropertyFlag)
  331. *
  332. * @mfunc
  333. * Notify text services that save-selection property changed
  334. *
  335. * @rdesc
  336. * S_OK - Notification successfully processed.
  337. */
  338. HRESULT CTxtEdit::OnSaveSelection(
  339. BOOL fPropertyFlag) //@parm TRUE = save selection when inactive
  340. {
  341. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnSaveSelection");
  342. return S_OK;
  343. }
  344. /*
  345. * CTxtEdit::OnAutoWordSel (fPropertyFlag)
  346. *
  347. * @mfunc
  348. * Notify text services that auto-word-selection property changed
  349. *
  350. * @rdesc
  351. * S_OK - Notification successfully processed.
  352. */
  353. HRESULT CTxtEdit::OnAutoWordSel(
  354. BOOL fPropertyFlag) //@parm TRUE = auto word selection on
  355. {
  356. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnAutoWordSel");
  357. // We call back to the host when we need to know, so we don't bother doing
  358. // anything in response to this notification.
  359. return S_OK;
  360. }
  361. /*
  362. * CTxtEdit::OnTxVerticalChange (fVertical)
  363. *
  364. * @mfunc
  365. * Notify text services that vertical property changed
  366. *
  367. * @rdesc
  368. * S_OK - Notification successfully processed.
  369. */
  370. HRESULT CTxtEdit::OnTxVerticalChange(
  371. BOOL fVertical) //@parm TRUE - text vertically oriented.
  372. {
  373. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxVerticalChange");
  374. // We pretend like something actually happened.
  375. GetCallMgr()->SetChangeEvent(CN_GENERIC);
  376. return S_OK;
  377. }
  378. /*
  379. * CTxtEdit::OnClientRectChange (fPropertyFlag)
  380. *
  381. * @mfunc
  382. * Notify text services that client rectangle changed
  383. *
  384. * @rdesc
  385. * S_OK - Notification successfully processed.
  386. */
  387. HRESULT CTxtEdit::OnClientRectChange(
  388. BOOL fPropertyFlag) //@parm Ignored for this property
  389. {
  390. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnClientRectChange");
  391. // It is unclear whether we need to actually do anything for this
  392. // notification. Logically, the change of this property is followed
  393. // closely by some kind of operation which will cause the display
  394. // cache to be updated anyway. The old code is left here as an
  395. // example of what might be done if it turns out we need to do
  396. // anything. For now, we will simply return S_OK to this notification.
  397. #if 0
  398. if (_fInPlaceActive)
  399. {
  400. RECT rc;
  401. if(_phost->TxGetClientRect(&rc) == NOERROR)
  402. _pdp->OnClientRectChange(rc);
  403. return S_OK;
  404. }
  405. return NeedViewUpdate(fPropertyFlag);
  406. #endif // 0
  407. // With a client rect change we do need to update the caret when
  408. // we get redrawn even if the basic information did not change.
  409. _pdp->SetUpdateCaret();
  410. return S_OK;
  411. }
  412. /*
  413. * CTxtEdit::OnCharFormatChange (fPropertyFlag)
  414. *
  415. * @mfunc
  416. * Update default CCharFormat
  417. *
  418. * @rdesc
  419. * S_OK - update successfully processed.
  420. */
  421. HRESULT CTxtEdit::OnCharFormatChange(
  422. BOOL fPropertyFlag) //@parm Not used
  423. {
  424. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnCharFormatChange");
  425. CCharFormat CF;
  426. DWORD dwMask;
  427. HRESULT hr = TxGetDefaultCharFormat(&CF, dwMask);
  428. if(hr == NOERROR)
  429. {
  430. DWORD dwMask2 = CFM2_CHARFORMAT;
  431. WPARAM wparam = SCF_ALL;
  432. if(!GetAdjustedTextLength())
  433. {
  434. dwMask2 = CFM2_CHARFORMAT | CFM2_NOCHARSETCHECK;
  435. wparam = 0;
  436. }
  437. // OnSetCharFormat handles updating the view.
  438. hr = OnSetCharFormat(wparam, &CF, NULL, dwMask, dwMask2) ? NOERROR : E_FAIL;
  439. }
  440. return hr;
  441. }
  442. /*
  443. * CTxtEdit::OnParaFormatChange (fPropertyFlag)
  444. *
  445. * @mfunc
  446. * Update default CParaFormat
  447. *
  448. * @rdesc
  449. * S_OK - update successfully processed
  450. *
  451. * @devnote
  452. * Because Forms^3 doesn't set cbSize correctly, we limit this API
  453. * to PARAFORMAT (until they fix it).
  454. */
  455. HRESULT CTxtEdit::OnParaFormatChange(
  456. BOOL fPropertyFlag) //@parm Not used
  457. {
  458. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnParaFormatChange");
  459. CParaFormat PF;
  460. HRESULT hr = TxGetDefaultParaFormat(&PF);
  461. if(hr == NOERROR)
  462. {
  463. // OnSetParaFormat handles updating the view.
  464. hr = OnSetParaFormat(SPF_SETDEFAULT, &PF, NULL, PFM_ALL2)
  465. ? NOERROR : E_FAIL;
  466. }
  467. #ifdef TABS
  468. GetTabsCache()->Release(PF._iTabs);
  469. #endif
  470. return hr;
  471. }
  472. /*
  473. * CTxtEdit::NeedViewUpdate (fPropertyFlag)
  474. *
  475. * @mfunc
  476. * Notify text services that view of data changed
  477. *
  478. * @rdesc
  479. * S_OK - Notification successfully processed.
  480. */
  481. HRESULT CTxtEdit::NeedViewUpdate(
  482. BOOL fPropertyFlag)
  483. {
  484. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::NeedViewUpdate");
  485. _pdp->UpdateView();
  486. return S_OK;
  487. }
  488. /*
  489. * CTxtEdit::OnTxBackStyleChange (fPropertyFlag)
  490. *
  491. * @mfunc
  492. * Notify text services that background style changed
  493. *
  494. * @rdesc
  495. * S_OK - Notification successfully processed.
  496. */
  497. HRESULT CTxtEdit::OnTxBackStyleChange(
  498. BOOL fPropertyFlag) //@parm Ignored for this property
  499. {
  500. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxBackStyleChange");
  501. _fTransparent = (TxGetBackStyle() == TXTBACK_TRANSPARENT);
  502. TxInvalidateRect(NULL, FALSE);
  503. return S_OK;
  504. }
  505. /*
  506. * CTxtEdit::OnAllowBeep (fPropertyFlag)
  507. *
  508. * @mfunc
  509. * Notify text services that beep property changed
  510. *
  511. * @rdesc
  512. * S_OK - Notification successfully processed.
  513. */
  514. HRESULT CTxtEdit::OnAllowBeep(
  515. BOOL fPropertyFlag) //@parm New state of property
  516. {
  517. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnAllowBeep");
  518. _fAllowBeep = fPropertyFlag;
  519. return S_OK;
  520. }
  521. /*
  522. * CTxtEdit::OnMaxLengthChange (fPropertyFlag)
  523. *
  524. * @mfunc
  525. * Notify text services that max-length property changed
  526. *
  527. * @rdesc
  528. * S_OK - Notification successfully processed.
  529. */
  530. HRESULT CTxtEdit::OnMaxLengthChange(
  531. BOOL fPropertyFlag) //@parm New state of property
  532. {
  533. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnMaxLengthChange");
  534. // Query host for max text length
  535. DWORD length = CP_INFINITE;
  536. _phost->TxGetMaxLength(&length);
  537. _cchTextMost = length;
  538. return S_OK;
  539. }
  540. /*
  541. * CTxtEdit::OnWordWrapChange (fPropertyFlag)
  542. *
  543. * @mfunc
  544. * Notify text services that word-wrap property changed
  545. *
  546. * @rdesc
  547. * S_OK - Notification successfully processed.
  548. */
  549. HRESULT CTxtEdit::OnWordWrapChange(
  550. BOOL fPropertyFlag) //@parm TRUE = do word wrap
  551. {
  552. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnWordWrapChange");
  553. _pdp->SetWordWrap(fPropertyFlag);
  554. // Update was successful so we need the screen updated at some point
  555. _pdp->UpdateView();
  556. return S_OK;
  557. }
  558. /*
  559. * CTxtEdit::OnDisableDrag (fPropertyFlag)
  560. *
  561. * @mfunc
  562. * Notify text services that disable drag property changed
  563. *
  564. * @rdesc
  565. * S_OK - Notification successfully processed.
  566. */
  567. HRESULT CTxtEdit::OnDisableDrag(
  568. BOOL fPropertyFlag) //@parm New state of property
  569. {
  570. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnDisableDrag");
  571. _fDisableDrag = fPropertyFlag;
  572. return S_OK;
  573. }
  574. /*
  575. * CTxtEdit::OnScrollChange (fPropertyFlag)
  576. *
  577. * @mfunc
  578. * Notify text services scroll property change
  579. *
  580. * @rdesc
  581. * S_OK - Notification successfully processed.
  582. */
  583. HRESULT CTxtEdit::OnScrollChange(
  584. BOOL fPropertyFlag) //@parm New state of property
  585. {
  586. TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnScrollChange");
  587. // Tell the display that scroll bars for sure need to be updated
  588. _pdp->SetViewChanged();
  589. // Tell the display to update itself.
  590. _pdp->UpdateView();
  591. return S_OK;
  592. }