📄 textserv.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 EXTERNAL
*
* @module TEXTSERV.CPP -- Text Services Implementation |
*
* Original Author: <nl>
* Rick Sailor
*
* History: <nl>
* 8/1/95 ricksa Created and documented
* 10/95 murrays Further doc and simplifications
*
* Documentation is generated straight from the code. The following
* date/time stamp indicates the version of code from which the
* the documentation was generated.
*
* $Header: /richedit/src/textserv.cpp 53 11/15/95 2:39p Ricksa $
*
*/
#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 "_m_undo.h"
#include "_antievt.h"
#include "_rtext.h"
#include "_ime.h"
#include "_urlsup.h"
#include "_magelln.h"
// By turning on the PROFILE_TS compiler directive, you tell IceCap2.0
// to turn on profiling for only ITextServices API's. Typically only
// used during profiling work.
//#define PROFILE_TS
#ifdef PROFILE_TS
#include <icapexp.h>
class CapProfile
{
public:
CapProfile() { StartCAP(); }
~CapProfile() { StopCAP(); }
};
#define START_PROFILING CapProfile capprf;
#else
#define START_PROFILING
#endif //PROFILE_TS
ASSERTDATA
// Macros to get mouse coordinates out of a message
// need to cast to SHORT first for sign extension
#define MOUSEX ((INT)(SHORT)LOWORD(lparam))
#define MOUSEY ((INT)(SHORT)HIWORD(lparam))
LONG ValidateTextRange(TEXTRANGE *pstrg);
#ifdef WIN95_IMEDEBUG
extern BOOL forceLevel2;
#endif
// if there's an active object being dragged around, on WM_PAINT we always
// try to reposition it to there it should be. A not-so-well-behaved object
// my generate another WM_PAINT message in response to that, even if it actually
// did not move. So we limit our number of attempts to reposition it and reset
// this counter every time a mouse moves.
// The corresponding field is declared as :2, so don't try to bump it up
// without allocating more bits!!
#define MAX_ACTIVE_OBJ_POS_TRIES (3)
///////////////////////////// Helper Functions ///////////////////////////////////
#if 0
/*
* @doc INTERNAL
*
* IsScreenDC(hdc)
*
* @func
* Determine whether DC is for the screen
*
* @rdesc
* TRUE - DC is to the screen
* FALSE - DC is probably a printer
*
* @devnote
* This is currently not used. However, it might sometime prove useful
* so the code is left here.
*/
BOOL IsScreenDC(
HDC hdc ) //@parm DC to test
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "IsScreenDC");
return (GetDeviceCaps(hdc, LOGPIXELSX) == xPerInchScreenDC)
&& (GetDeviceCaps(hdc, LOGPIXELSY) == yPerInchScreenDC);
}
#endif // 0
/*
* ConvertDrawDCMapping(hdcDraw)
*
* @func
* Put screen DC in MM_TEXT mapping mode.
*/
void ConvertDrawDCMapping(
HDC hdcDraw ) //@parm HDC to draw on
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "ConvertDrawDCMapping");
SaveDC(hdcDraw);
SetViewportOrgEx(hdcDraw, 0, 0, NULL);
SetWindowOrgEx(hdcDraw, 0, 0, NULL);
SetMapMode(hdcDraw, MM_TEXT);
}
/*
* CTxtEdit::FormatAndPrint (hdcDraw, hicTargetDev, ptd, lprcBounds,
* fMakeHeightMax, fPrint )
* @mfunc
* Format and Print data in control
*
* @rdesc
* S_OK - everything worked
* E_FAIL - unexpected failure occurred
*/
HRESULT CTxtEdit::FormatAndPrint(
HDC hdcDraw, //@parm HDC to draw on
HDC hicTargetDev, //@parm Input information context if any
DVTARGETDEVICE *ptd, //@parm Device target information
RECT *lprcBounds, //@parm Rectangle to measure
RECT *lprcWBounds) //@parm Metafile information
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::FormatAndPrint");
// Put client rectangle in format structure
FORMATRANGE fr;
fr.rc = *lprcBounds;
HDC hdcMeasure = NULL;
// Get number of device units per inch
LONG xPerInch = 0;
LONG yPerInch = 0;
if (NULL == lprcWBounds)
{
xPerInch = GetDeviceCaps(hdcDraw, LOGPIXELSX);
yPerInch = GetDeviceCaps(hdcDraw, LOGPIXELSY);
}
else
{
hdcMeasure = CreateMeasureDC(hdcDraw, lprcBounds, FALSE, lprcWBounds->left,
lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom,
&xPerInch, &yPerInch);
}
// Convert rectangle into TWIPS
fr.rc.left = MulDiv(fr.rc.left, LX_PER_INCH, xPerInch);
fr.rc.top = MulDiv(fr.rc.top, LY_PER_INCH, yPerInch);
fr.rc.right = MulDiv(fr.rc.right, LX_PER_INCH, xPerInch);
fr.rc.bottom = MulDiv(fr.rc.bottom, LY_PER_INCH, yPerInch);
// Use message based printing code to do our printing for us
fr.hdc = hdcDraw;
fr.hdcTarget = hicTargetDev;
fr.rcPage = fr.rc;
fr.chrg.cpMin = _pdp->GetFirstVisibleCp();
fr.chrg.cpMost = -1;
// Assume this is all going to work
HRESULT hr = S_OK;
SPrintControl prtcon;
prtcon._fDoPrint = TRUE;
prtcon._fPrintFromDraw = TRUE;
// Print control
if (OnFormatRange(&fr, prtcon, hdcMeasure, xPerInch, yPerInch) == -1)
{
// For some reason the control could not be printed
hr = E_FAIL;
}
if (hdcMeasure != NULL)
{
TxReleaseMeasureDC(hdcMeasure);
}
return hr;
}
/*
* CTxtEdit::RectChangeHelper (dwDrawAspect, lindex, pvAspect, ptd, hdcDraw,
* hicTargetDev, lprcClient, prcLocal)
* @func
* Format and Print data in the control
*
* @rdesc
* S_OK - everything worked
* E_INVALIDARG - client parameter is invalid
*
* @devnote
* Caller must release the DC from the display object.
*/
HRESULT CTxtEdit::RectChangeHelper(
CDrawInfo *pdi, //@parm Draw information memory
DWORD dwDrawAspect, //@parm Draw aspect
LONG lindex, //@parm Currently unused
void * pvAspect, //@parm Info for drawing optimizations (OCX 96)
DVTARGETDEVICE *ptd, //@parm Info on target device
HDC hdcDraw, //@parm Rendering device context
HDC hicTargetDev, //@parm Target information context
const RECT *lprcClient, //@parm New client rectangle
RECT * prcLocal ) //@parm Rect to use if previous parm is NULL
{
TRACEBEGIN(TRCSUBSYSTS, TRCSCOPEINTERN, "CTxtEdit::RectChangeHelper");
HRESULT hr = S_OK;
BOOL fRestore = FALSE;
// We assume that if client's rectangle is supplied, it has changed.
if (lprcClient)
{
// Set up information context if necessary
HDC hicLocal = NULL;
// Did they give us a ptd without a hic?
if (!hicTargetDev && ptd)
{
// Create information context for device information,
// since it wasn't supplied
hicLocal = CreateIC(
(TCHAR *)((BYTE *) ptd + ptd->tdDriverNameOffset),
(TCHAR *)((BYTE *) ptd + ptd->tdDeviceNameOffset),
(TCHAR *)((BYTE *) ptd + ptd->tdPortNameOffset),
(DEVMODE *)((BYTE *) ptd + ptd->tdExtDevmodeOffset));
if (NULL == hicLocal)
{
// Couldn't create it
return E_FAIL;
}
hicTargetDev = hicLocal;
}
// Force DC in MM_TEXT
if(GetMapMode(hdcDraw) != MM_TEXT &&
GetDeviceCaps(hdcDraw, TECHNOLOGY) != DT_METAFILE)
{
fRestore = TRUE;
// Store the input data in our local copy so we can update it
*prcLocal = *lprcClient;
// Convert input parameters to new mapping
WinLPtoDP(hdcDraw, (POINT *)prcLocal, 2);
//
lprcClient = prcLocal;
// Convert HDC to new mapping
ConvertDrawDCMapping(hdcDraw);
}
// Set the DC
_pdp->SetDC(hdcDraw);
// Set the draw information
_pdp->SetDrawInfo(
pdi,
dwDrawAspect,
lindex,
pvAspect,
ptd,
hicTargetDev);
_pdp->ReDrawOnRectChange(hicTargetDev, lprcClient);
if (fRestore)
{
// Put the DC back into the correct mapping mode.
RestoreDC(hdcDraw, -1);
}
if (hicLocal)
{
// Clean up information context if we created one.
DeleteDC(hicLocal);
}
}
else if (_fInPlaceActive)
{
// We can figure out what the client rectangle is.
TxGetClientRect(prcLocal);
lprcClient = prcLocal;
}
else
{
// If not inplace active, a rectangle must be supplied.
hr = E_INVALIDARG;
}
return hr;
}
/*
* CTxtEdit::SetText (pszText, flags)
*
* @mfunc sets the text in the document, clearing out any existing
* text
*
* @rdesc HRESULT
*/
HRESULT CTxtEdit::SetText(
LPCWSTR pszText, //@parm Text to set
SetTextFlags flags) //@parm IGNORE_PROTECTION, CHECK_PROTECTION
{
CCallMgr callmgr(this);
CTxtRange rg(this, 0, 0);// Select whole story
CGenUndoBuilder undobldr(this, 0);
LONG lCleanseResult;
if( flags & CHECK_PROTECTION &&
IsProtectedRange(WM_SETTEXT, 0, (LPARAM)pszText, &rg))
{
return E_ACCESSDENIED;
}
if( _pundo )
{
_pundo->ClearAll();
}
if( _predo )
{
_predo->ClearAll();
}
if (IsRich())
{
// SetText causing all formatting to return to the default. We use
// the notification system to remove the formatting. This is
// particularly important for the final EOP which cannot be deleted.
// Notify every interested party that they should dump their formatting
_nm.NotifyPreReplaceRange(NULL, CONVERT_TO_PLAIN, 0, 0, 0, 0);
// Tell document to dump its format runs
_story.DeleteFormatRuns();
}
rg.Set(0, -(LONG)GetTextLength());
// if we are re-entered, there may be anti-events higher up the
// chain. Grab the undo builder and clear things away if necessary.
undobldr.Discard();
lCleanseResult = rg.CleanseAndReplaceRange(-1, pszText, FALSE, NULL);
if ((0 == lCleanseResult) && (pszText != NULL) && (*pszText != '\0'))
{
// There was an input string but for some reason there was no update.
return E_FAIL;
}
// Setting the text means a new document so if there is a selection
// turn it into an insertion point at the beginning of the document.
if (_psel)
{
_psel->ClearPrevSel();
_psel->Set(0, 0);
// Since the text is being completely replaced and all formatting
// is being lost, let's go back to the default format for the
// selection.
_psel->Set_iCF(-1);
if (_fFocus)
{
// Update the caret to reflect new postion
_psel->UpdateCaret(TRUE);
}
}
// Since we've replaced the entire document, we aren't
// really "modified" anymore. This is necessary to match
// the Windows MLE behavior. However, since RichEdit1.0
// did _not_ do this (they left fModified to be TRUE), we
// only do this for richedit 2.0.
if( !Get10Mode() )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -