Пример #1
0
/*
 *	CRchTxtPtr::InitRunPtrs(cp)
 *
 *	@mfunc
 *		Initialize Run Ptrs of this rich-text ptr to correspond to
 *		document given by ped and to cp given by cp.
 */
void CRchTxtPtr::InitRunPtrs(
	LONG cp)			// @parm character position to move RunPtrs to
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::InitRunPtrs");

	CTxtStory *pStory;

	AssertSz(GetPed(), "RTP::InitRunPtrs: illegal GetPed()");

	if( IsRich() || IsIMERich() )						
	{
		pStory = GetPed()->GetTxtStory();
		if(pStory->_pCFRuns)						//  and there's RichData,
		{											//  initialize format-run ptrs
			_rpCF.SetRunArray((CRunArray *)pStory->_pCFRuns);
			_rpCF.BindToCp(cp);
		}
		if (pStory->_pPFRuns)
		{
			_rpPF.SetRunArray((CRunArray *)pStory->_pPFRuns);
			_rpPF.BindToCp(cp);
		}
	}
 
}
Пример #2
0
// Window procedure
WXLRESULT ExtTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{
   // if we're richtext and read-only, block ctrl-l, -e, -r key strokes
   if (IsRich())
   {
      if (nMsg == WM_KEYDOWN)
      {
         char c = LOWORD(MapVirtualKey(wParam, 2));
         if (c == 'R' || c == 'L' || c == 'E')
         {
            if (GetKeyState(VK_CONTROL) < 0)
               return 0;
         }
         if (GetKeyState(VK_CONTROL) < 0)
         {
            if (wParam == VK_UP)
            {
               return myKeyHandler ? myKeyHandler->OnArrowUpDown(true) : 0;
            }
            else if (wParam == VK_DOWN)
            {
               return myKeyHandler ? myKeyHandler->OnArrowUpDown(false) : 0;
            }
         }
         else if (wParam == ' ')
            if (myKeyHandler)
               return myKeyHandler->OnSpace();
      }
   }

   if (!IsRich())
   {
      if (nMsg == WM_CHAR)
      {
         if (wParam == 1)
         {
            SetSelection(-1, -1);
            return 0;
         }
      }
   }

   // inherited behaviour
   return wxTextCtrl::MSWWindowProc(nMsg, wParam, lParam);
}
Пример #3
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;
}
Пример #4
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;
}