undo.c revision 75406
18876Srgrimes/* readline.c -- a general facility for reading lines of input 24Srgrimes with emacs style editing and completion. */ 34Srgrimes 44Srgrimes/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 58876Srgrimes 64Srgrimes This file is part of the GNU Readline Library, a library for 74Srgrimes reading lines of text with interactive input and history editing. 84Srgrimes 94Srgrimes The GNU Readline Library is free software; you can redistribute it 104Srgrimes and/or modify it under the terms of the GNU General Public License 118876Srgrimes as published by the Free Software Foundation; either version 2, or 128876Srgrimes (at your option) any later version. 134Srgrimes 144Srgrimes The GNU Readline Library is distributed in the hope that it will be 158876Srgrimes useful, but WITHOUT ANY WARRANTY; without even the implied warranty 164Srgrimes of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178876Srgrimes GNU General Public License for more details. 184Srgrimes 194Srgrimes The GNU General Public License is often shipped with GNU software, and 204Srgrimes is generally kept in a file called COPYING or LICENSE. If you do not 214Srgrimes have a copy of the license, write to the Free Software Foundation, 228876Srgrimes 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 234Srgrimes#define READLINE_LIBRARY 244Srgrimes 254Srgrimes#if defined (HAVE_CONFIG_H) 2612515Sphk# include <config.h> 274Srgrimes#endif 28623Srgrimes 294Srgrimes#include <sys/types.h> 304Srgrimes 314Srgrimes#if defined (HAVE_UNISTD_H) 324Srgrimes# include <unistd.h> /* for _POSIX_VERSION */ 334Srgrimes#endif /* HAVE_UNISTD_H */ 342056Swollman 352056Swollman#if defined (HAVE_STDLIB_H) 362056Swollman# include <stdlib.h> 372056Swollman#else 384Srgrimes# include "ansi_stdlib.h" 394Srgrimes#endif /* HAVE_STDLIB_H */ 404Srgrimes 414Srgrimes#include <stdio.h> 4212515Sphk 4312473Sbde/* System-specific feature definitions and include files. */ 444Srgrimes#include "rldefs.h" 4512515Sphk 4612515Sphk/* Some standard library routines. */ 4712515Sphk#include "readline.h" 4812515Sphk#include "history.h" 4912515Sphk 504Srgrimes#include "rlprivate.h" 514Srgrimes 524Srgrimes#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) 534Srgrimes 544Srgrimes/* Non-zero tells rl_delete_text and rl_insert_text to not add to 5512515Sphk the undo list. */ 5612515Sphkint _rl_doing_an_undo = 0; 574Srgrimes 5812515Sphk/* How many unclosed undo groups we currently have. */ 594Srgrimesint _rl_undo_group_level = 0; 604Srgrimes 614Srgrimes/* The current undo list for THE_LINE. */ 624SrgrimesUNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; 634Srgrimes 644Srgrimes/* **************************************************************** */ 654Srgrimes/* */ 664Srgrimes/* Undo, and Undoing */ 674Srgrimes/* */ 684Srgrimes/* **************************************************************** */ 694Srgrimes 704Srgrimes/* Remember how to undo something. Concatenate some undos if that 714Srgrimes seems right. */ 724Srgrimesvoid 734Srgrimesrl_add_undo (what, start, end, text) 744Srgrimes enum undo_code what; 754Srgrimes int start, end; 764Srgrimes char *text; 774Srgrimes{ 784Srgrimes UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); 794Srgrimes temp->what = what; 804Srgrimes temp->start = start; 814Srgrimes temp->end = end; 824Srgrimes temp->text = text; 834Srgrimes temp->next = rl_undo_list; 844Srgrimes rl_undo_list = temp; 854Srgrimes} 864Srgrimes 874Srgrimes/* Free the existing undo list. */ 884Srgrimesvoid 894Srgrimesrl_free_undo_list () 904Srgrimes{ 914Srgrimes while (rl_undo_list) 924Srgrimes { 934Srgrimes UNDO_LIST *release = rl_undo_list; 944Srgrimes rl_undo_list = rl_undo_list->next; 954Srgrimes 964Srgrimes if (release->what == UNDO_DELETE) 974Srgrimes free (release->text); 9812515Sphk 9912515Sphk free (release); 1004Srgrimes } 1014Srgrimes rl_undo_list = (UNDO_LIST *)NULL; 1024Srgrimes} 1034Srgrimes 1044Srgrimes/* Undo the next thing in the list. Return 0 if there 1054Srgrimes is nothing to undo, or non-zero if there was. */ 1064Srgrimesint 1074Srgrimesrl_do_undo () 1084Srgrimes{ 1094Srgrimes UNDO_LIST *release; 1104Srgrimes int waiting_for_begin, start, end; 1114Srgrimes 11212515Sphk#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i))) 1134Srgrimes 114798Swollman start = end = waiting_for_begin = 0; 1154Srgrimes do 1164Srgrimes { 1174Srgrimes if (!rl_undo_list) 1184Srgrimes return (0); 11912473Sbde 1204Srgrimes _rl_doing_an_undo = 1; 1214Srgrimes RL_SETSTATE(RL_STATE_UNDOING); 1224Srgrimes 1234Srgrimes /* To better support vi-mode, a start or end value of -1 means 1244Srgrimes rl_point, and a value of -2 means rl_end. */ 1254Srgrimes if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT) 1264Srgrimes { 127798Swollman start = TRANS (rl_undo_list->start); 1284Srgrimes end = TRANS (rl_undo_list->end); 1294Srgrimes } 1304Srgrimes 1314Srgrimes switch (rl_undo_list->what) 13212473Sbde { 1334Srgrimes /* Undoing deletes means inserting some text. */ 1344Srgrimes case UNDO_DELETE: 1354Srgrimes rl_point = start; 1364Srgrimes rl_insert_text (rl_undo_list->text); 1374Srgrimes free (rl_undo_list->text); 1384Srgrimes break; 1394Srgrimes 1404Srgrimes /* Undoing inserts means deleting some text. */ 14112473Sbde case UNDO_INSERT: 14212473Sbde rl_delete_text (start, end); 14312473Sbde rl_point = start; 14412473Sbde break; 14512473Sbde 1464Srgrimes /* Undoing an END means undoing everything 'til we get to a BEGIN. */ 1474Srgrimes case UNDO_END: 1484Srgrimes waiting_for_begin++; 1494Srgrimes break; 1504Srgrimes 1514Srgrimes /* Undoing a BEGIN means that we are done with this group. */ 1524Srgrimes case UNDO_BEGIN: 1534Srgrimes if (waiting_for_begin) 1544Srgrimes waiting_for_begin--; 1554Srgrimes else 1564Srgrimes rl_ding (); 1574Srgrimes break; 1584Srgrimes } 1594Srgrimes 1604Srgrimes _rl_doing_an_undo = 0; 1614Srgrimes RL_UNSETSTATE(RL_STATE_UNDOING); 1624Srgrimes 1634Srgrimes release = rl_undo_list; 1644Srgrimes rl_undo_list = rl_undo_list->next; 1654Srgrimes free (release); 1664Srgrimes } 1674Srgrimes while (waiting_for_begin); 1684Srgrimes 1694Srgrimes return (1); 1704Srgrimes} 1714Srgrimes#undef TRANS 1724Srgrimes 1734Srgrimesint 1744Srgrimes_rl_fix_last_undo_of_type (type, start, end) 175 int type, start, end; 176{ 177 UNDO_LIST *rl; 178 179 for (rl = rl_undo_list; rl; rl = rl->next) 180 { 181 if (rl->what == type) 182 { 183 rl->start = start; 184 rl->end = end; 185 return 0; 186 } 187 } 188 return 1; 189} 190 191/* Begin a group. Subsequent undos are undone as an atomic operation. */ 192int 193rl_begin_undo_group () 194{ 195 rl_add_undo (UNDO_BEGIN, 0, 0, 0); 196 _rl_undo_group_level++; 197 return 0; 198} 199 200/* End an undo group started with rl_begin_undo_group (). */ 201int 202rl_end_undo_group () 203{ 204 rl_add_undo (UNDO_END, 0, 0, 0); 205 _rl_undo_group_level--; 206 return 0; 207} 208 209/* Save an undo entry for the text from START to END. */ 210int 211rl_modifying (start, end) 212 int start, end; 213{ 214 if (start > end) 215 { 216 SWAP (start, end); 217 } 218 219 if (start != end) 220 { 221 char *temp = rl_copy_text (start, end); 222 rl_begin_undo_group (); 223 rl_add_undo (UNDO_DELETE, start, end, temp); 224 rl_add_undo (UNDO_INSERT, start, end, (char *)NULL); 225 rl_end_undo_group (); 226 } 227 return 0; 228} 229 230/* Revert the current line to its previous state. */ 231int 232rl_revert_line (count, key) 233 int count, key; 234{ 235 if (!rl_undo_list) 236 rl_ding (); 237 else 238 { 239 while (rl_undo_list) 240 rl_do_undo (); 241 } 242 return 0; 243} 244 245/* Do some undoing of things that were done. */ 246int 247rl_undo_command (count, key) 248 int count, key; 249{ 250 if (count < 0) 251 return 0; /* Nothing to do. */ 252 253 while (count) 254 { 255 if (rl_do_undo ()) 256 count--; 257 else 258 { 259 rl_ding (); 260 break; 261 } 262 } 263 return 0; 264} 265