示例#1
0
/*
 * CRchTxtPtr::SetCp(cp)
 *
 *	@mfunc
 *		Set this rich text ptr's cp to cp
 */
DWORD CRchTxtPtr::SetCp(
	DWORD cp)			// @parm new cp for this text ptr
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::SetCp");

	CRchTxtPtr::Advance(cp - GetCp());
	return GetCp();
}
示例#2
0
LONG CRchTxtPtr::GetCchLeftRunPF() 
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetCchLeftRunPF");

	return _rpPF.IsValid()
		? _rpPF.GetCchLeft() : GetTextLength() - GetCp();
}
示例#3
0
/*
 *	CRchTxtPtr::CheckFormatRuns ()
 *
 *	@mfunc
 *		Check the format runs against what's in CTxtStory.  If
 *		different, forces a rebind to <p cp>
 */
void CRchTxtPtr::CheckFormatRuns( )
{
	CTxtStory *pStory = GetPed()->GetTxtStory();

	if( (pStory->GetCFRuns() != (CFormatRuns *)_rpCF._prgRun) ||
		(pStory->GetPFRuns() != (CFormatRuns *)_rpPF._prgRun) )
	{
		InitRunPtrs(GetCp());
	}

	_TEST_INVARIANT_
}
示例#4
0
/*
 *	CRchTxtPtr::FindText(cpMost, dwFlags, pch, cchToFind)
 *	
 *	@mfunc
 *		Find text in a range starting at this text pointer;
 *		if found, moves this text pointer to that position.
 *	
 *	@rdesc
 *		character position of first match
 *		<lt> 0 if no match
 *
 *	@devnote
 *		Would be easy to match a single format (like Word 6) provided
 *		cchToFind is nonzero.  Else need to search runs (also pretty easy).
 *		For format-sensitive searches, might be easier to search for matching
 *		format run first and then within that run search for text.
 */
LONG CRchTxtPtr::FindText (
	LONG		cpMost,		// @parm Limit of search; <lt> 0 for end of text
	DWORD		dwFlags,	// @parm FR_MATCHCASE	case must match
							//		 FR_WHOLEWORD	match must be a whole word
	TCHAR const *pch,		// @parm Text to search for
	LONG		cchToFind)	// @parm Length of text to search for
{

	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::FindText");

	_TEST_INVARIANT_

	LONG cpSave = GetCp();
	LONG cpMatch = _rpTX.FindText(cpMost, dwFlags, pch, cchToFind);

	if(cpMatch >= 0)					// cpMatch = -1 means "not found"
		SetRunPtrs(GetCp(), cpSave);	
	
			// possible code for format-dependent Finds

	return cpMatch;
}
示例#5
0
文件: line.cpp 项目: hufuman/xindows
/*
*  CLinePtr::GetAdjustedLineLength
*
*  @mfunc  returns the length of the line _without_ EOP markers
*
*  @rdesc  LONG; the length of the line
*/
LONG CLinePtr::GetAdjustedLineLength()
{
    CLine* pline = GetCurrRun();
    Assert(pline);

    LONG cchJunk;
    LONG cchTrim;
    CTreePos *ptpRet, *ptpPrev;

    LONG cpEndLine = _pdp->GetFirstCp() + GetCp() - GetIch() + pline->_cch;
    CTreePos* ptp = _pdp->GetMarkup()->TreePosAtCp(cpEndLine, &cchJunk);

    _pdp->EndNodeForLine(cpEndLine, ptp, &cchTrim, &ptpRet, NULL);
    cchTrim = min(cchTrim, pline->_cch);

    LONG cpNewMost = cpEndLine - cchTrim;

    if(ptpRet)
    {
        ptpPrev = ptpRet;

        if(ptpPrev->GetCch()==0 || ptpPrev->IsNode() || (ptpPrev->IsText() && ptpPrev->GetCp()>=cpNewMost))
        {
            do
            {
                ptpPrev = ptpPrev->PreviousTreePos();
            } while(ptpPrev->GetCch() == 0);
        }

        if(ptpPrev->IsEndElementScope() && ptpPrev->Branch()->Tag()==ETAG_BR)
        {
            cchTrim += 2;
        }
        else if(ptpPrev->IsText())
        {
            CTxtPtr tp(_pdp->GetMarkup(), cpNewMost-1);
            if(tp.GetChar() == WCH_ENDPARA1)
            {
                cchTrim++;
            }
        }
    }

    cchTrim = min(cchTrim, pline->_cch);
    return pline->_cch-cchTrim;
}
示例#6
0
/*
 *	CRchTxtPtr::Check_rpPF()
 *	
 *	@mfunc
 *		enable _rpPF if it's not already enabled
 *	
 *	@rdesc
 *		TRUE if _rpPF is enabled
 */
