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.

350 lines
10 KiB

  1. /*
  2. * _M_UNDO.H
  3. *
  4. * Purpose:
  5. * Declares multilevel undo interfaces and classes
  6. *
  7. * Author:
  8. * alexgo 3/25/95
  9. *
  10. * Copyright (c) 1995-2000, 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 antievent 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() = 0;
  95. protected:
  96. ~IAntiEvent() {;}
  97. };
  98. /*
  99. * IUndoMgr
  100. *
  101. * Purpose:
  102. * Interface for managing "stacks" of antievents
  103. */
  104. class IUndoMgr
  105. {
  106. public:
  107. virtual void Destroy () = 0;
  108. virtual LONG SetUndoLimit (LONG cUndoLim) = 0;
  109. virtual LONG 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 () = 0;
  114. virtual void * GetTopAECookie () = 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 antievents. These antievents 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(); //@cmember Destroy
  145. virtual LONG SetUndoLimit(LONG cUndoLim);//@cmember Set item limit
  146. virtual LONG GetUndoLimit();
  147. //@cmember Add an AE to stack
  148. virtual HRESULT PushAntiEvent(UNDONAMEID idName, IAntiEvent *pae);
  149. //@cmember Execute most recent
  150. virtual HRESULT PopAndExecuteAntiEvent(void *pAE);// antievent or upto pAE
  151. virtual UNDONAMEID GetNameIDFromAE(void *pAE);//@cmember Get name of given AE
  152. virtual IAntiEvent *GetMergeAntiEvent(); //@cmember Get most recent AE
  153. // of merge state
  154. virtual void * GetTopAECookie(); //@cmember Get cookie for top AE
  155. virtual void ClearAll(); //@cmember Delete all AEs
  156. virtual BOOL CanUndo(); //@cmember Something to undo?
  157. virtual void StartGroupTyping(); //@cmember Starts group typing
  158. virtual void StopGroupTyping(); //@cmember Stops group typing
  159. // Public methods; not part of IUndoMgr
  160. HRESULT EnableSingleLevelMode(); //@cmember RE1.0 undo mode
  161. void DisableSingleLevelMode(); //@cmember Back to RE2.0 mode
  162. //@cmember Are we in 1.0 mode?
  163. BOOL GetSingleLevelMode() {return _fSingleLevelMode;}
  164. CUndoStack(CTxtEdit *ped, LONG &cUndoLim, USFlags flags);
  165. private:
  166. ~CUndoStack();
  167. struct UndoAction
  168. {
  169. IAntiEvent * pae;
  170. UNDONAMEID id;
  171. };
  172. void Next(); //@cmember Moves by 1
  173. void Prev(); //@cmember Moves by -1
  174. LONG GetPrev(); //@cmember Get previous index
  175. //@cmember TRUE iff cookie ae is in ae list
  176. BOOL IsCookieInList(IAntiEvent *pae, IAntiEvent *paeCookie);
  177. //@cmember Transfer this object to new stack
  178. void TransferToNewBuffer(UndoAction *prgnew, LONG dwLimNew);
  179. UndoAction *_prgActions; //@cmember List of AEs
  180. LONG _cUndoLim; //@cmember Undo limit
  181. LONG _index; //@cmember Current index
  182. CTxtEdit * _ped; //@cmember Big Papa
  183. DWORD _fGroupTyping :1; //@cmember Group Typing flag
  184. DWORD _fMerge :1; //@cmember Merge flag
  185. DWORD _fRedo :1; //@cmember Stack is the redo stack
  186. DWORD _fSingleLevelMode :1; //@cmember TRUE if single level undo
  187. // mode is on. Valid only for undo,
  188. }; // i.e., not for redo stack
  189. /*
  190. * IUndoBuilder
  191. *
  192. * Purpose:
  193. * Provides a closure for collecting a sequence of antievents (such
  194. * as all of the antievents involved in doing an intraedit drag-move
  195. * operation.
  196. */
  197. class IUndoBuilder
  198. {
  199. public:
  200. // Names antievent collection
  201. virtual void SetNameID( UNDONAMEID idName ) = 0;
  202. // Adds new antievent to collection
  203. virtual HRESULT AddAntiEvent( IAntiEvent *pae ) = 0;
  204. // Gets topmost antievent in this undo context. This method
  205. // is useful for grouped typing (merging antievents)
  206. virtual IAntiEvent *GetTopAntiEvent() = 0;
  207. // Commits antievent collection
  208. virtual HRESULT Done() = 0;
  209. // Get rid of any antievents that have been collected
  210. virtual void Discard() = 0;
  211. // Notify that a group-typing session should start (forwarded
  212. // to the undo manager)
  213. virtual void StartGroupTyping() = 0;
  214. // Notify that a group-typing session should stop (forwarded
  215. // to the undo manager)
  216. virtual void StopGroupTyping() = 0;
  217. };
  218. /*
  219. * UBFlags
  220. *
  221. * @enum
  222. * Flags affecting the behaviour of Undo builders
  223. */
  224. enum UBFlags
  225. {
  226. UB_AUTOCOMMIT = 1, //@emem Call IUndoBuilder::Done before delete
  227. UB_REDO = 2, //@emem Undo builder is for REDO functionality
  228. UB_DONTFLUSHREDO = 4 //@emem Don't flush redo stack when adding
  229. // antievents to undo stack
  230. };
  231. /*
  232. * CGenUndoBuilder
  233. *
  234. * @class
  235. * A general purpose undo builder. It can be easily allocated and freed
  236. * on the stack and simply puts new antievents at the beginning of an
  237. * antievent linked list. NO attempt is made to optimize or reorder
  238. * antievents.
  239. */
  240. class CGenUndoBuilder : public IUndoBuilder, public IReEntrantComponent
  241. {
  242. //@access Public methods
  243. public:
  244. virtual void SetNameID( UNDONAMEID idName ); //@cmember Set the name
  245. virtual HRESULT AddAntiEvent(IAntiEvent *pae); //@cmember Add an AE
  246. virtual IAntiEvent *GetTopAntiEvent( ); //@cmember Get top AE
  247. virtual HRESULT Done(); //@cmember Commit AEs
  248. virtual void Discard(); //@cmember Discard AEs
  249. virtual void StartGroupTyping(); //@cmember Start GT
  250. virtual void StopGroupTyping(); //@cmember Stop GT
  251. CGenUndoBuilder(CTxtEdit *ped, DWORD flags, //@cmember Constructor
  252. IUndoBuilder **ppubldr = NULL);
  253. ~CGenUndoBuilder( ); //@cmember Destructor
  254. // IReEntrantComponent methods
  255. virtual void OnEnterContext() {;} //@cmember Reentered notify
  256. //@access Private methods
  257. private:
  258. IUndoBuilder * _publdrPrev; //@cmember Ptr to undobldr
  259. // higher in stack
  260. IUndoMgr * _pundo; //@cmember Ptr to undo mgr
  261. CTxtEdit * _ped; //@cmember Ptr to edit contxt
  262. UNDONAMEID _idName; //@cmember Current name
  263. IAntiEvent * _pfirstae; //@cmember AE list
  264. UINT _fAutoCommit:1; //@cmember AutoCommit on?
  265. UINT _fStartGroupTyping:1; //@cmember GroupTyping on?
  266. UINT _fRedo:1; //@cmember UB destination is
  267. // the redo stack
  268. UINT _fDontFlushRedo:1; //@cmember Don't flush redo
  269. // stack; i.e. we are
  270. // invoking a redo action
  271. UINT _fInactive:1; //@cmember TRUE if undo enabled
  272. };
  273. /*
  274. * CUndoStackGuard
  275. *
  276. * @class
  277. * A stack based class which helps manage reentrancy for the undo stack
  278. */
  279. class CUndoStackGuard : public IReEntrantComponent
  280. {
  281. //@access Public Methods
  282. public:
  283. virtual void OnEnterContext(); //@cmember reentered notify
  284. CUndoStackGuard(CTxtEdit *ped); //@cmember Constructor
  285. ~CUndoStackGuard(); //@cmember Destructor
  286. //@cmember Execute the undo
  287. HRESULT SafeUndo(IAntiEvent *pae, IUndoBuilder *publdr);// actions in <p pae>
  288. BOOL WasReEntered() {return _fReEntered;} //@cmember Return reentered flag
  289. //@access Private Data
  290. private:
  291. CTxtEdit * _ped; //@cmember Edit context
  292. volatile IAntiEvent * _paeNext; //@cmember Antievent loop ptr
  293. volatile HRESULT _hr; //@cmember Cached hr
  294. IUndoBuilder * _publdr; //@cmember Undo/redo context
  295. BOOL _fReEntered; //@cmember Have we been
  296. }; // been reentered?
  297. // Helper Functions.
  298. // Loop through a chain of antievents and destroy them
  299. void DestroyAEList(IAntiEvent *pae);
  300. // Loop through a chain of antievents and call OnCommit
  301. void CommitAEList(CTxtEdit *ped, IAntiEvent *pae);
  302. // Handles merging and/or creation of selection antievent info
  303. HRESULT HandleSelectionAEInfo(CTxtEdit *ped, IUndoBuilder *publdr,
  304. LONG cp, LONG cch, LONG cpNext, LONG cchNext, SELAE flags);
  305. #endif // !__M_UNDO_H__