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.

194 lines
5.2KB

  1. //
  2. // "$Id$"
  3. //
  4. // FLUID undo support for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-2010 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems on the following page:
  24. //
  25. // http://www.fltk.org/str.php
  26. //
  27. #include <FL/Fl.H>
  28. #include "Fl_Type.h"
  29. #include "undo.h"
  30. #include <FL/Fl_Preferences.H>
  31. #include <FL/filename.H>
  32. #include "../src/flstring.h"
  33. #if defined(WIN32) && !defined(__CYGWIN__)
  34. # include <io.h>
  35. # include <windows.h>
  36. # define getpid (int)GetCurrentProcessId
  37. # ifndef __WATCOMC__
  38. // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
  39. // on Windows, which is supposed to be POSIX compliant...
  40. # define unlink _unlink
  41. # endif // !__WATCOMC__
  42. #else
  43. # include <unistd.h>
  44. #endif // WIN32 && !__CYGWIN__
  45. extern Fl_Preferences fluid_prefs; // FLUID preferences
  46. extern Fl_Menu_Item Main_Menu[]; // Main menu
  47. #define UNDO_ITEM 25 // Undo menu item index
  48. #define REDO_ITEM 26 // Redo menu item index
  49. //
  50. // This file implements an undo system using temporary files; ideally
  51. // we'd like to do this in memory, however the current data structures
  52. // and design aren't well-suited... Instead, we save and restore
  53. // checkpoint files.
  54. //
  55. int undo_current = 0; // Current undo level in buffer
  56. int undo_last = 0; // Last undo level in buffer
  57. int undo_max = 0; // Maximum undo level used
  58. int undo_save = -1; // Last undo level that was saved
  59. static int undo_paused = 0; // Undo checkpointing paused?
  60. // Return the undo filename
  61. static char *undo_filename(int level, char *buf, int bufsize) {
  62. static char undo_path[FL_PATH_MAX] = ""; // Undo path
  63. if (!undo_path[0]) fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path));
  64. snprintf(buf, bufsize, "%sundo_%d_%d.fl", undo_path, getpid(), level);
  65. return buf;
  66. }
  67. // Redo menu callback
  68. void redo_cb(Fl_Widget *, void *) {
  69. char filename[FL_PATH_MAX]; // Undo checkpoint file
  70. if (undo_current >= undo_last) return;
  71. undo_suspend();
  72. if (!read_file(undo_filename(undo_current + 1, filename, sizeof(filename)), 0)) {
  73. // Unable to read checkpoint file, don't redo...
  74. undo_resume();
  75. return;
  76. }
  77. undo_current ++;
  78. // Update modified flag...
  79. set_modflag(undo_current != undo_save);
  80. // Update undo/redo menu items...
  81. if (undo_current >= undo_last) Main_Menu[REDO_ITEM].deactivate();
  82. Main_Menu[UNDO_ITEM].activate();
  83. }
  84. // Undo menu callback
  85. void undo_cb(Fl_Widget *, void *) {
  86. char filename[FL_PATH_MAX]; // Undo checkpoint file
  87. if (undo_current <= 0) return;
  88. if (undo_current == undo_last) {
  89. write_file(undo_filename(undo_current, filename, sizeof(filename)));
  90. }
  91. undo_suspend();
  92. if (!read_file(undo_filename(undo_current - 1, filename, sizeof(filename)), 0)) {
  93. // Unable to read checkpoint file, don't undo...
  94. undo_resume();
  95. return;
  96. }
  97. undo_current --;
  98. // Update modified flag...
  99. set_modflag(undo_current != undo_save);
  100. // Update undo/redo menu items...
  101. if (undo_current <= 0) Main_Menu[UNDO_ITEM].deactivate();
  102. Main_Menu[REDO_ITEM].activate();
  103. undo_resume();
  104. }
  105. // Save current file to undo buffer
  106. void undo_checkpoint() {
  107. char filename[FL_PATH_MAX]; // Undo checkpoint filename
  108. // printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n",
  109. // undo_current, undo_paused, modflag);
  110. // Don't checkpoint if undo_suspend() has been called...
  111. if (undo_paused) return;
  112. // Save the current UI to a checkpoint file...
  113. if (!write_file(undo_filename(undo_current, filename, sizeof(filename)))) {
  114. // Don't attempt to do undo stuff if we can't write a checkpoint file...
  115. perror(filename);
  116. return;
  117. }
  118. // Update the saved level...
  119. if (modflag && undo_current <= undo_save) undo_save = -1;
  120. else if (!modflag) undo_save = undo_current;
  121. // Update the current undo level...
  122. undo_current ++;
  123. undo_last = undo_current;
  124. if (undo_current > undo_max) undo_max = undo_current;
  125. // Enable the Undo and disable the Redo menu items...
  126. Main_Menu[UNDO_ITEM].activate();
  127. Main_Menu[REDO_ITEM].deactivate();
  128. }
  129. // Clear undo buffer
  130. void undo_clear() {
  131. char filename[FL_PATH_MAX]; // Undo checkpoint filename
  132. // Remove old checkpoint files...
  133. for (int i = 0; i <= undo_max; i ++) {
  134. unlink(undo_filename(i, filename, sizeof(filename)));
  135. }
  136. // Reset current, last, and save indices...
  137. undo_current = undo_last = undo_max = 0;
  138. if (modflag) undo_save = -1;
  139. else undo_save = 0;
  140. }
  141. // Resume undo checkpoints
  142. void undo_resume() {
  143. undo_paused = 0;
  144. }
  145. // Suspend undo checkpoints
  146. void undo_suspend() {
  147. undo_paused = 1;
  148. }
  149. //
  150. // End of "$Id$".
  151. //