📄 propchg.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
* @doc INTERNAL
*
* @module PROPCHG.CPP -- Property Change Notification Routines |
*
* Original Author: <nl>
* Rick Sailor
*
* History: <nl>
* 9/5/95 ricksa Created and documented
*
* Documentation is generated straight from the code. The following
* date/time stamp indicates the version of code from which the
* the documentation was generated.
*
*/
#include "_common.h"
#include "_edit.h"
#include "_dispprt.h"
#include "_dispml.h"
#include "_dispsl.h"
#include "_select.h"
#include "_text.h"
#include "_runptr.h"
#include "_font.h"
#include "_measure.h"
#include "_render.h"
#include "_urlsup.h"
ASSERTDATA
CTxtEdit::FNPPROPCHG CTxtEdit::_fnpPropChg[MAX_PROPERTY_BITS] =
{
&CTxtEdit::OnRichEditChange, // TXTBIT_RICHTEXT
&CTxtEdit::OnTxMultiLineChange, // TXTBIT_MULTILINE
&CTxtEdit::OnTxReadOnlyChange, // TXTBIT_READONLY
&CTxtEdit::OnShowAccelerator, // TXTBIT_SHOWACCELERATOR
&CTxtEdit::OnUsePassword, // TXTBIT_USEPASSWORD
&CTxtEdit::OnTxHideSelectionChange, // TXTBIT_HIDESELECTION
&CTxtEdit::OnSaveSelection, // TXTBIT_SAVESELECTION
&CTxtEdit::OnAutoWordSel, // TXTBIT_AUTOWORDSEL
&CTxtEdit::OnTxVerticalChange, // TXTBIT_VERTICAL
&CTxtEdit::NeedViewUpdate, // TXTBIT_SELECTIONBAR
&CTxtEdit::OnWordWrapChange, // TXTBIT_WORDWRAP
&CTxtEdit::OnAllowBeep, // TXTBIT_ALLOWBEEP
&CTxtEdit::OnDisableDrag, // TXTBIT_DISABLEDRAG
&CTxtEdit::NeedViewUpdate, // TXTBIT_VIEWINSETCHANGE
&CTxtEdit::OnTxBackStyleChange, // TXTBIT_BACKSTYLECHANGE
&CTxtEdit::OnMaxLengthChange, // TXTBIT_MAXLENGTHCHANGE
&CTxtEdit::OnScrollChange, // TXTBIT_SCROLLBARCHANGE
&CTxtEdit::OnCharFormatChange, // TXTBIT_CHARFORMATCHANGE
&CTxtEdit::OnParaFormatChange, // TXTBIT_PARAFORMATCHANGE
&CTxtEdit::NeedViewUpdate, // TXTBIT_EXTENTCHANGE
&CTxtEdit::OnClientRectChange, // TXTBIT_CLIENTRECTCHANGE
};
/*
* CTxtEdit::UpdateAccelerator()
*
* @mfunc
* Get accelerator cp from host
*
* @rdesc
* HRESULT
*
* @devnote:
* The point of this is to leave the accelerator offset unchanged
* in the face of an error from the host.
*/
HRESULT CTxtEdit::UpdateAccelerator()
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::UpdateAccelerator");
LONG cpAccel;
HRESULT hr = _phost->TxGetAcceleratorPos(&cpAccel);
if (SUCCEEDED(hr))
{
// It worked so reset our value
AssertSz(cpAccel < 32768,
"CTxtEdit::UpdateAccelerator: cp too large");
_cpAccelerator = cpAccel;
}
return hr;
}
/*
* CTxtEdit::HandleRichToPlainConversion()
*
* @mfunc
* Convert a rich text object to a plain text object
*/
INLINE void CTxtEdit::HandleRichToPlainConversion()
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::HandleRichToPlainConversion");
CRchTxtPtr rtp(this,0);
// Notify every interested party that they should dump their formatting
_nm.NotifyPreReplaceRange(NULL, CONVERT_TO_PLAIN, 0, 0, 0, 0);
// set _fRich to false so we can delete the final CRLF.
_fRich = 0;
if( _pdetecturl )
{
delete _pdetecturl;
_pdetecturl = NULL;
}
// Set the format runs to NULL since this really isn't a rich text object
// any more.
rtp._rpCF.SetToNull();
rtp._rpPF.SetToNull();
// Tell document to dump its format runs
_story.DeleteFormatRuns();
// clear out the ending CRLF
rtp.ReplaceRange(GetTextLength(), 0, NULL, NULL, -1);
}
/*
* CTxtEdit::HandleIMEToPlain()
*
* @mfunc
* After IME composition in a plain text environment, return the CF runs to normal.
*/
void CTxtEdit::HandleIMEToPlain()
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::HandleIMEToPlain");
CRchTxtPtr rtp(this,0);
_pdp->WaitForRecalc(GetTextLength(), -1);
// Notify every interested party that they should dump their formatting
_nm.NotifyPreReplaceRange(NULL, CONVERT_TO_PLAIN, 0, 0, 0, 0);
// Set the format runs to NULL since this really isn't a rich text object
// any more.
rtp._rpCF.SetToNull();
// Tell document to dump its format runs
_story.DeleteFormatRuns();
}
/*
* CTxtEdit::OnRichEditChange (fPropertyFlag)
*
* @mfunc
* Notify text services that rich-text property changed
*
* @rdesc
* S_OK - Notification successfully processed.
*/
HRESULT CTxtEdit::OnRichEditChange(
BOOL fPropertyFlag ) //@parm New state of richedit flag
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnRichEditChange");
// Calculate length of empty document. Remember that multiline rich text
// controls always have and end of paragraph marker.
DWORD dwEmptyDocLen = cchCR;
if (!_fRich)
{
dwEmptyDocLen = 0;
}
else if (_f10Mode)
{
dwEmptyDocLen = cchCRLF;
}
// This can only be changed if there is no text and nothing to undo.
// It makes no sense to change when there is already text. This is
// particularly true of going from rich to plain. Further, what would
// you do with the undo state?
if ((GetTextLength() == dwEmptyDocLen)
&& (!_pundo || !_pundo->CanUndo()))
{
#ifdef DEBUG
// Make sure that document is in a sensible state.
if (_fRich)
{
CRchTxtPtr tp(this);
WCHAR szBuf[cchCRLF];
if (!_f10Mode)
{
// 2.0 Rich text document. Must have a single CR.
tp._rpTX.GetText(cchCR, &szBuf[0]);
AssertSz(szBuf[0] == szCRLF[0],
"CTxtEdit::OnRichEditChange 1.0 no CR terminator");
}
else
{
// 1.0 Rich text document. Must have a CRLF
tp._rpTX.GetText(cchCRLF, &szBuf[0]);
AssertSz((szBuf[0] == szCRLF[0]) && (szBuf[1] == szCRLF[1]),
"CTxtEdit::OnRichEditChange 1.0 no CRLF terminator");
}
}
#endif // DEBUG
if (_fRich && !fPropertyFlag)
{
// We are going from rich text to plain text. We need to
// dump all format runs.
HandleRichToPlainConversion();
}
else if (!_fRich && fPropertyFlag)
{
// Going to rich text from plain text ML. Need to add the
// appropriate EOP at the end of the document.
SetRichDocEndEOP(0);
}
_fRich = fPropertyFlag;
return S_OK;
}
return E_FAIL; // Flag was not updated
}
/*
* CTxtEdit::OnTxMultiLineChange (fMultiline)
*
* @mfunc
* Notify text services that the display changed.
*
* @rdesc
* S_OK - Notification successfully processed.
*/
HRESULT CTxtEdit::OnTxMultiLineChange(
BOOL fMultiLine)
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxMultiLineChange");
BOOL fHadSelection = (_psel != NULL);
CDisplay * pSavedDisplay;
BOOL fOldShowSelection = FALSE;
// Remember the old value for show selection
if (fHadSelection)
fOldShowSelection = _psel->GetShowSelection();
// Save the current display away and null it out
pSavedDisplay = _pdp;
_pdp = NULL;
// Attempt to create the new display
if (fMultiLine)
_pdp = new CDisplayML(this);
else
_pdp = new CDisplaySL(this);
if (!_pdp)
{
_pdp = pSavedDisplay;
return E_OUTOFMEMORY;
}
// Attempt to init the new display
if( pSavedDisplay )
{
_pdp->InitFromDisplay(pSavedDisplay);
}
if (!_pdp->Init())
{
delete _pdp;
_pdp = pSavedDisplay;
return E_FAIL;
}
// Ok to now kill the old display
delete pSavedDisplay;
// Is there are selection?
if (_psel)
{
// Need to tell it there is a new display to talk to.
_psel->SetDisplay(_pdp);
}
// Is this a switch to Single Line? If this is we need to
// make sure we truncate the text to the first EOP. We wait
// till this point to do this check to make sure that everything
// is in sync before doing something which potentially affects
// the display and the selection.
if (!fMultiLine)
{
// Set up for finding an EOP
CTxtPtr tp(this, 0);
tp.FindEOP(tomForward);
// Is there any EOP and text beyond?
if (tp.GetCp() < GetAdjustedTextLength())
{
// FindEOP places the text after the EOP if there
// is one. Since we want to delete the EOP as well
// we need to back up to the EOP.
tp.BackupCpCRLF();
// Sync up the cp's of all the ranges before deleting
// the text.
CRchTxtPtr rtp(this, tp.GetCp());
// Truncate from the EOP to the end of the document
rtp.ReplaceRange(GetAdjustedTextLength() - tp.GetCp(), 0, NULL, NULL, -1);
}
}
_pdp->UpdateView();
if (fHadSelection)
{
if (_fFocus && fOldShowSelection)
_psel->ShowSelection( TRUE );
}
return S_OK;
}
/*
* CTxtEdit::OnTxReadOnlyChange (fReadOnly)
*
* @mfunc
* Notify text services that read-only property changed
*
* @rdesc
* S_OK - Notification successfully processed.
*/
HRESULT CTxtEdit::OnTxReadOnlyChange(
BOOL fReadOnly ) //@parm TRUE = read only, FALSE = not read only
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::OnTxReadOnlyChange");
if (fReadOnly)
{
_ldte.ReleaseDropTarget();
}
_fReadOnly = fReadOnly; // Cache bit
return S_OK;
}
/*
* CTxtEdit::OnShowAccelerator (fPropertyFlag)
*
* @mfunc
* Update accelerator based on change
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -