⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 select.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// 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	select.cpp -- Implement the CTxtSelection class |
 *	
 *		This module implements the internal CTxtSelection methods.
 *		See select2.c and range2.c for the ITextSelection methods
 *
 *	Authors: <nl>
 *		Original RichEdit code: David R. Fulmer <nl>
 *		Christian Fortini <nl>
 *		Murray Sargent <nl>
 *
 *	@devnote
 *		The selection UI is one of the more intricate parts of an editor.
 *		One common area of confusion is the "ambiguous cp", that is,
 *		a cp at the beginning of one line, which is also the cp at the
 *		end of the previous line.  We control which location to use by
 *		the _fCaretNotAtBOL flag.  Specifically, the caret is OK at the
 *		beginning of the line (BOL) (_fCaretNotAtBOL = FALSE) except in
 *		three cases:
 *
 *			1) the user clicked at or past the end of a wrapped line,
 *			2) the user typed End key on a wrapped line,
 *			3) the active end of a nondegenerate selection is at the EOL.
 *
 */

#include "_common.h"
#include "_select.h"
#include "_edit.h"
#include "_disp.h"
#include "_measure.h"
#include "_font.h"
#include "_rtfconv.h"
#include "_ime.h"

// GuyBark JupiterJ IME:
#ifndef TARGET_NT
#include <keybd.h>
#endif // !TARGET_NT

#ifndef MACPORT
// default FE Fonts for handling autoFont switching
const TCHAR lpJapanFontName[]		= { 0x0FF2D, 0x0FF33, L' ', 0x0660E, 0x0671D, 0x0 };
const TCHAR lpKoreanFontName[]	= { 0x0AD74, 0x0B9BC, 0x0CCB4, 0x0 };
const TCHAR lpSChineseFontName[]	= { 0x05B8B, 0x04F53, 0x0 };
const TCHAR lpTChineseFontName[]	= { 0x065B0, 0x07D30, 0x0660E, 0x09AD4, 0x0 };
#endif

#define MAX_RUNTOSEARCH (256L)

extern WCHAR	lfJapaneseFaceName[LF_FACESIZE];
extern WCHAR	lfHangulFaceName[LF_FACESIZE];
extern WCHAR	lfBig5FaceName[LF_FACESIZE];
extern WCHAR	lfGB2312FaceName[LF_FACESIZE];

ASSERTDATA

// ======================= Invariant stuff and Constructors ======================================================

#define DEBUG_CLASSNAME CTxtSelection
#include "_invar.h"

#ifdef DEBUG
BOOL
CTxtSelection::Invariant( void ) const
{
	// FUTURE: maybe add some thoughtful asserts...

	static LONG	numTests = 0;
	numTests++;				// how many times we've been called
	
	if(IsInOutlineView() && _cch)
	{
		LONG cpMin, cpMost;					
		GetRange(cpMin, cpMost);

		CTxtPtr tp(_rpTX);					// Scan range for an EOP
		tp.SetCp(cpMin);

		AssertSz((unsigned)(tp.FindEOP(cpMost - cpMin) != 0) == _fSelHasEOP,
			"Incorrect CTxtSelection::_fSelHasEOP");
	}

	return CTxtRange::Invariant();
}
#endif

CTxtSelection::CTxtSelection(CDisplay * const pdp) :
				CTxtRange(pdp->GetED())
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "CTxtSelection::CTxtSelection");

	Assert(pdp);

	_fSel = TRUE;					// This range is a selection
	_pdp = pdp;

	// Set the show selection flag to the inverse of the hide selection flag in 
	// the PED.
	_fShowSelection = !pdp->GetED()->fHideSelection();

	// When we are initialized we don't have a selection therefore,
	// we do want to show the caret.
	_fShowCaret = TRUE;
}	

inline void SelectionNull(CTxtEdit *ped)
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "SelectionNull");

	if(ped)
		ped->SetSelectionToNull();
}
										

CTxtSelection::~CTxtSelection()
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "CTxtSelection::~CTxtSelection");

	// Notify edit object that we are gone (if there's a nonNULL ped, i.e.,
	// if the selection isn't a zombie).
	SelectionNull(GetPed());
}