BOOL CRchTxtPtr::Check_rpPF()
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::Check_rpPF");

	if(_rpPF.IsValid())
		return TRUE;

	if( !IsRich() )
		return FALSE;

	if( !_rpPF.InitRuns (GetCp(), GetTextLength(),
				&(GetPed()->GetTxtStory()->_pPFRuns)) )
	{
		return FALSE;
	}

	CNotifyMgr *pnm = GetPed()->GetNotifyMgr();	// For notifying of changes
	if( pnm )
		pnm->NotifyPostReplaceRange(	 		// Notify interested parties
				(ITxNotify *)this, INFINITE,	// of the change.
				0, 0, INFINITE, INFINITE);

	return TRUE;
}
示例#7
0
文件: line.cpp 项目: hufuman/xindows
// Move runptr by a certain number of cch/runs
BOOL CLinePtr::RpAdvanceCp(long cch, BOOL fSkipFrame)
{
    // See if this is a multi-line ptr
    Assert(_prgRun);

    if(cch == CRunPtr<CLine>::AdvanceCp(cch))
    {
        if(fSkipFrame)
        {
            CLine* pLine=GetCurrRun();

            // There might not be a valid run pointer.
            if(pLine && pLine->IsFrame())
            {
                int iStep;
                long iRunEnd;

                Assert(NumRuns());

                if(cch < 0)
                {
                    iStep = -1;
                    iRunEnd = 0;
                }
                else
                {
                    iStep = 1;
                    iRunEnd = NumRuns() - 1;
                }

                while(GetCurrRun()->IsFrame())
                {
                    if(GetIRun() == iRunEnd)
                    {
                        // If the last line is a frame line, then put the
                        // line ptr at the end of the previous line. Assert
                        // that we have a previous line: it will contain the
                        // embedding character for the site in the frame line.
                        Assert(iRunEnd > 0);
                        SetIRun(iRunEnd - 1);
                        if((pLine=GetCurrRun()) != NULL)
                        {
                            SetIch(pLine->_cch);
                        }

#ifdef _DEBUG
                        {
                            CTxtPtr tp(_pdp->GetMarkup(), GetCp()-1);
                            TCHAR ch = tp.GetChar();

                            Assert('\r' != ch);
                        }
#endif
                        return TRUE;
                    }
                    else
                    {
                        SetIRun(GetIRun()+iStep);
                    }
                }
            }
        }
    }
    else
    {
        return FALSE;
    }
    return TRUE;
}
示例#8
0
/*
 *	CRchTxtPtr::ChangeCase(cch, Type, publdr)
 *	
 *	@mfunc
 *		Change case of cch chars starting at this text ptr according to Type,
 *		which has the possible values:
 *
 *		tomSentenceCase	= 0: capitalize first letter of each sentence
 *		tomLowerCase	= 1: change all letters to lower case
 *		tomUpperCase	= 2: change all letters to upper case
 *		tomTitleCase	= 3: capitalize the first letter of each word
 *		tomToggleCase	= 4: toggle the case of each letter
 *	
 *	@rdesc
 *		TRUE iff a change occurred
 *
 *	@devnote
 *		Since this routine only changes the case of characters, it has no
 *		effect on rich-text formatting.  However it is part of the CRchTxtPtr
 *		class in order to notify the display of changes.  CTxtRanges are also
 *		notified just in case the text blocks are modified.
 */
BOOL CRchTxtPtr::ChangeCase (
	LONG		  cch,			//@parm # chars to change case for
	LONG		  Type,			//@parm Type of change case command
	IUndoBuilder *publdr)		//@parm UndoBuilder to receive anti-event
								//  	for any replacements
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::ChangeCase");
	_TEST_INVARIANT_

