fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

undo.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id$"
00003 //
00004 // FLUID undo support for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 #include <FL/Fl.H>
00029 #include "Fl_Type.h"
00030 #include "undo.h"
00031 #include <FL/Fl_Preferences.H>
00032 #include <FL/filename.H>
00033 #include "../src/flstring.h"
00034 #if defined(WIN32) && !defined(__CYGWIN__)
00035 #  include <io.h>
00036 #  include <windows.h>
00037 #  define getpid (int)GetCurrentProcessId
00038 #  ifndef __WATCOMC__
00039 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
00040 // on Windows, which is supposed to be POSIX compliant...
00041 #    define unlink _unlink
00042 #  endif // !__WATCOMC__
00043 #else
00044 #  include <unistd.h>
00045 #endif // WIN32 && !__CYGWIN__
00046 
00047 
00048 extern Fl_Preferences   fluid_prefs;    // FLUID preferences
00049 extern Fl_Menu_Item     Main_Menu[];    // Main menu
00050 
00051 #define UNDO_ITEM       25              // Undo menu item index
00052 #define REDO_ITEM       26              // Redo menu item index
00053 
00054 
00055 //
00056 // This file implements an undo system using temporary files; ideally
00057 // we'd like to do this in memory, however the current data structures
00058 // and design aren't well-suited...  Instead, we save and restore
00059 // checkpoint files.
00060 //
00061 
00062 
00063 int undo_current = 0;                   // Current undo level in buffer
00064 int undo_last = 0;                      // Last undo level in buffer
00065 int undo_max = 0;                       // Maximum undo level used
00066 int undo_save = -1;                     // Last undo level that was saved
00067 static int undo_paused = 0;             // Undo checkpointing paused?
00068 
00069 
00070 // Return the undo filename
00071 static char *undo_filename(int level, char *buf, int bufsize) {
00072   static char   undo_path[FL_PATH_MAX] = "";    // Undo path
00073 
00074 
00075   if (!undo_path[0]) fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path));
00076 
00077   snprintf(buf, bufsize, "%sundo_%d_%d.fl", undo_path, getpid(), level);
00078   return buf;
00079 }
00080 
00081 
00082 // Redo menu callback
00083 void redo_cb(Fl_Widget *, void *) {
00084   char  filename[FL_PATH_MAX];                  // Undo checkpoint file
00085 
00086   if (undo_current >= undo_last) return;
00087 
00088   undo_suspend();
00089   if (!read_file(undo_filename(undo_current + 1, filename, sizeof(filename)), 0)) {
00090     // Unable to read checkpoint file, don't redo...
00091     undo_resume();
00092     return;
00093   }
00094 
00095   undo_current ++;
00096 
00097   // Update modified flag...
00098   set_modflag(undo_current != undo_save);
00099 
00100   // Update undo/redo menu items...
00101   if (undo_current >= undo_last) Main_Menu[REDO_ITEM].deactivate();
00102   Main_Menu[UNDO_ITEM].activate();
00103 }
00104 
00105 // Undo menu callback
00106 void undo_cb(Fl_Widget *, void *) {
00107   char  filename[FL_PATH_MAX];                  // Undo checkpoint file
00108 
00109   if (undo_current <= 0) return;
00110 
00111   if (undo_current == undo_last) {
00112     write_file(undo_filename(undo_current, filename, sizeof(filename)));
00113   }
00114 
00115   undo_suspend();
00116   if (!read_file(undo_filename(undo_current - 1, filename, sizeof(filename)), 0)) {
00117     // Unable to read checkpoint file, don't undo...
00118     undo_resume();
00119     return;
00120   }
00121 
00122   undo_current --;
00123 
00124   // Update modified flag...
00125   set_modflag(undo_current != undo_save);
00126 
00127   // Update undo/redo menu items...
00128   if (undo_current <= 0) Main_Menu[UNDO_ITEM].deactivate();
00129   Main_Menu[REDO_ITEM].activate();
00130   undo_resume();
00131 }
00132 
00133 // Save current file to undo buffer
00134 void undo_checkpoint() {
00135   char  filename[FL_PATH_MAX];                  // Undo checkpoint filename
00136 
00137 //  printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n",
00138 //         undo_current, undo_paused, modflag);
00139 
00140   // Don't checkpoint if undo_suspend() has been called...
00141   if (undo_paused) return;
00142 
00143   // Save the current UI to a checkpoint file...
00144   if (!write_file(undo_filename(undo_current, filename, sizeof(filename)))) {
00145     // Don't attempt to do undo stuff if we can't write a checkpoint file...
00146     perror(filename);
00147     return;
00148   }
00149 
00150   // Update the saved level...
00151   if (modflag && undo_current <= undo_save) undo_save = -1;
00152   else if (!modflag) undo_save = undo_current;
00153 
00154   // Update the current undo level...
00155   undo_current ++;
00156   undo_last = undo_current;
00157   if (undo_current > undo_max) undo_max = undo_current;
00158 
00159   // Enable the Undo and disable the Redo menu items...
00160   Main_Menu[UNDO_ITEM].activate();
00161   Main_Menu[REDO_ITEM].deactivate();
00162 }
00163 
00164 // Clear undo buffer
00165 void undo_clear() {
00166   char  filename[FL_PATH_MAX];                  // Undo checkpoint filename
00167 
00168 
00169   // Remove old checkpoint files...
00170   for (int i = 0; i <= undo_max; i ++) {
00171     unlink(undo_filename(i, filename, sizeof(filename)));
00172   }
00173 
00174   // Reset current, last, and save indices...
00175   undo_current = undo_last = undo_max = 0;
00176   if (modflag) undo_save = -1;
00177   else undo_save = 0;
00178 }
00179 
00180 // Resume undo checkpoints
00181 void undo_resume() {
00182   undo_paused = 0;
00183 }
00184 
00185 // Suspend undo checkpoints
00186 void undo_suspend() {
00187   undo_paused = 1;
00188 }
00189 
00190 
00191 //
00192 // End of "$Id$".
00193 //