////////////////////////////////  Assignments  /////////////////////////////////////////


CRchTxtPtr& CTxtSelection::operator =(const CRchTxtPtr& rtp)
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "CTxtSelection::operator =");

    _TEST_INVARIANT_
    return CTxtRange::operator =(rtp);
}

CTxtRange& CTxtSelection::operator =(const CTxtRange &rg)
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "CTxtSelection::operator =");

    _TEST_INVARIANT_
    return CTxtRange::operator =(rg);
}

//////////////////////  Update caret & selection mechanism  ///////////////////////////////

/*
 *	CTxtSelection::Update(fScrollIntoView)
 *
 *	@mfunc
 *		Update selection and/or caret on screen. As a side
 *		effect, this methods ends deferring updates.
 *
 *	@rdesc
 *		TRUE if success, FALSE otherwise
 */
BOOL CTxtSelection::Update (
	BOOL fScrollIntoView)		//@parm TRUE if should scroll caret into view
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "CTxtSelection::Update");

	LONG cch;
	LONG cchSave = _cch;
	LONG cchText = GetTextLength();
	LONG cp, cpMin, cpMost;
	BOOL fMoveBack = _fMoveBack;

	if(!_cch)								// Update _cpAnchor, etc.
		UpdateForAutoWord();

	else if(GetPF()->InTable() && (_fSelHasEOP || _fSelHasCell))
	{
		Expander(_fSelHasEOP ? tomParagraph : tomCell,
				 TRUE, NULL, &cpMin, &cpMost);
	}
				
	if(IsInOutlineView() && !GetPed()->IsMouseDown())
	{
		CPFRunPtr rp(*this);

		cp = GetCp();
		GetRange(cpMin, cpMost);
		if(_cch && (cpMin || cpMost < cchText))
		{
			LONG *pcpMin = &cpMin;
			LONG *pcpMost = &cpMost;

			// If selection contains an EOP, expand to para boundaries
			if(_fSelHasEOP)
			{
				if(_fMoveBack ^ (_cch < 0))	// Decreasing selection
				{							//  size: move active end
					if(_fMoveBack)			
						pcpMost = NULL;		//  to StartOf para
					else
						pcpMin = NULL;		//  to EndOf para				
				}
				Expander(tomParagraph, TRUE, NULL, pcpMin, pcpMost);
			}

			LONG cpMinSave  = cpMin;		// Save initial cp's to see if		
			LONG cpMostSave = cpMost;		//  we need to Set() below

			// The following handles selection expansion correctly, but
			// not compression; need logic like that preceding Expander()
			rp.AdvanceCp(cpMin - cp);		// Start at cpMin
			if(rp.IsCollapsed())
				cpMin += rp.FindExpandedBackward();

			rp.AdjustForward();

			BOOL fCpMinCollapsed = rp.IsCollapsed();
			rp.AdvanceCp(cpMost - cpMin);	// Go to cpMost
			if(rp.IsCollapsed())
				cpMost += rp.FindExpandedForward();

            // GuyBark Jupiter 17766.
            //
            // If fCpMinCollapsed is set, then cpMin is in a collapsed range. Therefore 
            // remove the selection and move the caret to cpMost. That's a reasonable 
            // thing to do.  Also check to see if cpMost is in a collapsed region. If 
            // so, the selection is removed, and the caret is moved to cpMin, This is 
            // also a reasonable thing to do.
            //
            // However, the test of rp.IsCollapsed() is not complete. Say you tap the +
            // for a collapsed header. The header and the entire collapsed range is 
            // selected on the pen down. This includes the final eop for the collapsed
            // range. Then on the pen up, we end up here. The call to rp.IsCollapsed()
            // here checks to see if the cp after the end of selection is in a collapsed range.
            // But the end of the selection here is after the final eop in the range.
            // It's actually at the start of the next visible text, which by definition
            // cannot be collapsed. So the cpMost is found not to be collapsed, and we
            // don't mess with cpMost here. BUT say the collapsed text for the header 
            // selected runs to the end of the document. In this case, there's nothin
            // beyond the final eop in the collapsed range. So when we try to find if 
            // whatever's beyond that is collapsed, we can't. So we say that cpMost 
            // does lie in a collapsed range.
            //
            // So therefore, check if cpMost is at the end of the document. If so, we 
            // won't mess with cpMost here. This makes sense, as how can a non-existant
            // cp beyond the end of the document lie in a collapsed range.
            //
            // This leads to one other change to the RichEdit behavior. In Normal View,
            // select part way through the last header in the document up to the end of
            // the document, (including the final eop). Change to outline view, such that
            // as soon as you get there, the last header will be the last visible line.
            // Previously we found here that cpMin was not in collapsed text, but that 
            // cpMost was. This meant the selection was removed, and the caret is set
            // to the beginning of the header. With this change, we find that cpMost is
            // not in collapsed text, so we don't mess with it. This means by the time 
            // we get to Outline View, the entire header, (and all its collapsed text),
            // is selected. That's how other headers behave in the document too. So this
            // change in behavior is a good thing.

            // At least I think that's what's going on.
#ifdef PWD_JUPITER
			if(fCpMinCollapsed || (rp.IsCollapsed() && (cpMost < cchText)))
#else
			if(fCpMinCollapsed || rp.IsCollapsed())
#endif // PWD_JUPITER
			{
				if(rp.IsCollapsed())
				{
					rp.AdvanceCp(cpMin - cpMost);
					rp.AdjustForward();
					cpMost = cpMin;
				}
				else
					cpMin = cpMost;
			}							
			if(cpMin != cpMinSave || cpMost != cpMostSave)
				Set(cpMost, cpMost - cpMin);
		}
		if(!_cch && rp.IsCollapsed())		// Note: above may have collapsed
		{									//  selection...
			cch = fMoveBack ? rp.FindExpandedBackward() : 0;
			if(rp.IsCollapsed())
#ifdef PWD_JUPITER // GuyBark Jupiter 18391
				cch = rp.FindExpanded(FALSE);
#else
				cch = rp.FindExpanded();
#endif // PWD_JUPITER

			_fExtend = FALSE;
			Advance(cch);
			rp.AdjustForward();
			if(cch <= 0 && rp.IsCollapsed() && _rpTX.IsAfterEOP())
				BackupCRLF();
			_fCaretNotAtBOL = FALSE;
		}
	}

	// Don't let active end be in hidden text
	CCFRunPtr rp(*this);

	cp = GetCp();
	GetRange(cpMin, cpMost);
	if(_cch && (cpMin || cpMost < cchText))
	{
		rp.AdvanceCp(cpMin - cp);		// Start at cpMin
		BOOL fHidden = rp.IsInHidden();
		rp.AdvanceCp(cpMost - cpMin);	// Go to cpMost

		if(fHidden)						// It's hidden, so collapse
			Collapser(tomEnd);			//  selection at End for treatment

		else if(rp.IsInHidden() &&		// cpMin OK, how about cpMost?
			cpMost < cchText)
		{								// Check both sides of edge
			Collapser(tomEnd);			//  collapse selection at end
		}								
	}
	if(!_cch && rp.IsInHidden())		// Note: above may have collapsed
	{									//  selection...
		cch = fMoveBack ? rp.FindUnhiddenBackward() : 0;
		if(!fMoveBack || rp.IsHidden())
			cch = rp.FindUnhidden();

		_fExtend = FALSE;
		Advance(cch);
		_fCaretNotAtBOL = FALSE;
	}
	if((cchSave ^ _cch) < 0)			// Don't change active end
		FlipRange();

	if(!_cch && cchSave)
	{
		Update_iFormat(-1);
		_fCaretNotAtBOL = FALSE;
	}

	_TEST_INVARIANT_

	if( !GetPed()->fInplaceActive() || GetPed()->IsStreaming() )
	{
		// nothing to do while inactive or streaming in text or RTF data.
		return TRUE;
	}

	// Recalc up to active end (caret)
	if(!_pdp->WaitForRecalc(GetCp(), -1))
	{										// Line recalc failure
		Set(0, 0);							// Put caret at start of text 
	}

	ShowCaret(!_cch);
	UpdateCaret(fScrollIntoView);			// Update Caret position, possibly
											//  scrolling it into view
	GetPed()->TxShowCaret(FALSE);
	UpdateSelection();						// Show new selection
	GetPed()->TxShowCaret(TRUE);

	return TRUE;
}