#define	BUFFERLEN	256

	LONG	cchChunk, cchFirst, cchGet, cchLast;
	BOOL	fAlpha, fToUpper, fUpper;			// Flags controling case change
	BOOL	fChange = FALSE;					// No change yet
	BOOL	fStart = TRUE;						// Start of Word/Sentence
	TCHAR *	pch;								// Ptr to walk rgCh with
	WORD *	pType;								// Ptr to walk rgType with
	TCHAR	rgCh[BUFFERLEN];					// Char buffer to work in
	WORD	rgType[BUFFERLEN];					// C1_TYPE array for rgCh

	if( GetCp() )
	{
		if( Type == tomSentenceCase )
		{
			fStart = _rpTX.IsAtBOSentence();
		}
		else if( Type == tomTitleCase )
		{
			// check to see if we are at the beginning of
			// a word.  This is the case if the character preceeding
			// our current position is white space.
			fStart = IsWhiteSpace(_rpTX.PrevChar());
			_rpTX.AdvanceCp(1);
		}
	}
	while(cch > 0)								// Do 'em all (or as many as
	{											//  in story)
		cchChunk = min(BUFFERLEN, cch);			// Get next bufferful
		cch -= cchChunk;						// Decrement the count
		cchGet = _rpTX.GetText(cchChunk, rgCh);	// Manipulate chars in buffer
		if(cchGet < cchChunk)					//  (for undo, need to use
		{										//  ReplaceRange())
			cch = 0;							// No more chars in story,
			if(!cchGet)							//  so we'll be done
				break;							// We're done already
			cchChunk = cchGet;					// Something in this chunk
		}

		GetStringTypeEx(0, CT_CTYPE1, rgCh,		// Find out whether chars are
						cchChunk, rgType);		//  UC, LC, or neither
		
		cchLast = 0;							// Default nothing to replace
		cchFirst = -1;
		for(pch = rgCh, pType = rgType;			// Process buffered chars
			cchChunk;
			cchChunk--, pch++, pType++)
		{
			fAlpha = *pType & (C1_UPPER | C1_LOWER); // Nonzero if UC or LC
			fUpper = (*pType & C1_UPPER) != 0;	// TRUE if UC
			fToUpper = fStart ? TRUE : fUpper;	// capitalize first letter of a
												// sentence
			switch(Type)
			{									// Decide whether to change
			case tomLowerCase:					//  case and determine start
				fToUpper = FALSE;				//  of word/sentence for title
				break;							//  and sentence cases

			case tomUpperCase:
				fToUpper = TRUE;
				break;

			case tomToggleCase:
				fToUpper = !fUpper;
				break;

			case tomSentenceCase:
				if(*pch == TEXT('.'))			// If sentence terminator,
					fStart = TRUE;				//  capitalize next alpha
				if(fAlpha)						// If this char is alpha, next
					fStart = FALSE;				//  char can't start a
				break;							//  sentence

			case tomTitleCase:					// If this char is alpha, next
				fStart = (fAlpha == 0);			//  char can't start a word
				break;
			default:
				return FALSE;
			}

			if(fAlpha && (fToUpper ^ fUpper))	// Only change case if it
			{									//  makes a difference (saves
				if(fToUpper)					//  on system calls and undos)
					CharUpperBuff(pch, 1);
				else
					CharLowerBuff(pch, 1);

				fChange = TRUE;					// Return value: change made
				if( cchFirst == -1 )			// Save cch of unchanged
					cchFirst = cchGet-cchChunk;	//  leading string
				cchLast = cchChunk - 1;			// Save cch of unchanged
			}									//  trailing string
		}
		if( cchFirst == -1 )
		{
			Assert(cchLast == 0);
			cchFirst = cchGet;
		}

		Advance(cchFirst);						// Skip unchanged leading
		cchGet -= cchFirst + cchLast;			//  string. cchGet = cch of
		ReplaceRange(cchGet, cchGet, rgCh		//  changed span
			+ cchFirst, publdr, tomUndefined);
		Advance(cchLast);						// Skip unchanged trailing 
	}											//  string
	return fChange;
}
示例#9
0
/*
 *	CRchTxtPtr::ReplaceRangeFormatting(cchOld, cchNew, iFormat, publdr,
 *									   ppaeCF, ppaePF, cchMove)
 *	@mfunc
 *		replace character and paragraph formatting at this text pointer
 *		using CCharFormat with index iFormat
 *	
 *	@rdesc
 *		count of new characters added
 *	
 *	@devnote
 *		moves _rpCF and _rpPF to end of replaced text
 *		moves format run arrays
 *		CCharFormat for iFormat is fully configured, i.e., no NINCHes
 */
