undo.c revision 75406
1147359Simp/* readline.c -- a general facility for reading lines of input 2147595Sru with emacs style editing and completion. */ 3147359Simp 4147359Simp/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 5147359Simp 6147359Simp This file is part of the GNU Readline Library, a library for 7147359Simp reading lines of text with interactive input and history editing. 8147359Simp 9147359Simp The GNU Readline Library is free software; you can redistribute it 10147359Simp and/or modify it under the terms of the GNU General Public License 11147359Simp as published by the Free Software Foundation; either version 2, or 12147359Simp (at your option) any later version. 13147359Simp 14147359Simp The GNU Readline Library is distributed in the hope that it will be 15147359Simp useful, but WITHOUT ANY WARRANTY; without even the implied warranty 16147359Simp of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17147359Simp GNU General Public License for more details. 18147359Simp 19147359Simp The GNU General Public License is often shipped with GNU software, and 20147359Simp is generally kept in a file called COPYING or LICENSE. If you do not 21147359Simp have a copy of the license, write to the Free Software Foundation, 22147359Simp 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 23147359Simp#define READLINE_LIBRARY 24147359Simp 25147359Simp#if defined (HAVE_CONFIG_H) 26147359Simp# include <config.h> 27147595Sru#endif 28147359Simp 29147359Simp#include <sys/types.h> 30147595Sru 31147359Simp#if defined (HAVE_UNISTD_H) 32147359Simp# include <unistd.h> /* for _POSIX_VERSION */ 33147359Simp#endif /* HAVE_UNISTD_H */ 34147359Simp 35147359Simp#if defined (HAVE_STDLIB_H) 36147359Simp# include <stdlib.h> 37147359Simp#else 38147359Simp# include "ansi_stdlib.h" 39147595Sru#endif /* HAVE_STDLIB_H */ 40147359Simp 41147359Simp#include <stdio.h> 42147359Simp 43147359Simp/* System-specific feature definitions and include files. */ 44147359Simp#include "rldefs.h" 45147359Simp 46147359Simp/* Some standard library routines. */ 47147359Simp#include "readline.h" 48147359Simp#include "history.h" 49147359Simp 50147359Simp#include "rlprivate.h" 51147359Simp 52147595Sru#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) 53147595Sru 54147359Simp/* Non-zero tells rl_delete_text and rl_insert_text to not add to 55147359Simp the undo list. */ 56147359Simpint _rl_doing_an_undo = 0; 57147359Simp 58147359Simp/* How many unclosed undo groups we currently have. */ 59147359Simpint _rl_undo_group_level = 0; 60147359Simp 61147359Simp/* The current undo list for THE_LINE. */ 62147359SimpUNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; 63147359Simp 64157954Sjmg/* **************************************************************** */ 65157954Sjmg/* */ 66157954Sjmg/* Undo, and Undoing */ 67157954Sjmg/* */ 68147359Simp/* **************************************************************** */ 69147359Simp 70147359Simp/* Remember how to undo something. Concatenate some undos if that 71147359Simp seems right. */ 72147359Simpvoid 73147359Simprl_add_undo (what, start, end, text) 74147359Simp enum undo_code what; 75147359Simp int start, end; 76147359Simp char *text; 77147359Simp{ 78157954Sjmg UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); 79157954Sjmg temp->what = what; 80157954Sjmg temp->start = start; 81157954Sjmg temp->end = end; 82147359Simp temp->text = text; 83147359Simp temp->next = rl_undo_list; 84147359Simp rl_undo_list = temp; 85147359Simp} 86157954Sjmg 87157954Sjmg/* Free the existing undo list. */ 88157954Sjmgvoid 89157954Sjmgrl_free_undo_list () 90157954Sjmg{ 91157954Sjmg while (rl_undo_list) 92157954Sjmg { 93157954Sjmg UNDO_LIST *release = rl_undo_list; 94157954Sjmg rl_undo_list = rl_undo_list->next; 95157954Sjmg 96157954Sjmg if (release->what == UNDO_DELETE) 97157954Sjmg free (release->text); 98157954Sjmg 99157954Sjmg free (release); 100157954Sjmg } 101157954Sjmg rl_undo_list = (UNDO_LIST *)NULL; 102147359Simp} 103147359Simp 104147359Simp/* Undo the next thing in the list. Return 0 if there 105147359Simp is nothing to undo, or non-zero if there was. */ 106157954Sjmgint 107157954Sjmgrl_do_undo () 108157954Sjmg{ 109157954Sjmg UNDO_LIST *release; 110147359Simp int waiting_for_begin, start, end; 111147359Simp 112147359Simp#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i))) 113147359Simp 114147359Simp start = end = waiting_for_begin = 0; 115147359Simp do 116147359Simp { 117147359Simp if (!rl_undo_list) 118147359Simp return (0); 119147359Simp 120157954Sjmg _rl_doing_an_undo = 1; 121157954Sjmg RL_SETSTATE(RL_STATE_UNDOING); 122157954Sjmg 123157954Sjmg /* To better support vi-mode, a start or end value of -1 means 124147359Simp rl_point, and a value of -2 means rl_end. */ 125147359Simp if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT) 126147359Simp { 127157954Sjmg start = TRANS (rl_undo_list->start); 128157954Sjmg end = TRANS (rl_undo_list->end); 129157954Sjmg } 130157954Sjmg 131157954Sjmg switch (rl_undo_list->what) 132157954Sjmg { 133157954Sjmg /* Undoing deletes means inserting some text. */ 134157954Sjmg case UNDO_DELETE: 135157954Sjmg rl_point = start; 136147595Sru rl_insert_text (rl_undo_list->text); 137147359Simp free (rl_undo_list->text); 138147595Sru break; 139147359Simp 140147595Sru /* Undoing inserts means deleting some text. */ 141147595Sru case UNDO_INSERT: 142147595Sru rl_delete_text (start, end); 143147595Sru rl_point = start; 144147359Simp break; 145147595Sru 146147595Sru /* Undoing an END means undoing everything 'til we get to a BEGIN. */ 147147595Sru case UNDO_END: 148147359Simp waiting_for_begin++; 149147595Sru break; 150147595Sru 151147595Sru /* Undoing a BEGIN means that we are done with this group. */ 152147595Sru case UNDO_BEGIN: 153147359Simp if (waiting_for_begin) 154147359Simp waiting_for_begin--; 155147359Simp else 156147359Simp rl_ding (); 157147359Simp break; 158147359Simp } 159147359Simp 160147595Sru _rl_doing_an_undo = 0; 161147595Sru RL_UNSETSTATE(RL_STATE_UNDOING); 162147595Sru 163231564Sed release = rl_undo_list; 164147595Sru rl_undo_list = rl_undo_list->next; 165147595Sru free (release); 166147595Sru } 167231564Sed while (waiting_for_begin); 168147595Sru 169147595Sru return (1); 170147595Sru} 171231564Sed#undef TRANS 172147595Sru 173147595Sruint 174147595Sru_rl_fix_last_undo_of_type (type, start, end) 175231564Sed int type, start, end; 176147595Sru{ 177147595Sru UNDO_LIST *rl; 178147595Sru 179231564Sed for (rl = rl_undo_list; rl; rl = rl->next) 180157954Sjmg { 181157954Sjmg if (rl->what == type) 182157954Sjmg { 183231564Sed rl->start = start; 184157954Sjmg rl->end = end; 185157954Sjmg return 0; 186157954Sjmg } 187231564Sed } 188157954Sjmg return 1; 189157954Sjmg} 190157954Sjmg 191231564Sed/* Begin a group. Subsequent undos are undone as an atomic operation. */ 192157954Sjmgint 193157954Sjmgrl_begin_undo_group () 194157954Sjmg{ 195147359Simp rl_add_undo (UNDO_BEGIN, 0, 0, 0); 196147595Sru _rl_undo_group_level++; 197147595Sru return 0; 198231564Sed} 199147595Sru 200147359Simp/* End an undo group started with rl_begin_undo_group (). */ 201147595Sruint 202147595Srurl_end_undo_group () 203231564Sed{ 204147595Sru rl_add_undo (UNDO_END, 0, 0, 0); 205147359Simp _rl_undo_group_level--; 206147595Sru return 0; 207147595Sru} 208231564Sed 209147595Sru/* Save an undo entry for the text from START to END. */ 210147359Simpint 211147595Srurl_modifying (start, end) 212147595Sru int start, end; 213231564Sed{ 214147595Sru if (start > end) 215147359Simp { 216157954Sjmg SWAP (start, end); 217157954Sjmg } 218231564Sed 219157954Sjmg if (start != end) 220157954Sjmg { 221157954Sjmg char *temp = rl_copy_text (start, end); 222157954Sjmg rl_begin_undo_group (); 223231564Sed rl_add_undo (UNDO_DELETE, start, end, temp); 224157954Sjmg rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); 225157954Sjmg rl_end_undo_group (); 226157954Sjmg } 227157954Sjmg return 0; 228231564Sed} 229157954Sjmg 230157954Sjmg/* Revert the current line to its previous state. */ 231157954Sjmgint 232157954Sjmgrl_revert_line (count, key) 233231564Sed int count, key; 234157954Sjmg{ 235157954Sjmg if (!rl_undo_list) 236147595Sru rl_ding (); 237147595Sru else 238147595Sru { 239147595Sru while (rl_undo_list) 240147359Simp rl_do_undo (); 241147595Sru } 242147595Sru return 0; 243231564Sed} 244147595Sru 245147595Sru/* Do some undoing of things that were done. */ 246147359Simpint 247147595Srurl_undo_command (count, key) 248147595Sru int count, key; 249231564Sed{ 250147595Sru if (count < 0) 251147595Sru return 0; /* Nothing to do. */ 252147359Simp 253147595Sru while (count) 254147595Sru { 255231564Sed if (rl_do_undo ()) 256147595Sru count--; 257147595Sru else 258147359Simp { 259147595Sru rl_ding (); 260147595Sru break; 261231564Sed } 262147595Sru } 263147595Sru return 0; 264147359Simp} 265157954Sjmg