/*
 *	CTxtSelection::CheckSynchCharSet()
 *
 *	@mfunc
 *		Check if the current keyboard matches the current font's charset;
 *		if not, call CheckChangeFont to find the right font
 */
void CTxtSelection::CheckSynchCharSet()
{	
	CTxtEdit*			ped = GetPed();
	const CCharFormat	*pCF;
	UINT				lcidKbd;
	UINT				uKbdCodePage;

	if (_cch)
	{
		// for selection, we need to get the character format at cpMin+1
		CTxtRange rg( ped, GetCpMin()+1, 0 );
		Set_iCF(rg.Get_iCF ());

		_fUseiFormat = TRUE;
	}
		
	pCF = ped->GetCharFormat(_iFormat);

 	// If current font is not set correctly,
	// change to a font preferred by current keyboard.
	lcidKbd = GetKeyboardLCID();
	uKbdCodePage = ConvertLanguageIDtoCodePage(lcidKbd);
	if 	(lcidKbd && pCF && !ped->_fSingleCodePage && 
		 ((UINT)GetCodePage(pCF->bCharSet) != uKbdCodePage) && 
		 pCF->bCharSet != SYMBOL_CHARSET && pCF->bCharSet != DEFAULT_CHARSET &&
		 pCF->bCharSet != OEM_CHARSET &&
		 (!IsFELCID(lcidKbd) || pCF->bCharSet != ANSI_CHARSET ||
		 uKbdCodePage == _JAPAN_CP && ped->_fKANAMode && pCF->bCharSet != SHIFTJIS_CHARSET ) 
		)
	{
		CheckChangeFont (ped, TRUE, lcidKbd, uKbdCodePage);
	}
}