INLINE LONG CRchTxtPtr::ReplaceRangeFormatting(
	LONG		cchOld,		//@parm length of range to replace
	LONG		cchNew,		//@parm length of replacement text
	LONG		iFormat,	//@parm Char format to use
	IUndoBuilder *publdr,	//@parm UndoBuilder to receive antievents
	IAntiEvent **ppaeCF,	//@parm where to return 'extra' CF anti-events
	IAntiEvent **ppaePF,	//@parm where to return extra PF anti-events
	LONG		cchMove,	//@parm cch to move between PF runs
	LONG		cchPrevEOP,	//@parm cch from _cp back to prev EOP
	LONG		cchNextEOP)	//@parm cch from _cp up to next EOP
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::ReplaceRangeFormatting");

	LONG				cp = GetCp();				
	ICharFormatCache *	pcfc;
	IParaFormatCache *	ppfc;
	DWORD iRunMerge	= 0;

	AssertSz(cchOld >= 0,
		"CRchTxtPtr::ReplaceRangeFormatting: Illegal cchOld");

	if(_rpCF.IsValid())
	{
		iRunMerge = _rpCF._iRun;
		if( iRunMerge > 0 )
		{
			iRunMerge--;
		}

		if(FAILED(GetCharFormatCache(&pcfc)))
			return -1;							// Access to CF caches failed

		if(cchOld > 0)
		{										// add the soon-to-be deleted
			if( publdr )						// formats to the undo list
			{
				*ppaeCF = gAEDispenser.CreateReplaceFormattingAE(
							GetPed(), _rpCF, cchOld, pcfc, CharFormat);
			}
												// Delete/modify CF runs <-->
			_rpCF.Delete(cchOld, pcfc, 0);		//  to cchOld chars
		}
		// If we deleted all of text in story, don't bother adding a new
		// run.	Else insert/modify CF runs corresponding to cchNew chars
		//
		// For IME composition in a plain text control, there is no
		// trailing carriage return and thus need the extra test.
		if(cchNew > 1 || cchNew && ( cchOld < (LONG)GetTextLength()
						|| ( IsIMERich() && cchOld == (LONG)GetTextLength())))
		{
			_rpCF.InsertFormat(cchNew, iFormat, pcfc);
		}
#ifdef DEBUG
 		else if( cchNew > 0 )
		{
			// Make sure that we don't have any format runs; we should
			// be in the new document state.
			Assert(!_rpCF.IsValid());
		}
#endif // DEBUG

		if((cchOld || cchNew) && _rpCF.IsValid())// Deleting all text
		{										//  invalidates _rpCF
			_rpCF.MergeRuns(iRunMerge, pcfc);
			_rpCF.BindToCp(cp + cchNew);
		}
	}

	if(_rpPF.IsValid())
	{
		_rpPF.AdjustForward();					// Be absolutely sure that
												//  PF runs end with EOPs
		iRunMerge = _rpPF._iRun;
		if( iRunMerge > 0 )
		{
			iRunMerge--;
		}

		if(FAILED(GetParaFormatCache(&ppfc)))
			return -1;							// Access to PF caches failed

		if(cchOld)								// Delete cchOld from PF runs
		{										// add the soon-to-be deleted
			if( publdr )						// formats to the undo list
			{
				CFormatRunPtr rp(_rpPF);

				rp.AdvanceCp(cchPrevEOP);
				*ppaePF = gAEDispenser.CreateReplaceFormattingAE(GetPed(),
								rp, cchNextEOP - cchPrevEOP, ppfc, ParaFormat);
			}
		    _rpPF.Delete(cchOld, ppfc, cchMove);
		}

		if(_rpPF.IsValid())						// Deleting all text
		{										//  invalidates _rpPF
			_rpPF.AdjustForward();
			_rpPF.GetRun(0)->_cch += cchNew;	// Insert cchNew into current
			_rpPF._ich	+= cchNew;				//  PF run
			if(cchOld || cchNew)
			{
				_rpPF.MergeRuns(iRunMerge, ppfc);
				_rpPF.BindToCp(cp + cchNew);
			}
		}
	}
	return cchNew;
}
示例#10
0
/*
 *	CRchTxtPtr::ReplaceRange(cchOld, cchNew, *pch, pcpFirstRecalc, publdr,
 *							 iFormat)
 *	@mfunc
 *		Replace a range of text at this text pointer using CCharFormat iFormat
 *		and updating other text runs as needed
 *	
 *	@rdesc
 *		Count of new characters added
 *	
 *	@devnote
 *		Moves this text pointer to end of replaced text.
 *		May move text block and formatting arrays.
 */
