// // "$Id$" // // FLUID undo support for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2005 by Bill Spitzak and others. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // // Please report all bugs and problems on the following page: // // http://www.fltk.org/str.php // #include #include "Fl_Type.h" #include "undo.h" #include #include "../src/flstring.h" #if defined(WIN32) && !defined(__CYGWIN__) # include # include # define getpid (int)GetCurrentProcessId // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs // on Windows, which is supposed to be POSIX compliant... # define unlink _unlink #else # include #endif // WIN32 && !__CYGWIN__ extern Fl_Preferences fluid_prefs; // FLUID preferences extern Fl_Menu_Item Main_Menu[]; // Main menu #define UNDO_ITEM 25 // Undo menu item index #define REDO_ITEM 26 // Redo menu item index // // This file implements an undo system using temporary files; ideally // we'd like to do this in memory, however the current data structures // and design aren't well-suited... Instead, we save and restore // checkpoint files. // int undo_current = 0; // Current undo level in buffer int undo_last = 0; // Last undo level in buffer int undo_max = 0; // Maximum undo level used int undo_save = -1; // Last undo level that was saved static int undo_paused = 0; // Undo checkpointing paused? // Return the undo filename static char *undo_filename(int level, char *buf, int bufsize) { static char undo_path[1024] = ""; // Undo path if (!undo_path[0]) fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path)); snprintf(buf, bufsize, "%sundo_%d_%d.fl", undo_path, getpid(), level); return buf; } // Redo menu callback void redo_cb(Fl_Widget *, void *) { char filename[1024]; // Undo checkpoint file if (undo_current >= undo_last) return; undo_suspend(); if (!read_file(undo_filename(undo_current + 1, filename, sizeof(filename)), 0)) { // Unable to read checkpoint file, don't redo... undo_resume(); return; } undo_current ++; // Update modified flag... set_modflag(undo_current != undo_save); // Update undo/redo menu items... if (undo_current >= undo_last) Main_Menu[REDO_ITEM].deactivate(); Main_Menu[UNDO_ITEM].activate(); } // Undo menu callback void undo_cb(Fl_Widget *, void *) { char filename[1024]; // Undo checkpoint file if (undo_current <= 0) return; if (undo_current == undo_last) { write_file(undo_filename(undo_current, filename, sizeof(filename))); } undo_suspend(); if (!read_file(undo_filename(undo_current - 1, filename, sizeof(filename)), 0)) { // Unable to read checkpoint file, don't undo... undo_resume(); return; } undo_current --; // Update modified flag... set_modflag(undo_current != undo_save); // Update undo/redo menu items... if (undo_current <= 0) Main_Menu[UNDO_ITEM].deactivate(); Main_Menu[REDO_ITEM].activate(); undo_resume(); } // Save current file to undo buffer void undo_checkpoint() { char filename[1024]; // Undo checkpoint filename // printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n", // undo_current, undo_paused, modflag); // Don't checkpoint if undo_suspend() has been called... if (undo_paused) return; // Save the current UI to a checkpoint file... if (!write_file(undo_filename(undo_current, filename, sizeof(filename)))) { // Don't attempt to do undo stuff if we can't write a checkpoint file... perror(filename); return; } // Update the saved level... if (modflag && undo_current <= undo_save) undo_save = -1; else if (!modflag) undo_save = undo_current; // Update the current undo level... undo_current ++; undo_last = undo_current; if (undo_current > undo_max) undo_max = undo_current; // Enable the Undo and disable the Redo menu items... Main_Menu[UNDO_ITEM].activate(); Main_Menu[REDO_ITEM].deactivate(); } // Clear undo buffer void undo_clear() { char filename[1024]; // Undo checkpoint filename // Remove old checkpoint files... for (int i = 0; i <= undo_max; i ++) { unlink(undo_filename(i, filename, sizeof(filename))); } // Reset current, last, and save indices... undo_current = undo_last = undo_max = 0; if (modflag) undo_save = -1; else undo_save = 0; } // Resume undo checkpoints void undo_resume() { undo_paused = 0; } // Suspend undo checkpoints void undo_suspend() { undo_paused = 1; } // // End of "$Id$". //