]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/undo.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / lib / readline / undo.c
CommitLineData
ccc6cda3
JA
1/* readline.c -- a general facility for reading lines of input
2 with emacs style editing and completion. */
3
4/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
5
6 This file is part of the GNU Readline Library, a library for
7 reading lines of text with interactive input and history editing.
8
9 The GNU Readline Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License
bb70624e 11 as published by the Free Software Foundation; either version 2, or
ccc6cda3
JA
12 (at your option) any later version.
13
14 The GNU Readline Library is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
bb70624e 22 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
ccc6cda3
JA
23#define READLINE_LIBRARY
24
25#if defined (HAVE_CONFIG_H)
26# include <config.h>
27#endif
28
29#include <sys/types.h>
30
31#if defined (HAVE_UNISTD_H)
32# include <unistd.h> /* for _POSIX_VERSION */
33#endif /* HAVE_UNISTD_H */
34
35#if defined (HAVE_STDLIB_H)
36# include <stdlib.h>
37#else
38# include "ansi_stdlib.h"
39#endif /* HAVE_STDLIB_H */
40
ccc6cda3
JA
41#include <stdio.h>
42
43/* System-specific feature definitions and include files. */
44#include "rldefs.h"
45
46/* Some standard library routines. */
47#include "readline.h"
48#include "history.h"
49
bb70624e
JA
50#include "rlprivate.h"
51
ccc6cda3
JA
52#define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0)
53
54/* Non-zero tells rl_delete_text and rl_insert_text to not add to
55 the undo list. */
56int _rl_doing_an_undo = 0;
57
58/* How many unclosed undo groups we currently have. */
59int _rl_undo_group_level = 0;
60
61/* The current undo list for THE_LINE. */
62UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
63
64/* **************************************************************** */
65/* */
66/* Undo, and Undoing */
67/* */
68/* **************************************************************** */
69
70/* Remember how to undo something. Concatenate some undos if that
71 seems right. */
72void
73rl_add_undo (what, start, end, text)
74 enum undo_code what;
75 int start, end;
76 char *text;
77{
78 UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
79 temp->what = what;
80 temp->start = start;
81 temp->end = end;
82 temp->text = text;
83 temp->next = rl_undo_list;
84 rl_undo_list = temp;
85}
86
87/* Free the existing undo list. */
88void
28ef6c31 89rl_free_undo_list ()
ccc6cda3
JA
90{
91 while (rl_undo_list)
92 {
93 UNDO_LIST *release = rl_undo_list;
94 rl_undo_list = rl_undo_list->next;
95
96 if (release->what == UNDO_DELETE)
97 free (release->text);
98
99 free (release);
100 }
101 rl_undo_list = (UNDO_LIST *)NULL;
102}
103
104/* Undo the next thing in the list. Return 0 if there
105 is nothing to undo, or non-zero if there was. */
106int
107rl_do_undo ()
108{
109 UNDO_LIST *release;
28ef6c31 110 int waiting_for_begin, start, end;
ccc6cda3
JA
111
112#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
113
28ef6c31 114 start = end = waiting_for_begin = 0;
ccc6cda3
JA
115 do
116 {
117 if (!rl_undo_list)
118 return (0);
119
120 _rl_doing_an_undo = 1;
28ef6c31 121 RL_SETSTATE(RL_STATE_UNDOING);
ccc6cda3
JA
122
123 /* To better support vi-mode, a start or end value of -1 means
124 rl_point, and a value of -2 means rl_end. */
125 if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
126 {
127 start = TRANS (rl_undo_list->start);
128 end = TRANS (rl_undo_list->end);
129 }
130
131 switch (rl_undo_list->what)
132 {
133 /* Undoing deletes means inserting some text. */
134 case UNDO_DELETE:
135 rl_point = start;
136 rl_insert_text (rl_undo_list->text);
137 free (rl_undo_list->text);
138 break;
139
140 /* Undoing inserts means deleting some text. */
141 case UNDO_INSERT:
142 rl_delete_text (start, end);
143 rl_point = start;
144 break;
145
146 /* Undoing an END means undoing everything 'til we get to a BEGIN. */
147 case UNDO_END:
148 waiting_for_begin++;
149 break;
150
151 /* Undoing a BEGIN means that we are done with this group. */
152 case UNDO_BEGIN:
153 if (waiting_for_begin)
154 waiting_for_begin--;
155 else
28ef6c31 156 rl_ding ();
ccc6cda3
JA
157 break;
158 }
159
160 _rl_doing_an_undo = 0;
28ef6c31 161 RL_UNSETSTATE(RL_STATE_UNDOING);
ccc6cda3
JA
162
163 release = rl_undo_list;
164 rl_undo_list = rl_undo_list->next;
165 free (release);
166 }
167 while (waiting_for_begin);
168
169 return (1);
170}
171#undef TRANS
172
173int
174_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)
28ef6c31 236 rl_ding ();
ccc6cda3
JA
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 {
28ef6c31 259 rl_ding ();
ccc6cda3
JA
260 break;
261 }
262 }
263 return 0;
264}