LONG CRchTxtPtr::ReplaceRange(
	LONG		cchOld,		// @parm length of range to replace
							//		(<lt> 0 means to end of text)
	LONG		cchNew,		// @parm length of replacement text
	TCHAR const *pch,		// @parm replacement text
	IUndoBuilder *publdr,	// @parm CCharFormat iFormat to use for cchNew
	LONG		iFormat)
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::ReplaceRange");

	LONG		  cch;
	LONG		  cchEndEOP = 0;				// Default 0 final EOP fixup
	LONG		  cchMove = 0;					// Default nothing to move
	LONG		  cchNextEOP = cchOld;			// cch to next EOP
	LONG		  cchPrevEOP = 0;				// cch back to previous EOP
	LONG		  cpFR;							//  between PF runs
	LONG 		  cpSave = GetCp();
	LONG		  cpFormatMin = cpSave;			// Used for notifications
	LONG		  cpFormat = cpSave;			// Will add cchOld, maybe cchMove
	IAntiEvent *  paeCF = NULL;
	IAntiEvent *  paePF = NULL;
	CNotifyMgr *  pnm;
	CObjectMgr *  pobjmgr;

 	_TEST_INVARIANT_

	LONG cchEnd = GetTextLength() - GetCp();
	if(cchOld < 0)
		cchOld = cchEnd;

  	if(IsRich() && cchOld == cchEnd)			// Attempting to delete up
	{											//  thru final EOP
		cchEndEOP = (GetPed()->Get10Mode())		// Calc cch of final EOP
				  ? CCH_EOD_10 : CCH_EOD_20;

		if(cchEndEOP <= cchOld)					// Don't delete it unless
			cchOld -= cchEndEOP;				//  converting from 2.0
	}
	else if(_rpPF.IsValid() && cchOld)			// If PARAFORMATs are enabled,
	{											//  get tp and rp at end of 
		CFormatRunPtr rp(_rpPF);				//  range. Need bounding para
		CTxtPtr 	  tp(_rpTX);				//  counts to save valid PF
		BOOL		  fIsAtBOP;					//  for undo

		tp.AdvanceCp(cchOld);
		rp.AdvanceCp(cchOld);

		cch = 0;
		if(tp.IsAfterEOP())						// Range ends with an EOP:
		{										//  get EOP length by
			cch = -tp.BackupCpCRLF();			//  backing up over it
			tp.AdvanceCp(cch);					// Advance past EOP
		}
		cchNextEOP = tp.FindEOP(tomForward);	// Get cch up to next EOP

		fIsAtBOP = !GetCp() || _rpTX.IsAfterEOP();
		if (!fIsAtBOP && cch == cchOld &&		// Deleting EOP alone before
			!rp.GetIch())						//  new PARAFORMAT run start
		{										//  in para with more than EOP
			cchMove = cchNextEOP;				// Need to move chars up to
			cpFormat += cchMove;				//  end of next para for
		}
		
		cchNextEOP += cchOld;					// Count from GetCp() to EOP
			
		tp.SetCp(GetCp());						// Back to this ptr's _cp
		if(!fIsAtBOP)
			cchPrevEOP = tp.FindEOP(tomBackward);// Get cch to start of para

		// If deleting from within one format run up to or into another, set
		// up to move last para in starting format run into the run following
		// the deleted text
		if(rp.GetFormat() != _rpPF.GetFormat()	// Change of format during  
			&& !fIsAtBOP && !cchMove)			//  deleted text not starting
		{										//  at BOP
			cchMove = cchPrevEOP;				// Get cch to start of para
			cpFormatMin += cchMove;				//  in this ptr's run for
		}										//  moving into rp's run
	}
	
	Assert(cchNew >= 0 && cchOld >= 0);
	if(!(cchNew + cchOld))						// Nothing to do (note: all
		return 0;								//  these cch's are >= 0)

	// Handle pre-replace range notifications.  This method is very
	// useful for delayed rendering of data copied to the clipboard.

	pnm = GetPed()->GetNotifyMgr();
	if( pnm )
	{
		pnm->NotifyPreReplaceRange((ITxNotify *)this, cpSave, cchOld,
			cchNew, cpFormatMin, cpFormat + cchOld);
	}

	if(iFormat >= 0)
		Check_rpCF();

	// Get rid of objects first.  This let's us guarantee that when we
	// insert the objects as part of an undo, the objects themselves are
	// restored _after_ their corresponding WCH_EMBEDDINGs have been
	// added to the backing store.

	if(GetObjectCount())
	{
		pobjmgr = GetPed()->GetObjectMgr();

		Assert(pobjmgr);

		pobjmgr->ReplaceRange(cpSave, cchOld, publdr);
	}

	if( ( IsRich() || IsIMERich() ) && iFormat != tomUndefined)			// Rich text enabled
	{
		// The anti-events used below are a bit tricky (paeCF && paePF).
		// Essentially, this call, CRchTxtPtr::ReplaceRange generates one
		// 'combo' anti-event composed of up to two formatting AE's plus
		// the text anti-event.  These anti-events are combined together
		// to prevent ordering problems during undo/redo.
		cpFR = ReplaceRangeFormatting(cchOld + cchEndEOP, cchNew + cchEndEOP, 
			iFormat, publdr, &paeCF, &paePF, cchMove, cchPrevEOP, cchNextEOP);

		if (cchEndEOP)
		{
			// If we added in the EOP we need to back up by the EOP so
			// that the invariants don't get annoyed and the richtext object
			// doesn't get out of sync.
			_rpCF.AdvanceCp(-cchEndEOP);
			_rpPF.AdvanceCp(-cchEndEOP);
		}
				
		if(cpFR < 0)
		{
			Tracef(TRCSEVERR, "ReplaceRangeFormatting(%ld, %ld, %ld) failed", GetCp(), cchOld, cchNew);
			cch = 0;
			goto Exit;
		}
	}

	// As noted above in the call to ReplaceRangeFormatting, the anti-events
	// paeCF and paePF, if non-NULL, were generated by ReplaceRangeFormatting.
	// In order to solve ordering problems, the anti-event generated by this
	// method is actually a combo anti-event of text && formatting AE's.
	cch = _rpTX.ReplaceRange(cchOld, cchNew, pch, publdr, paeCF, paePF);
	if (cch != cchNew)
	{
		Tracef(TRCSEVERR, "_rpTX.ReplaceRange(%ld, %ld, ...) failed", cchOld, cchNew);

		// Boy, out of memory or something bad.  Dump our formatting and hope
		// for the best.  
		//
		// FUTURE: (alexgo) degrade more gracefully than loosing formatting
		// info.

		// Notify every interested party that they should dump their formatting
		if( pnm )
		{
			pnm->NotifyPreReplaceRange(NULL, CONVERT_TO_PLAIN, 0, 0, 0, 0);
		}

		// Tell document to dump its format runs
		GetPed()->GetTxtStory()->DeleteFormatRuns();
		goto Exit;
	}

	AssertSz(!_rpPF.IsValid() || _rpPF.GetIch() || !GetCp() || _rpTX.IsAfterEOP(),
		"CRchTxtPtr::ReplaceRange: EOP not at end of PF run");
			
	// BUGBUG!! (alexgo) doesn't handle correctly the case where things fail
	// (due to out of memory or whatever).  See also notes in CTxtPtr::HandleReplaceRange
	// Undo.  The assert below is therefore somewhat bogus, but if it fires, 
	// then our floating ranges are going to be in trouble until we fix
	// up the logic here.

	Assert(cch == cchNew);

Exit:

#ifdef DEBUG
	// test the invariant again before calling out to replace range notification;
	// in this way, we can catch bugs earlier. The invariant has its own
	// scope for convenience.
	if( 1 )
	{
		_TEST_INVARIANT_
	}
#endif

	if( pnm )
	{
		pnm->NotifyPostReplaceRange((ITxNotify *)this, cpSave, cchOld, cch,
			cpFormatMin, cpFormat + cchOld);
	}

	GetPed()->GetCallMgr()->SetChangeEvent(CN_TEXTCHANGED);

	return cch;
}
示例#11
0
ASSERTDATA

#define DEBUG_CLASSNAME CRchTxtPtr
#include "_invar.h"

#ifdef DEBUG
/*
 *	CRchTxtPtr::Invariant
 */
BOOL CRchTxtPtr::Invariant( void ) const
{
	unsigned ch;
	DWORD cch;
	DWORD cchLength = GetTextLength();
	LONG cp;

#ifdef EXTREME_CHECKING
	const TCHAR *pch;
	const TCHAR *pchReverse;
	LONG cchvalid;
#endif // EXTREME_CHECKING
	
	_rpTX.Invariant();
	_rpCF.Invariant();
	_rpPF.Invariant();

	if( _rpCF.IsValid() )
	{
		// BEGIN tone down of assert for IME Rich composition.
		CFormatRun *pRun = _rpCF.Elem(0);

		if ( !IsIMERich() || !pRun || pRun->_iFormat != -1 || _rpCF.Count() != 1 )
		// END tone down
		{
			Assert(GetCp()   == (cp  = _rpCF.GetCp()));
			Assert(cchLength == (cch = _rpCF.GetCch()));
		}
	}

	if( _rpPF.IsValid() )
	{
		Assert(GetCp()   == (cp  = _rpPF.GetCp()));
		Assert(cchLength == (cch = _rpPF.GetCch()));

		CTxtPtr	tp(_rpTX);

		tp.AdvanceCp(_rpPF.GetCchLeft() - 1);
		ch = tp.GetChar();
		if(!IsASCIIEOP(ch))
		{
			_rpTX.MoveGapToEndOfBlock();			// Make it easier to see
			AssertSz(FALSE,							//  what's going on
				"CRchTxtPtr::Invariant: PF run doesn't end with EOP");
		}

#ifdef EXTREME_CHECKING
		// we don't do this check normally as it is _extremely_ slow.
		// However, it's very useful for catching para-format run problems

		// now make sure that each para format run ends on a paragraph mark!
		CFormatRunPtr	rppf(_rpPF);

		rppf.BindToCp(0);
		tp.BindToCp(0);

		do
		{
			tp.SetCp(rppf.GetCp() + rppf.GetRun(0)->_cch);
			if( !tp.IsAfterEOP() )
			{
				cp = tp.GetCp();

				pch = tp.GetPch(cchvalid);
				pchReverse = tp.GetPchReverse(cchvalid);
				pchReverse -= cchvalid;
		
				AssertSz(0, "ParaFormat Run not aligned along paragraphs!");
			}
		} while( rppf.NextRun() );
#endif // EXTREME_CHECKING
	}

	return TRUE;
}
示例#12
0
/*	CRchTxtPtr::GetIchRunXX() and CRchTxtPtr::GetCchRunXX()
 *
 *	@mfunc
 *		Text-run management to retrieve current text run cch and offset
 *
 *	@rdesc
 *		current run ich or cch
 *
 *	@devnote
 *		Use of queries like _rpCF.IsValid() instead of an inclusive fRich
 *		allows rich-text formatting to be applied per rich-text category,
 *		e.g., CHARFORMATs, but not necessarily PARAFORMATs.  If the rp isn't
 *		valid, _cp is used for ich and the document length is used for cch,
 *		i.e., the values for a document describable by a single plain-text run
 */