/*
 *	CTxtSelection::UpdateCaret(fScrollIntoView)
 *
 *	@mfunc
 *		This routine updates caret/selection active end on screen. 
 *		It figures its position, size, clipping, etc. It can optionally 
 *		scroll the caret into view.
 *
 *	@rdesc
 *		TRUE if view was scrolled, FALSE otherwise
 *
 *	@devnote
 *		The caret is actually shown on screen only if _fShowCaret is TRUE.
 */
BOOL CTxtSelection::UpdateCaret (
	BOOL fScrollIntoView)	//@parm If TRUE, scroll caret into view if we have
							// focus or if not and selection isn't hidden 
{
	TRACEBEGIN(TRCSUBSYSSEL, TRCSCOPEINTERN, "CTxtSelection::UpdateCaret");
							// of focus
	_TEST_INVARIANT_

	// Is the display currently frozen
	if (_pdp->IsFrozen())
	{
		// Save this call for another time.
		_pdp->SaveUpdateCaret(fScrollIntoView);
		return FALSE;
	}

	BOOL		fAutoVScroll	= FALSE;
	BOOL		fAutoHScroll	= FALSE;
	CTxtEdit* 	ped				= GetPed();
	POINT 		pt;
	CLinePtr 	rp(_pdp);

	RECT		rcClient;
	RECT		rcView;
	LONG		xWidthView;
	LONG		yHeightView;

	LONG		xScroll			= _pdp->GetXScroll();
	LONG		yScroll			= _pdp->GetYScroll();

	INT 		yAbove			= 0;	// ascent of line above & beyond IP
	INT			yAscent         = 0;	// ascent of IP
	INT 		yAscentLine;
	LONG		yBase;					// base of IP & line
	INT 		yBelow			= 0;	// descent of line below & beyond IP
	INT 		yDescent        = 0;    // descent of IP
	INT 		yDescentLine;
	const INT 	yHeightSave		= _yHeightCaret;
	INT			ySum;
	LONG		yViewTop;
	LONG		yViewBottom;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -