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.

196 lines
3.9 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include <shellp.h>
  4. // use a linked list because we're going to be pulling things off the top
  5. // and bottom all the time.
  6. HDPA s_hdpaUndo = NULL;
  7. BOOL s_fUndoSuspended = FALSE;
  8. #define MAX_UNDO 10
  9. void NukeUndoAtom(LPUNDOATOM lpua)
  10. {
  11. lpua->Release( lpua );
  12. LocalFree( lpua );
  13. }
  14. void SuspendUndo(BOOL f)
  15. {
  16. if (f)
  17. s_fUndoSuspended++;
  18. else
  19. s_fUndoSuspended--;
  20. ASSERT(s_fUndoSuspended >= 0);
  21. // sanity check
  22. if (s_fUndoSuspended < 0)
  23. s_fUndoSuspended = 0;
  24. }
  25. void AddUndoAtom(LPUNDOATOM lpua)
  26. {
  27. int i;
  28. ENTERCRITICAL;
  29. ASSERT(lpua);
  30. if (!s_hdpaUndo) {
  31. s_hdpaUndo = DPA_Create(MAX_UNDO + 1);
  32. }
  33. if (s_hdpaUndo) {
  34. i = DPA_AppendPtr(s_hdpaUndo, lpua);
  35. if (i != -1) {
  36. if (i >= MAX_UNDO) {
  37. lpua = DPA_FastGetPtr(s_hdpaUndo, 0);
  38. NukeUndoAtom(lpua);
  39. DPA_DeletePtr(s_hdpaUndo, 0);
  40. }
  41. } else {
  42. NukeUndoAtom(lpua);
  43. }
  44. }
  45. LEAVECRITICAL;
  46. }
  47. LPUNDOATOM _PeekUndoAtom(LPINT lpi)
  48. {
  49. int i = -1;
  50. LPUNDOATOM lpua = NULL;
  51. ASSERTCRITICAL;
  52. if (s_hdpaUndo) {
  53. i = DPA_GetPtrCount(s_hdpaUndo) - 1;
  54. if (i >= 0) {
  55. lpua = DPA_FastGetPtr(s_hdpaUndo, i);
  56. }
  57. }
  58. if (lpi)
  59. *lpi = i;
  60. return lpua;
  61. }
  62. void EnumUndoAtoms(int (CALLBACK* lpfn)(LPUNDOATOM lpua, LPARAM lParam), LPARAM lParam)
  63. {
  64. int i;
  65. if (!s_hdpaUndo) {
  66. return;
  67. }
  68. ENTERCRITICAL;
  69. for (i = DPA_GetPtrCount(s_hdpaUndo) - 1; i >= 0; i--) {
  70. LPUNDOATOM lpua;
  71. int iRet;
  72. lpua = DPA_FastGetPtr(s_hdpaUndo, i);
  73. iRet = lpfn(lpua, lParam);
  74. if (iRet & EUA_DELETE) {
  75. DPA_DeletePtr(s_hdpaUndo, i);
  76. NukeUndoAtom(lpua);
  77. }
  78. if (iRet & EUA_ABORT) {
  79. break;
  80. }
  81. }
  82. LEAVECRITICAL;
  83. }
  84. #define DoUndoAtom(lpua) ((lpua)->Invoke((lpua)))
  85. void Undo(HWND hwnd)
  86. {
  87. int i;
  88. LPUNDOATOM lpua;
  89. DECLAREWAITCURSOR;
  90. if (!IsUndoAvailable()) {
  91. MessageBeep(0);
  92. return;
  93. }
  94. SetWaitCursor();
  95. ENTERCRITICAL;
  96. ASSERT(s_hdpaUndo);
  97. lpua = _PeekUndoAtom(&i);
  98. if (lpua)
  99. DPA_DeletePtr(s_hdpaUndo, i);
  100. LEAVECRITICAL;
  101. if (lpua) {
  102. lpua->hwnd = hwnd;
  103. DoUndoAtom(lpua);
  104. }
  105. ResetWaitCursor();
  106. }
  107. BOOL IsUndoAvailable()
  108. {
  109. return s_hdpaUndo && !s_fUndoSuspended &&
  110. DPA_GetPtrCount(s_hdpaUndo);
  111. }
  112. #define _GetUndoText(lpua, buffer, type) (lpua)->GetText((lpua), buffer, type)
  113. // Gets undo information for the first item in the undo buffer
  114. //
  115. void GetUndoText(LPTSTR lpszBuffer, UINT cchBuffer, int type)
  116. {
  117. TCHAR szTemp[MAX_PATH * 2 + 80];
  118. TCHAR lpszFormat[MAX_PATH]; // (MAX_PATH is overkill, oh well...)
  119. ASSERT(cchBuffer > 0);
  120. lpszBuffer[0] = 0; // assume failure
  121. szTemp[0] = 0;
  122. // While holding onto lpua's from the hdpa, we need to be inside the critical section
  123. {
  124. LPUNDOATOM lpua;
  125. ENTERCRITICAL;
  126. lpua = _PeekUndoAtom(NULL);
  127. if (lpua)
  128. _GetUndoText(lpua, szTemp, type);
  129. LEAVECRITICAL;
  130. }
  131. if (LoadString(HINST_THISDLL, (type == UNDO_MENUTEXT) ? IDS_UNDOACCEL : IDS_UNDO, lpszFormat, ARRAYSIZE(lpszFormat)) != 0)
  132. {
  133. if (type == UNDO_STATUSTEXT)
  134. {
  135. // Status text shouldn't have ampersand or tab
  136. ASSERT(StrChr(lpszFormat, TEXT('&')) == NULL);
  137. ASSERT(StrChr(lpszFormat, TEXT('\t')) == NULL);
  138. }
  139. wnsprintf(lpszBuffer, cchBuffer, lpszFormat, szTemp);
  140. }
  141. }
  142. void FreeUndoList()
  143. {
  144. HDPA hdpa;
  145. int i;
  146. ENTERCRITICAL;
  147. hdpa = s_hdpaUndo;
  148. s_hdpaUndo = NULL;
  149. LEAVECRITICAL;
  150. if (hdpa)
  151. {
  152. for (i = DPA_GetPtrCount(hdpa) - 1; i >= 0; i--)
  153. {
  154. NukeUndoAtom(DPA_FastGetPtr(hdpa, i));
  155. }
  156. DPA_DeleteAllPtrs(hdpa);
  157. }
  158. }