LONG CRchTxtPtr::GetIchRunCF()
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetIchRunCF");

	return _rpCF.IsValid() ? _rpCF.GetIch() : GetCp();
}
示例#13
0
/*
 *	CRchTxtPtr::UnitCounter (Unit, &cUnit, cchMax)
 *
 *	@mfunc
 *		Helper function to count chars in <p cUnit> Units defined by <p Unit>
 *		<p cUnit> is a signed count.  If it extends beyond either end of the
 *		story, count up to that end and update <p cUnit> accordingly.  If
 *		<p cchMax> is nonzero, stop counting when the count exceeds <p cchMax>
 *		in magnitude.
 *
 *	@rdesc
 *		If unit is implemented, return cch corresponding to the units counted
 *		(up to a maximum magnitude of <p cchMax>) and update cUnit;
 *		else return tomForward to signal unit not implemented and cUnit = 0.
 *		If unit is implemented but unavailable, e.g., tomObject with no
 *		embedded objects, return tomBackward.
 *
 *	@devnote
 *		This is the basic engine used by the TOM CTxtRange::Move() and Index()
 *		methods.
 */
LONG CRchTxtPtr::UnitCounter (
	LONG	Unit,				//@parm Type of unit to count
	LONG &	cUnit,				//@parm Count of units to count chars for
	LONG	cchMax)				//@parm Maximum character count
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEINTERN, "CRchTxtPtr::UnitCounter");

	LONG	action;				// Gives direction and tomWord commands
	LONG	cch;				// Collects cch counted
	LONG	cchText = GetTextLength();
	LONG	cp = GetCp();
	LONG	iDir = cUnit > 0 ? 1 : -1;
	LONG	j;					// For-loop index
	CDisplay *pdp;				// Used for tomLine case

	if(!cUnit)									// Nothing to count
	{
		return ((DWORD)Unit > tomObject || !((IMPL >> Unit) & 1))
			? tomForward : 0;					// Indicate Unit not
	}											//  implemented
	if(cchMax <= 0)
		cchMax = tomForward;					// No cch limit

	switch(Unit)
	{
	case tomCharacter:							// Smallest Unit
		cp += cUnit;							// Requested new cp
		ValidateCp(cp);							// Make sure it's OK
		cch = cUnit = cp - GetCp();				// How many cch, cUnits
		break;									//  actually moved

	case tomStory:								// Largest Unit
		cch = (cUnit > 0) ? cchText - cp : -cp;	// cch to start of story
		cUnit = cch ? iDir : 0;					// If already at end/start,
		break;									//  of story, no count

	case tomCharFormat:							// Constant CHARFORMAT
		cch = _rpCF.CountRuns(cUnit, cchMax, cchText);
		break;

	case tomParaFormat:							// Constant PARAFORMAT
		cch = _rpPF.CountRuns(cUnit, cchMax, cchText);
		break;

	case tomObject:
		if(!GetObjectCount())					// No objects: can't move, so
		{
			cUnit = 0;							//  set cUnit = 0 and
			return tomBackward;					//  signal Unit unavailable
		}
		cch = GetPed()->_pobjmgr->CountObjects(cUnit, GetCp());
		break;

	case tomLine:
		pdp = GetPed()->_pdp;
		if(pdp)									// If this story has a display
		{										//  use a CLinePtr
			CLinePtr rp(pdp);
			pdp->WaitForRecalc(cp, -1);
			rp.RpSetCp(cp, FALSE);
			cch = rp.CountRuns(cUnit, cchMax, cchText);
			break;
		}										// Else fall thru to treat as
												//  tomPara
	default:									// tp dependent cases
	  {											// Block to contain tp() which
		CTxtPtr tp(_rpTX);						//  takes time to construct

		if (cUnit < 0)							// Counting backward
		{
			action = (Unit == tomWord)
				? WB_MOVEWORDLEFT : tomBackward;
		}
		else									// Counting forward
		{
			action = (Unit == tomWord)
				? WB_MOVEWORDRIGHT : tomForward;
		}
	
		for (cch = 0, j = cUnit; j && abs(cch) < cchMax; j -= iDir)
		{
			cp = tp.GetCp();					// Save starting cp for
			switch (Unit)						//  calculating cch for this
			{									//  Unit
			case tomWord:
				tp.FindWordBreak(action);
				break;
	
			case tomSentence:
				tp.FindBOSentence(action);
				break;
		
			case tomLine:						// Story has no line array:
			case tomParagraph:					//  treat as tomParagraph
				tp.FindEOP(action);
				break;
		
			default:
				cUnit = 0;
				return tomForward;				// Return error
			}
			if(tp.GetCp() - cp == 0)			// No count:
				break;							//  don't decrement cUnit
			cch += tp.GetCp() - cp;
		}
		cUnit -= j;								// Discount any runs not
	  }											//  counted if |cch| >= cchMax
	}

	if(abs(cch) > cchMax)						// Keep cch within requested
	{											//  limit
		cch = cch > 0 ? cchMax : -cchMax;
		if(Unit == tomCharacter)
			cUnit = cch;
	}		

	Advance(cch);								// Move to new position
	return cch;									// Total cch counted
}