Exemplo n.º 1
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#AddAction}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::AddAction(IUndoAction * puact)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(puact);

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	if(m_fCreateMarkIfNeeded && m_viMarks.Size() == 0)
	{
		// m_fCreateMarkIfNeeded probably didn't get reset (TE-4856)
		Assert(m_nDepth <= 0 || m_fStartedNext);

		int hmark;
		CheckHr(Mark(&hmark));
		Assert(hmark == 1); // Should only have 1 mark!
	}
	ContinueUndoTask();
	AddActionAux(puact);
	EndUndoTask();

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("AddAction:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 2
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#BreakUndoTask}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::BreakUndoTask(BSTR bstrUndo, BSTR bstrRedo)
{
	BEGIN_COM_METHOD;
	ChkComBstrArg(bstrUndo);
	ChkComBstrArg(bstrRedo);

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	int nSaveDepth = m_nDepth;

	EndOuterUndoTask();

	BeginUndoTask(bstrUndo, bstrRedo);

	m_nDepth = nSaveDepth;

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("BreakUndoTask:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 3
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#EndUndoTask}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::EndUndoTask()
{
	BEGIN_COM_METHOD;

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	if (m_nDepth <= 0)
	{
		return E_UNEXPECTED;
	}
	else
	{
		--m_nDepth;
		if (m_nDepth == 0)
		{
			// cleans no-op undo tasks
			EndOuterUndoTask();
		}
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("EndUndoTask:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 4
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Commit}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Commit()
{
	BEGIN_COM_METHOD;

	HRESULT hr = E_FAIL;
	HRESULT hrFinal = S_OK;
	if (m_vquact.Size())
	{
		// JohnT 10/22/01: this can happen, typically if the only thing in the sequence is a
		// position mark. We could try to check for that but it doesn't seem worth it. Nothing
		// actually depends on having at least one sequence start here.
		//Assert(m_viSeqStart.Size() > 0);

		// Commit all actions.
		for (int i = 0; i <= m_iuactCurr; i++)
		{
			// If for some reason, we cannot commit an action that is part of a sequence, it's
			// just too bad.  We can't undo a commited action so we might as well just amble on
			// and hope for the best.
			IgnoreHr(hr = m_vquact[i]->Commit());
			if (FAILED(hr))
			{
				hrFinal = hr;
			}
		}

		EmptyStack();
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("Commit:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 5
0
/*----------------------------------------------------------------------------------------------
	Inserts a mark and returns a handle that can be used later to discard all Undo items
	back to the mark. Handle will never be zero.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Mark(int * phMark)
{
	BEGIN_COM_METHOD;
	ChkComOutPtr(phMark);

	// It's only valid to place a mark while no action sequence is in progress.
	if (m_nDepth > 0 && !m_fStartedNext)
		ThrowHr(WarnHr(E_UNEXPECTED));

	m_fCanContinueTask = false; // Can't merge another action into the current task.

	// For now, we are only supporting one mark at a time.
	Assert(m_viMarks.Size() == 0);

	m_viMarks.Push(m_iuactCurr + 1); // index of next action to be added
	*phMark = m_viMarks.Size();

	//StrAnsi sta;
	//sta.Format("mark location: %d\n", m_iuactCurr + 1);
	//::OutputDebugStringA(sta.Chars());

	//::OutputDebugStringA("MARK\n");
	//StrAnsi sta;
	//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
	//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
	//::OutputDebugStringA(sta.Chars());

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("Mark:%d", *phMark);
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 6
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Redo}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Redo(UndoResult * pures)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pures);

	*pures = kuresSuccess;
	// Do not allow actions to be redone if they have not been undone.
	Assert(m_viSeqStart.Size() > 0);
	Assert(m_iCurrSeq <= m_viSeqStart.Size() - 1);

	m_fCanContinueTask = false; // Can't 'continue' the previous task from before the Undo.
	m_fUndoOrRedoInProgress = true;
	HRESULT hrFinal = S_OK;
	int iSeqToRedo = m_iCurrSeq + 1;

	try // to ensure in progress gets cleared.
	{
		int handle;
		// Start a 'transaction' if possible to group together all the stuff we're going to Undo.
		if (m_qundg)
		{
			m_qundg->BeginGroup(&handle);
		}

		// Determine the last action to be redone; The last action to redo is the action
		// before the next redo sequence. Or the last existing action if there is not a
		// redo sequence after the sequence we are about to redo.
		int iLastRedoAct = m_vquact.Size() - 1;
		if (iSeqToRedo <= m_viSeqStart.Size() - 2)
			iLastRedoAct = m_viSeqStart[iSeqToRedo + 1] - 1;

		// Loop through all of the actions that are about to be redone and see if any of them
		// require a refresh.
		for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(true));
		}

		// Redo all the actions in the next action sequence that change data.
		hrFinal = CallRedo(pures, true, iSeqToRedo, iLastRedoAct);

		// Now do all the PropChangeds
		for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(false));
		}

		// REVIEW (TimS/EberhardB): What do we do if the call to CallRedo above failed somewhere?
		// Should we do this at all? Or just until the failed action? Or everything?
		UndoResult uresTmp = kuresSuccess;
		// Redo all the actions in the next action sequence that don't change data.
		HRESULT hr;
		IgnoreHr(hr = CallRedo(&uresTmp, false, iSeqToRedo, iLastRedoAct));
		if (FAILED(hr))
		{
			hrFinal = hr;
			*pures = uresTmp;
		}
		else if (uresTmp == kuresFailed)
		{
			*pures = uresTmp;
		}

		// dlh testing
		if (*pures == kuresError || * pures == kuresFailed)
		{
			if (m_qundg)
				m_qundg->CancelGroup(handle);
			EmptyStack();
		}
		else // normal success case
		{
			// Set the current sequence and action.
			m_iCurrSeq++;
			m_iuactCurr = m_vquact.Size() - 1;
			if (m_iCurrSeq < m_viSeqStart.Size() - 1)
			{
				m_iuactCurr = m_viSeqStart[m_iCurrSeq + 1] - 1;
			}
			if (m_qundg)
				m_qundg->EndGroup(handle);
		}


#ifdef DEBUG_ACTION_HANDLER
		StrAnsi sta;
		sta.Format("Redo:");
		sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
			m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
		::OutputDebugStringA(sta.Chars());
#endif //DEBUG_ACTION_HANDLER
	}
	catch(...)
	{
		m_fUndoOrRedoInProgress = false;
		throw;
	}
	m_fUndoOrRedoInProgress = false;

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 7
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Undo}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Undo(UndoResult * pures)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pures);

	*pures = kuresSuccess;

	Assert(m_iCurrSeq >= 0);
	Assert(m_vquact.Size() > 0);

	HRESULT hr = E_FAIL;
	HRESULT hrFinal = S_OK;

	m_fCanContinueTask = false; // Can't 'continue' the previous task from before the Undo.
	m_fUndoOrRedoInProgress = true;

	try // to ensure in progress gets cleared.
	{
		int handle;
		// Start a 'transaction' if possible to group together all the stuff we're going to Undo.
		if (m_qundg)
		{
			m_qundg->BeginGroup(&handle);
		}

		// Loop through all of the actions that are about to be undone and see if any of them
		// require a refresh.
		Vector<long> vhvoCreatedObjects;
		for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(true));
		}

		// Undo all actions from the current action back to the first action of the current action
		// sequence.
		bool fRedoable = true;
		IgnoreHr(hrFinal = CallUndo(pures, fRedoable, true));

		// Now do all the PropChangeds
		for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(false));
		}

		// REVIEW (TimS/EberhardB): What do we do if the call to CallUndo above failed somewhere?
		// Should we do this at all? Or just until the failed action? Or everything?
		UndoResult uresTmp;
		IgnoreHr(hr = CallUndo(&uresTmp, fRedoable, false));
		if (FAILED(hr))
		{
			hrFinal = hr;
			*pures = uresTmp;
		}
		else if (uresTmp == kuresFailed)
		{
			*pures = uresTmp;
		}

		// dlh testing
		if (*pures == kuresError || * pures == kuresFailed)
		{
			if (m_qundg)
				m_qundg->CancelGroup(handle);
			EmptyStack();
		}
		else // normal success case
		{
			// Set the current action and start of the current action sequence.
			if (m_iCurrSeq >= 0)
			{
				m_iuactCurr = m_viSeqStart[m_iCurrSeq] - 1;
				m_iCurrSeq = m_iCurrSeq - 1;
			}
			if (m_qundg)
				m_qundg->EndGroup(handle);
		}

		// Delete any marks that now point after current undo action
		CleanUpMarks();

		if (!fRedoable)
			CleanUpRedoActions(true);

#ifdef DEBUG_ACTION_HANDLER
		StrAnsi sta;
		sta.Format("Undo:");
		sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
			m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
		::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER
	}
	catch(...)
	{
		CleanUpMarks();
		m_fUndoOrRedoInProgress = false;
		throw;
	}
	m_fUndoOrRedoInProgress = false;

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 8
0
/*----------------------------------------------------------------------------------------------
	Discard all Undo items back to the specified mark (or the most recent mark, if any,
	if handle is zero).
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::DiscardToMark(int hMark)
{
	BEGIN_COM_METHOD;
	// It's only valid to discard while no action sequence is in progress.
	if (m_nDepth > 0)
	{
		ThrowHr(WarnHr(E_UNEXPECTED));
	}
	m_fCanContinueTask = false; // Can't merge another action into the current task.

	// The handle hMark is 1 + the position of the mark in the mark stack.
	int iMarkGoal = (hMark == 0) ? m_viMarks.Size() - 1 : hMark - 1;

	if (iMarkGoal >= m_viMarks.Size() || iMarkGoal < 0)
		return E_INVALIDARG;

	//::OutputDebugStringA("Entering DiscardToMark\n");
	//StrAnsi sta;
	//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
	//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
	//::OutputDebugStringA(sta.Chars());

	int iuactMark = m_viMarks[iMarkGoal];
	int iuact;
	for (iuact = m_vquact.Size() - 1; iuact >= iuactMark; iuact--)
	{
		m_vquact.Delete(iuact);
	}
	m_iuactCurr = min(m_iuactCurr, m_vquact.Size() - 1);

	for (iuact = m_viSeqStart.Size() - 1; iuact >= 0; iuact--)
	{
		if (m_viSeqStart[iuact] < m_vquact.Size())
			break;
		m_viSeqStart.Delete(iuact);
		m_vstuUndo.Delete(iuact);
		m_vstuRedo.Delete(iuact);
	}
	m_iCurrSeq = min(m_iCurrSeq, m_viSeqStart.Size() - 1);

	// Delete the mark(s).
	for (int iMarkTmp = m_viMarks.Size() - 1; iMarkTmp >= iMarkGoal; iMarkTmp--)
	{
		m_viMarks.Delete(iMarkTmp);
	}

	//::OutputDebugStringA("After DiscardToMark\n");
	//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
	//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
	//::OutputDebugStringA(sta.Chars());

	// For now, we are only supporting one mark at a time:
	Assert(m_viMarks.Size() == 0);

	// If the depth is greater than zero, we're in the middle of recording a task, so
	// get back in the state where we can close it out.
	if (m_nDepth > 0)
	{
		Assert(m_viSeqStart.Size() == m_vstuUndo.Size());
		Assert(m_viSeqStart.Size() == m_vstuRedo.Size());

		m_fStartedNext = true;

		//::OutputDebugStringA("Leaving DiscardToMark\n");
		//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
		//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
		//::OutputDebugStringA(sta.Chars());
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("DiscardToMark:%d", hMark);
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Exemplo n.º 9
0
/*----------------------------------------------------------------------------------------------
	Write the given FontInfo string text property value in readable XML format.

	@param pstrm Pointer to an IStream for output.
	@param bstrVal
----------------------------------------------------------------------------------------------*/
void FwXml::WriteBulNumFontInfo(IStream * pstrm, BSTR bstrVal, int cchIndent)
{
	AssertPtr(pstrm);
	Assert(cchIndent >= 0);
	int cchProps = ::SysStringLen(bstrVal);
	if (!cchProps)
		return;

	Vector<char> vchIndent;
	vchIndent.Resize(cchIndent + 1);
	memset(vchIndent.Begin(), ' ', cchIndent);

	const OLECHAR * pchProps = bstrVal;
	const OLECHAR * pchPropsLim = pchProps + cchProps;

	FormatToStream(pstrm, "%s<BulNumFontInfo", vchIndent.Begin());
	StrAnsi staItalic;
	StrAnsi staBold;
	StrAnsi staSuperscript;
	StrAnsi staUnderline;
	StrAnsi staFontsize;
	StrAnsi staOffset;
	StrAnsi staForecolor;
	StrAnsi staBackcolor;
	StrAnsi staUndercolor;
	StrAnsi staXXX;
	int tpt;
	while (pchProps < pchPropsLim)
	{
		tpt = *pchProps++;
		if (tpt == ktptFontFamily)
			break;

		int nVal = *pchProps + ((*(pchProps + 1)) << 16);
		pchProps += 2;
		switch (tpt)
		{
		case ktptItalic:
			staItalic.Format(" italic=\"%s\"", ToggleValueName((byte)nVal));
			break;
		case ktptBold:
			staBold.Format(" bold=\"%s\"", ToggleValueName((byte)nVal));
			break;
		case ktptSuperscript:
			staSuperscript.Format(" superscript=\"%s\"", SuperscriptValName((byte)nVal));
			break;
		case ktptUnderline:
			staUnderline.Format(" underline=\"%s\"", UnderlineTypeName((byte)nVal));
			break;
		case ktptFontSize:
			staFontsize.Format(" fontsize=\"%dmpt\"", nVal);
			break;
		case ktptOffset:
			staOffset.Format(" offset=\"%dmpt\"", nVal);
			break;
		case ktptForeColor:
			staForecolor.Format(" forecolor=\"%s\"", ColorName(nVal));
			break;
		case ktptBackColor:
			staBackcolor.Format(" backcolor=\"%s\"", ColorName(nVal));
			break;
		case ktptUnderColor:
			staUndercolor.Format(" undercolor=\"%s\"", ColorName(nVal));
			break;
		default:
			staXXX.FormatAppend(" prop_%u=\"%d\"", tpt, nVal);
			break;
		}
	}
	ULONG cb;
	// Write the integer valued properties in alphabetical order.
	if (staBackcolor.Length())
		pstrm->Write(staBackcolor.Chars(), staBackcolor.Length(), &cb);
	if (staBold.Length())
		pstrm->Write(staBold.Chars(), staBold.Length(), &cb);
	if (staFontsize.Length())
		pstrm->Write(staFontsize.Chars(), staFontsize.Length(), &cb);
	if (staForecolor.Length())
		pstrm->Write(staForecolor.Chars(), staForecolor.Length(), &cb);
	if (staItalic.Length())
		pstrm->Write(staItalic.Chars(), staItalic.Length(), &cb);
	if (staOffset.Length())
		pstrm->Write(staOffset.Chars(), staOffset.Length(), &cb);
	if (staSuperscript.Length())
		pstrm->Write(staSuperscript.Chars(), staSuperscript.Length(), &cb);
	if (staUndercolor.Length())
		pstrm->Write(staUndercolor.Chars(), staUndercolor.Length(), &cb);
	if (staUnderline.Length())
		pstrm->Write(staUnderline.Chars(), staUnderline.Length(), &cb);
	if (staXXX.Length())
		pstrm->Write(staXXX.Chars(), staXXX.Length(), &cb);
	// Write the string valued property (if it exists).
	if (tpt == ktptFontFamily && pchProps < pchPropsLim)
	{
		FormatToStream(pstrm, " fontFamily=\"");
		WriteXmlUnicode(pstrm, pchProps, pchPropsLim - pchProps);
		FormatToStream(pstrm, "\"");
	}
	FormatToStream(pstrm, "/>%n");
}