Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

374 lines
11 KiB

  1. /*
  2. * _M_UNDO.H
  3. *
  4. * Purpose:
  5. * declares multi-level undo interfaces and classes
  6. *
  7. * Author:
  8. * alexgo 3/25/95
  9. *
  10. * Copyright (c) 1995-1998, Microsoft Corporation. All rights reserved.
  11. */
  12. #ifndef __M_UNDO_H__
  13. #define __M_UNDO_H__
  14. #include "_callmgr.h"
  15. // Forward declaration to get around dependency cycle
  16. class CTxtEdit;
  17. class IUndoBuilder;
  18. /*
  19. * MergeDataTypes
  20. *
  21. * @enum Tags indicating the different data types that can be
  22. * sent in IAntiEvent::MergeData
  23. */
  24. enum MergeDataTypes
  25. {
  26. MD_SIMPLE_REPLACERANGE = 1, //@emem a simple replace range;
  27. //usually just typing or backspace
  28. MD_SELECTIONRANGE = 2 //@emem the selection location
  29. };
  30. /*
  31. * SimpleReplaceRange
  32. *
  33. * @stuct SimpleReplaceRange | has the data from a replace range operation
  34. * *except* for any deleted characters. If we don't have to save
  35. * the deleted characters, we don't.
  36. */
  37. struct SimpleReplaceRange
  38. {
  39. LONG cpMin; //@field cpMin of new text
  40. LONG cpMax; //@field cpMax of new text
  41. LONG cchDel; //@field number of characters deleted
  42. };
  43. /*
  44. * SELAEFLAGS
  45. *
  46. * @enum Flags to control how the selection range info should be treated
  47. */
  48. enum SELAE
  49. {
  50. SELAE_MERGE = 1,
  51. SELAE_FORCEREPLACE = 2
  52. };
  53. /*
  54. * SelRange
  55. *
  56. * @struct SelRange | has the data for a selection's location _and_ the
  57. * information needed to generate an undo action for the selection
  58. * placement
  59. *
  60. * @comm -1 may be used to NO-OP any field
  61. */
  62. struct SelRange
  63. {
  64. LONG cp; //@field Active end
  65. LONG cch; //@field Signed extension
  66. LONG cpNext; //@field cp for the inverse of this action
  67. LONG cchNext; //@field Extension for the inverse of this action
  68. SELAE flags; //@field Controls how this info is interpreted
  69. };
  70. /*
  71. * IAntiEvent
  72. *
  73. * Purpose:
  74. * AntiEvents undo 'normal' events, like typing a character
  75. */
  76. class IAntiEvent
  77. {
  78. public:
  79. virtual void Destroy( void ) = 0;
  80. // It should be noted that CTxtEdit * here is really just a general
  81. // closure, i.e. it could be expressed by void *. However, since
  82. // this interface is currently just used internally, I've opted
  83. // to use the extra type-checking. alexgo
  84. virtual HRESULT Undo( CTxtEdit *ped, IUndoBuilder *publdr ) = 0;
  85. // This method will let us merge in arbitrary data for things like
  86. // group typing
  87. virtual HRESULT MergeData( DWORD dwDataType, void *pdata) = 0;
  88. // This method is called when anti-event is committed to undo stack.
  89. // Allows us to handle re-entrancy better for OLE objects.
  90. virtual void OnCommit(CTxtEdit *ped) = 0;
  91. // These two methods allow AntiEvents to be chained together in
  92. // a linked list
  93. virtual void SetNext( IAntiEvent *pNext ) = 0;
  94. virtual IAntiEvent *GetNext( void ) = 0;
  95. protected:
  96. ~IAntiEvent() {;}
  97. };
  98. /*
  99. * IUndoMgr
  100. *
  101. * Purpose:
  102. * interface for managing "stacks" of anti-events
  103. */
  104. class IUndoMgr
  105. {
  106. public:
  107. virtual void Destroy( void ) = 0;
  108. virtual DWORD SetUndoLimit( DWORD dwLim ) = 0;
  109. virtual DWORD GetUndoLimit( ) = 0;
  110. virtual HRESULT PushAntiEvent( UNDONAMEID idName, IAntiEvent *pae ) = 0;
  111. virtual HRESULT PopAndExecuteAntiEvent( void* pAE) = 0;
  112. virtual UNDONAMEID GetNameIDFromAE( void *pAE) = 0;
  113. virtual IAntiEvent *GetMergeAntiEvent( void ) = 0;
  114. virtual void* GetTopAECookie( void ) = 0;
  115. virtual void ClearAll() = 0;
  116. virtual BOOL CanUndo() = 0;
  117. virtual void StartGroupTyping() = 0;
  118. virtual void StopGroupTyping() = 0;
  119. protected:
  120. ~IUndoMgr() {;}
  121. };
  122. /*
  123. * USFlags
  124. *
  125. * @enum
  126. * flags affecting the behaviour of Undo stacks
  127. */
  128. enum USFlags
  129. {
  130. US_UNDO = 1, //@emem regular undo stack
  131. US_REDO = 2 //@emem Undo stack is for REDO functionality
  132. };
  133. /*
  134. * CUndoStack
  135. *
  136. * @class
  137. * manages a stack of anti-events. These anti-events are kept in
  138. * a resizable ring buffer. exports the IUndoMgr interface
  139. */
  140. class CUndoStack : public IUndoMgr
  141. {
  142. //@access Public Methods
  143. public:
  144. virtual void Destroy( void ); //@cmember Destroy
  145. virtual DWORD SetUndoLimit( DWORD dwLim ); //@cmember Set item limit
  146. virtual DWORD GetUndoLimit();
  147. virtual HRESULT PushAntiEvent(UNDONAMEID idName, IAntiEvent *pae); //@cmember
  148. // add an AE to the stack
  149. virtual HRESULT PopAndExecuteAntiEvent( void *pAE); //@cmember
  150. // execute the most recent anti
  151. // event or up to dwDoToCookie
  152. virtual UNDONAMEID GetNameIDFromAE( void *pAE);//@cmember Get
  153. //name of the given AE
  154. virtual IAntiEvent *GetMergeAntiEvent( void ); //@cmember get the most
  155. //recent AE of the merge state
  156. virtual void* GetTopAECookie( void ); //@cmember get a cookie for the
  157. //top AE
  158. virtual void ClearAll(); //@cmember delete all AEs
  159. virtual BOOL CanUndo(); //@cmember something to undo?
  160. virtual void StartGroupTyping(); //@cmember starts group typing
  161. virtual void StopGroupTyping(); //@cmember stops group typing
  162. // Public methods; not part of IUndoMgr
  163. HRESULT EnableSingleLevelMode(); //@cmember RE1.0 undo mode
  164. void DisableSingleLevelMode(); //@cmember back to RE2.0 mode
  165. //@cmember are we in 1.0 mode?
  166. BOOL GetSingleLevelMode() { return _fSingleLevelMode; }
  167. CUndoStack( CTxtEdit *ped, DWORD & rdwLim, USFlags flags );
  168. private:
  169. ~CUndoStack();
  170. struct UndoAction
  171. {
  172. IAntiEvent * pae;
  173. UNDONAMEID id;
  174. };
  175. void Next( void ); //@cmember advances by 1
  176. void Prev( void ); //@cmember advances by -1
  177. DWORD GetPrev( void ); //@cmember get previous index
  178. //@cmember TRUE iff cookie
  179. // ae in in ae list
  180. BOOL IsCookieInList( IAntiEvent *pae, IAntiEvent *paeCookie);
  181. //@cmember transfer this object to
  182. // a new stack
  183. void TransferToNewBuffer(UndoAction *prgnew, DWORD dwLimNew);
  184. UndoAction *_prgActions; //@cmember The list of AEs
  185. DWORD _dwLim; //@cmember the undo limit
  186. DWORD _index; //@cmember current index
  187. CTxtEdit * _ped; //@cmember Big Papa
  188. unsigned long _fGroupTyping : 1; //@cmember Group Typing flag
  189. unsigned long _fMerge : 1; //@cmember Merge flag
  190. unsigned long _fRedo : 1; //@cmember Stack is the redo
  191. // stack.
  192. unsigned long _fSingleLevelMode :1; //@cmember Indicates if single
  193. // level undo mode is on. Valid
  194. // only for the undo stack
  195. // but not the redo stack
  196. };
  197. /*
  198. * IUndoBuilder
  199. *
  200. * Purpose:
  201. * provides a closure for collecting a sequence of anti-events (such
  202. * as all of the anti-events involved in doing an intra-edit drag-move
  203. * operation.
  204. */
  205. class IUndoBuilder
  206. {
  207. public:
  208. // Names anti-event collection
  209. virtual void SetNameID( UNDONAMEID idName ) = 0;
  210. // Adds a new anti-event to the collection
  211. virtual HRESULT AddAntiEvent( IAntiEvent *pae ) = 0;
  212. // Gets top most anti-event in this undo context. This method
  213. // is useful for grouped typing (merging anti-events)
  214. virtual IAntiEvent *GetTopAntiEvent( ) = 0;
  215. // Commits anti-event collection
  216. virtual HRESULT Done( void ) = 0;
  217. // Get rid of any anti-events that have been collected.
  218. virtual void Discard( void ) = 0;
  219. // Notify that a group-typing session should start (forwarded
  220. // to the undo manager)
  221. virtual void StartGroupTyping() = 0;
  222. // Notify that a group-typing session should stop (forwarded
  223. // to the undo manager)
  224. virtual void StopGroupTyping() = 0;
  225. };
  226. /*
  227. * UBFlags
  228. *
  229. * @enum
  230. * flags affecting the behaviour of Undo builders
  231. */
  232. enum UBFlags
  233. {
  234. UB_AUTOCOMMIT = 1, //@emem call IUndoBuilder::Done before delete
  235. UB_REDO = 2, //@emem Undo builder is for REDO functionality
  236. UB_DONTFLUSHREDO = 4 //@emem don't flush redo stack when adding
  237. // anti-events to the undo stack
  238. };
  239. /*
  240. * CGenUndoBuilder
  241. *
  242. * @class
  243. * A general purpose undo builder. It can be easily allocated and freed
  244. * on the stack and simply puts new anti-events at the beginning of an
  245. * anti-event linked list. NO attempt is made to optimize or reorder
  246. * anti-events.
  247. */
  248. class CGenUndoBuilder : public IUndoBuilder, public IReEntrantComponent
  249. {
  250. //@access Public methods
  251. public:
  252. virtual void SetNameID( UNDONAMEID idName ); //@cmember set the name
  253. virtual HRESULT AddAntiEvent(IAntiEvent *pae); //@cmember add an AE
  254. virtual IAntiEvent *GetTopAntiEvent( ); //@cmember get top AE
  255. virtual HRESULT Done( void ); //@cmember Commit AEs
  256. virtual void Discard( void ); //@cmember Discard AEs
  257. virtual void StartGroupTyping(void); //@cmember start GT
  258. virtual void StopGroupTyping(void); //@cmember stop GT
  259. CGenUndoBuilder(CTxtEdit *ped, DWORD flags, //@cmember Constructor
  260. IUndoBuilder **ppubldr = NULL);
  261. ~CGenUndoBuilder( ); //@cmember Destructor
  262. // IReEntrantComponent methods
  263. virtual void OnEnterContext() {;} //@cmember reentered notify
  264. //@access Private methods
  265. private:
  266. IUndoBuilder * _publdrPrev; //@cmember Ptr to undobldr
  267. // higher in stack
  268. IUndoMgr * _pundo; //@cmember Ptr to undo mgr
  269. CTxtEdit * _ped; //@cmember Ptr to edit contxt
  270. UNDONAMEID _idName; //@cmember current name
  271. IAntiEvent * _pfirstae; //@cmember AE list
  272. UINT _fAutoCommit:1; //@cmember AutoCommit on?
  273. UINT _fStartGroupTyping:1; //@cmember GroupTyping on?
  274. UINT _fRedo:1; //@cmember UB destination is
  275. // the redo stack
  276. UINT _fDontFlushRedo:1; //@cmember Don't flush redo
  277. // stack; i.e. we are
  278. // invoking a redo action
  279. UINT _fInactive:1; //@cmember TRUE if undo enabled
  280. };
  281. /*
  282. * CUndoStackGuard
  283. *
  284. * @class
  285. * A stack based class which helps manage re-entrancy for the undo stack.
  286. */
  287. class CUndoStackGuard : public IReEntrantComponent
  288. {
  289. //@access Public Methods
  290. public:
  291. virtual void OnEnterContext(); //@cmember reentered notify
  292. CUndoStackGuard(CTxtEdit *ped); //@cmember Constructor
  293. ~CUndoStackGuard(); //@cmember Destructor
  294. //@cmember Execute the undo
  295. // actions in <p pae>
  296. HRESULT SafeUndo(IAntiEvent *pae, IUndoBuilder *publdr);
  297. BOOL WasReEntered() { return _fReEntered; } //@cmember return the
  298. // re-entered flag
  299. //@access Private Data
  300. private:
  301. CTxtEdit * _ped; //@cmember Edit context
  302. volatile IAntiEvent * _paeNext; //@cmember Loop index for
  303. // the ae's
  304. volatile HRESULT _hr; //@cmember Cached hr
  305. IUndoBuilder * _publdr; //@cmember Undo/redo
  306. // context
  307. BOOL _fReEntered; //@cmember Have we been
  308. // been re-entered?
  309. };
  310. // Helper Functions.
  311. // Loop through a chain of anti-events and destroy them
  312. void DestroyAEList(IAntiEvent *pae);
  313. // Loop through a chain of anti-events and call OnCommit
  314. void CommitAEList(IAntiEvent *pae, CTxtEdit *ped);
  315. // Handles merging and/or creation of selection anti-event info
  316. HRESULT HandleSelectionAEInfo(CTxtEdit *ped, IUndoBuilder *publdr,
  317. LONG cp, LONG cch, LONG cpNext, LONG cchNext, SELAE flags);
  318. #endif // !__M_UNDO_H__