undo.cxx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. Distribution and use rights are outlined in
  9. // the file "COPYING" which should have been included with this file. If this
  10. // file is missing or damaged, see the license at:
  11. //
  12. // http://www.fltk.org/COPYING.php
  13. //
  14. // Please report all bugs and problems on the following page:
  15. //
  16. // http://www.fltk.org/str.php
  17. //
  18. #include <FL/Fl.H>
  19. #include "Fl_Type.h"
  20. #include "undo.h"
  21. #include <FL/Fl_Preferences.H>
  22. #include <FL/filename.H>
  23. #include "../src/flstring.h"
  24. #if defined(WIN32) && !defined(__CYGWIN__)
  25. # include <io.h>
  26. # include <windows.h>
  27. # define getpid (int)GetCurrentProcessId
  28. # ifndef __WATCOMC__
  29. // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
  30. // on Windows, which is supposed to be POSIX compliant...
  31. # define unlink _unlink
  32. # endif // !__WATCOMC__
  33. #else
  34. # include <unistd.h>
  35. #endif // WIN32 && !__CYGWIN__
  36. extern Fl_Preferences fluid_prefs; // FLUID preferences
  37. extern Fl_Menu_Item Main_Menu[]; // Main menu
  38. #define UNDO_ITEM 25 // Undo menu item index
  39. #define REDO_ITEM 26 // Redo menu item index
  40. //
  41. // This file implements an undo system using temporary files; ideally
  42. // we'd like to do this in memory, however the current data structures
  43. // and design aren't well-suited... Instead, we save and restore
  44. // checkpoint files.
  45. //
  46. int undo_current = 0; // Current undo level in buffer
  47. int undo_last = 0; // Last undo level in buffer
  48. int undo_max = 0; // Maximum undo level used
  49. int undo_save = -1; // Last undo level that was saved
  50. static int undo_paused = 0; // Undo checkpointing paused?
  51. // Return the undo filename
  52. static char *undo_filename(int level, char *buf, int bufsize) {
  53. static char undo_path[FL_PATH_MAX] = ""; // Undo path
  54. if (!undo_path[0]) fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path));
  55. snprintf(buf, bufsize, "%sundo_%d_%d.fl", undo_path, getpid(), level);
  56. return buf;
  57. }
  58. // Redo menu callback
  59. void redo_cb(Fl_Widget *, void *) {
  60. char filename[FL_PATH_MAX]; // Undo checkpoint file
  61. if (undo_current >= undo_last) return;
  62. undo_suspend();
  63. if (!read_file(undo_filename(undo_current + 1, filename, sizeof(filename)), 0)) {
  64. // Unable to read checkpoint file, don't redo...
  65. undo_resume();
  66. return;
  67. }
  68. undo_current ++;
  69. // Update modified flag...
  70. set_modflag(undo_current != undo_save);
  71. // Update undo/redo menu items...
  72. if (undo_current >= undo_last) Main_Menu[REDO_ITEM].deactivate();
  73. Main_Menu[UNDO_ITEM].activate();
  74. }
  75. // Undo menu callback
  76. void undo_cb(Fl_Widget *, void *) {
  77. char filename[FL_PATH_MAX]; // Undo checkpoint file
  78. if (undo_current <= 0) return;
  79. if (undo_current == undo_last) {
  80. write_file(undo_filename(undo_current, filename, sizeof(filename)));
  81. }
  82. undo_suspend();
  83. if (!read_file(undo_filename(undo_current - 1, filename, sizeof(filename)), 0)) {
  84. // Unable to read checkpoint file, don't undo...
  85. undo_resume();
  86. return;
  87. }
  88. undo_current --;
  89. // Update modified flag...
  90. set_modflag(undo_current != undo_save);
  91. // Update undo/redo menu items...
  92. if (undo_current <= 0) Main_Menu[UNDO_ITEM].deactivate();
  93. Main_Menu[REDO_ITEM].activate();
  94. undo_resume();
  95. }
  96. // Save current file to undo buffer
  97. void undo_checkpoint() {
  98. char filename[FL_PATH_MAX]; // Undo checkpoint filename
  99. // printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n",
  100. // undo_current, undo_paused, modflag);
  101. // Don't checkpoint if undo_suspend() has been called...
  102. if (undo_paused) return;
  103. // Save the current UI to a checkpoint file...
  104. if (!write_file(undo_filename(undo_current, filename, sizeof(filename)))) {
  105. // Don't attempt to do undo stuff if we can't write a checkpoint file...
  106. perror(filename);
  107. return;
  108. }
  109. // Update the saved level...
  110. if (modflag && undo_current <= undo_save) undo_save = -1;
  111. else if (!modflag) undo_save = undo_current;
  112. // Update the current undo level...
  113. undo_current ++;
  114. undo_last = undo_current;
  115. if (undo_current > undo_max) undo_max = undo_current;
  116. // Enable the Undo and disable the Redo menu items...
  117. Main_Menu[UNDO_ITEM].activate();
  118. Main_Menu[REDO_ITEM].deactivate();
  119. }
  120. // Clear undo buffer
  121. void undo_clear() {
  122. char filename[FL_PATH_MAX]; // Undo checkpoint filename
  123. // Remove old checkpoint files...
  124. for (int i = 0; i <= undo_max; i ++) {
  125. unlink(undo_filename(i, filename, sizeof(filename)));
  126. }
  127. // Reset current, last, and save indices...
  128. undo_current = undo_last = undo_max = 0;
  129. if (modflag) undo_save = -1;
  130. else undo_save = 0;
  131. }
  132. // Resume undo checkpoints
  133. void undo_resume() {
  134. undo_paused = 0;
  135. }
  136. // Suspend undo checkpoints
  137. void undo_suspend() {
  138. undo_paused = 1;
  139. }
  140. //
  141. // End of "$Id$".
  142. //