Click here to Skip to main content
15,883,843 members
Articles / Desktop Programming / MFC

Formula Editor

Rate me:
Please Sign up or sign in to vote.
4.98/5 (306 votes)
15 Apr 20039 min read 558K   14.7K   361  
Formula-editor for editing and exporting mathematical content
// undo.h implementation
// Author - Keith Rule (keithr@dsl-only.net)
//
// A description of this code can be found in May 1997 - Windows Tech Journal.

#ifndef _UNDO_H_
#define _UNDO_H_
//------------------------------------------------------------
//  Undo/Redo for MFC By Keith Rule
class CUndo {
private:
	CObList	m_undolist;		// Stores undo states
	CObList	m_redolist;		// Stores redo states
	long	m_growsize;		// Adjust for faster saves
	long	m_undoLevels;	// Requested Undolevels 
	long	m_chkpt;

	void AddUndo(CMemFile*);
	void AddRedo(CMemFile *pFile); 
	void Load(CMemFile*);
	void Store(CMemFile*);
	void ClearRedoList();
	
public:

	// Here are the hooks into the CDocument class
	virtual void Serialize(CArchive& ar) = 0;
	virtual void DeleteContents() = 0;

	// User accessable functions
	CUndo(long undolevels = 4, long = 32768);	// Constructor
	~CUndo();			// Destructor
	BOOL CanUndo();		// Returns TRUE if can Undo
	BOOL CanRedo();		// Returns TRUE if can Redo
	void Undo();		// Restore next Undo state
	void Redo();		// Restore next Redo state				
	void CheckPoint();	// Save current state 
	void EnableCheckPoint();
	void DisableCheckPoint();
};

// Constructor
inline CUndo::
CUndo(long undolevels, long growsize) : 
	m_growsize(growsize), m_undoLevels(undolevels),
	m_chkpt(0)
{
		;
} 

// Remove contents of the redo list
inline void CUndo::
ClearRedoList()
{
	// Clear redo list
	POSITION pos = m_redolist.GetHeadPosition(); 
	CMemFile* nextFile = NULL;
	while(pos) {
		nextFile = (CMemFile *) m_redolist.GetNext(pos);
		delete nextFile;
	}
	m_redolist.RemoveAll();	
}

// Destructor
inline CUndo::
~CUndo() 
{
	// Clear undo list
	POSITION pos = m_undolist.GetHeadPosition(); 
	CMemFile  *nextFile = NULL;
	while(pos) {
		nextFile = (CMemFile *) m_undolist.GetNext(pos);
		delete nextFile;
	}
	m_undolist.RemoveAll();	

	// Clear redo list
	ClearRedoList();
}

// Checks undo availability, may be used to enable menus
inline BOOL CUndo::
CanUndo() 
{
	return (m_undolist.GetCount() > 1);
}

// Checks redo availability, may be used to enable menus
inline BOOL CUndo::
CanRedo() 
{
	return (m_redolist.GetCount() > 0);
}

// Adds state to the beginning of undo list		
inline void CUndo::
AddUndo(CMemFile* file) 
{
	// Remove old state if there are more than max allowed
	if (m_undolist.GetCount() > m_undoLevels) {
		CMemFile* pFile = (CMemFile *) m_undolist.RemoveTail();
		delete pFile;
	}
	// Add new state to head of undo list
	m_undolist.AddHead(file);
}

// Saves current object into CMemFile instance
inline void CUndo::
Store(CMemFile* file) 
{
	file->SeekToBegin();
	CArchive ar(file, CArchive::store);
	Serialize(ar); 
	ar.Close();
}

// Loads CMemfile instance to current object
inline void CUndo::
Load(CMemFile* file) 
{
	DeleteContents(); 
	file->SeekToBegin();
	CArchive ar(file, CArchive::load);
	Serialize(ar); 
	ar.Close();
}

// Save current object state to Undo list
inline void CUndo::
CheckPoint() 
{
	if (m_chkpt <= 0) {
		CMemFile* file = new CMemFile(m_growsize);
		Store(file);
		AddUndo(file);
		ClearRedoList();
	}
}

inline void CUndo::
EnableCheckPoint()
{
	if (m_chkpt > 0) {
		m_chkpt--;
	}
}

inline void CUndo::
DisableCheckPoint()
{
	m_chkpt++;
}

// Place CMemFile instnace on Redo list
inline void CUndo::
AddRedo(CMemFile *file) 
{
	// Move state to head of redo list
	m_redolist.AddHead(file);
}

// Perform an Undo command
inline void CUndo::
Undo() 
{
	if (CanUndo()) {
		// Remember that the head of the undo list
		// is the current state. So we just move that
		// to the Redo list and load then previous state.
		CMemFile *pFile = (CMemFile *) m_undolist.GetHead();
		m_undolist.RemoveHead();
		AddRedo(pFile);
		pFile = (CMemFile *)m_undolist.GetHead();
		Load(pFile);
	}
}

//Perform a Redo Command
inline void CUndo::
Redo() 
{
	if (CanRedo()) {
		CMemFile *pFile = (CMemFile *) m_redolist.GetHead() ;
		m_redolist.RemoveHead();
		AddUndo(pFile);
		Load(pFile);
	}
}

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
tbw
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions