?? undo.c
字號:
static const char CVSID[] = "$Id: undo.c,v 1.14 2002/08/27 05:39:27 n8gray Exp $";/******************************************************************************** ** undo.c -- Nirvana Editor undo command ** ** Copyright (C) 1999 Mark Edel ** ** This is free software; you can redistribute it and/or modify it under the ** terms of the GNU General Public License as published by the Free Software ** Foundation; either version 2 of the License, or (at your option) any later ** version. ** ** This software 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 General Public License ** for more details. ** ** You should have received a copy of the GNU General Public License along with ** software; if not, write to the Free Software Foundation, Inc., 59 Temple ** Place, Suite 330, Boston, MA 02111-1307 USA ** ** Nirvana Text Editor ** May 10, 1991 ** ** Written by Mark Edel ** ********************************************************************************/#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include "undo.h"#include "textBuf.h"#include "text.h"#include "nedit.h"#include "search.h"#include "window.h"#include "file.h"#include "userCmds.h"#include "preferences.h"#include <string.h>#ifdef VMS#include "../util/VMSparam.h"#else#ifndef __MVS__#include <sys/param.h>#endif#endif /*VMS*/#include <Xm/Xm.h>#include <Xm/Text.h>#ifdef HAVE_DEBUG_H#include "../debug.h"#endif#define FORWARD 1#define REVERSE 2static void addUndoItem(WindowInfo *window, UndoInfo *undo);static void addRedoItem(WindowInfo *window, UndoInfo *redo);static void removeUndoItem(WindowInfo *window);static void removeRedoItem(WindowInfo *window);static void appendDeletedText(WindowInfo *window, const char *deletedText, int deletedLen, int direction);static void trimUndoList(WindowInfo *window, int maxLength);static int determineUndoType(int nInserted, int nDeleted);static void freeUndoRecord(UndoInfo *undo);void Undo(WindowInfo *window){ UndoInfo *undo = window->undo; int restoredTextLength; /* return if nothing to undo */ if (undo == NULL) return; /* BufReplace will eventually call SaveUndoInformation. This is mostly good because it makes accumulating redo operations easier, however SaveUndoInformation needs to know that it is being called in the context of an undo. The inUndo field in the undo record indicates that this record is in the process of being undone. */ undo->inUndo = True; /* use the saved undo information to reverse changes */ BufReplace(window->buffer, undo->startPos, undo->endPos, (undo->oldText != NULL ? undo->oldText : "")); restoredTextLength = undo->oldText != NULL ? strlen(undo->oldText) : 0; /* position the cursor in the focus pane after the changed text to show the user where the undo was done */ TextSetCursorPos(window->lastFocus, undo->startPos + restoredTextLength); if (GetPrefUndoModifiesSelection()) { if (restoredTextLength > 0) { BufSelect(window->buffer, undo->startPos, undo->startPos + restoredTextLength); } else { BufUnselect(window->buffer); } } MakeSelectionVisible(window, window->lastFocus); /* restore the file's unmodified status if the file was unmodified when the change being undone was originally made. Also, remove the backup file, since the text in the buffer is now identical to the original file */ if (undo->restoresToSaved) { SetWindowModified(window, False); RemoveBackupFile(window); } /* free the undo record and remove it from the chain */ removeUndoItem(window);}void Redo(WindowInfo *window){ UndoInfo *redo = window->redo; int restoredTextLength; /* return if nothing to redo */ if (window->redo == NULL) return; /* BufReplace will eventually call SaveUndoInformation. To indicate to SaveUndoInformation that this is the context of a redo operation, we set the inUndo indicator in the redo record */ redo->inUndo = True; /* use the saved redo information to reverse changes */ BufReplace(window->buffer, redo->startPos, redo->endPos, (redo->oldText != NULL ? redo->oldText : "")); restoredTextLength = redo->oldText != NULL ? strlen(redo->oldText) : 0; /* position the cursor in the focus pane after the changed text to show the user where the redo was done */ TextSetCursorPos(window->lastFocus, redo->startPos + restoredTextLength); if (GetPrefUndoModifiesSelection()) { if (restoredTextLength > 0) { BufSelect(window->buffer, redo->startPos, redo->startPos + restoredTextLength); } else { BufUnselect(window->buffer); } } MakeSelectionVisible(window, window->lastFocus); /* restore the file's unmodified status if the file was unmodified when the change being redone was originally made */ if (redo->restoresToSaved) SetWindowModified(window, False); /* remove the redo record from the chain and free it */ removeRedoItem(window);}/*** SaveUndoInformation stores away the changes made to the text buffer. As a** side effect, it also increments the autoSave operation and character counts** since it needs to do the classification anyhow.*//* Note: This routine must be kept efficient. It is called for every character typed. */void SaveUndoInformation(WindowInfo *window, int pos, int nInserted, int nDeleted, const char *deletedText){ int newType, oldType; UndoInfo *u, *undo = window->undo; int isUndo = (undo != NULL && undo->inUndo); int isRedo = (window->redo != NULL && window->redo->inUndo); /* redo operations become invalid once the user begins typing or does other editing. If this is not a redo or undo operation and a redo list still exists, clear it and dim the redo menu item */ if (!(isUndo || isRedo) && window->redo != NULL) ClearRedoList(window); /* figure out what kind of editing operation this is, and recall what the last one was */ newType = determineUndoType(nInserted, nDeleted); if (newType == UNDO_NOOP) return; oldType = (undo == NULL || isUndo) ? UNDO_NOOP : undo->type; /* ** Check for continuations of single character operations. These are ** accumulated so a whole insertion or deletion can be undone, rather ** than just the last character that the user typed. If the window ** is currently in an unmodified state, don't accumulate operations ** across the save, so the user can undo back to the unmodified state. */ if (window->fileChanged) { /* normal sequential character insertion */ if ( ((oldType == ONE_CHAR_INSERT || oldType == ONE_CHAR_REPLACE) && newType == ONE_CHAR_INSERT) && (pos == undo->endPos)) { undo->endPos++; window->autoSaveCharCount++; return; } /* overstrike mode replacement */ if ((oldType == ONE_CHAR_REPLACE && newType == ONE_CHAR_REPLACE) && (pos == undo->endPos)) { appendDeletedText(window, deletedText, nDeleted, FORWARD); undo->endPos++; window->autoSaveCharCount++; return; } /* forward delete */ if ((oldType==ONE_CHAR_DELETE && newType==ONE_CHAR_DELETE) && (pos==undo->startPos)) { appendDeletedText(window, deletedText, nDeleted, FORWARD); return; } /* reverse delete */ if ((oldType==ONE_CHAR_DELETE && newType==ONE_CHAR_DELETE) && (pos == undo->startPos-1)) { appendDeletedText(window, deletedText, nDeleted, REVERSE); undo->startPos--; undo->endPos--; return; } } /* ** The user has started a new operation, create a new undo record ** and save the new undo data. */ undo = (UndoInfo *)XtMalloc(sizeof(UndoInfo)); undo->oldLen = 0; undo->oldText = NULL; undo->type = newType; undo->inUndo = False; undo->restoresToSaved = False; undo->startPos = pos; undo->endPos = pos + nInserted; /* if text was deleted, save it */ if (nDeleted > 0) { undo->oldLen = nDeleted + 1; /* +1 is for null at end */ undo->oldText = XtMalloc(nDeleted + 1);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -