]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - readline/undo.c
Sync readline/ to version 7.0 alpha
[thirdparty/binutils-gdb.git] / readline / undo.c
CommitLineData
d60d9f65
SS
1/* readline.c -- a general facility for reading lines of input
2 with emacs style editing and completion. */
3
37905921 4/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
d60d9f65 5
cc88a640
JK
6 This file is part of the GNU Readline Library (Readline), a library
7 for reading lines of text with interactive input and history editing.
d60d9f65 8
cc88a640
JK
9 Readline is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
d60d9f65
SS
12 (at your option) any later version.
13
cc88a640
JK
14 Readline is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d60d9f65
SS
17 GNU General Public License for more details.
18
cc88a640
JK
19 You should have received a copy of the GNU General Public License
20 along with Readline. If not, see <http://www.gnu.org/licenses/>.
21*/
22
d60d9f65
SS
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
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
1b17e766 50#include "rlprivate.h"
9255ee31 51#include "xmalloc.h"
d60d9f65 52
cc88a640
JK
53extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
54
d60d9f65
SS
55/* Non-zero tells rl_delete_text and rl_insert_text to not add to
56 the undo list. */
57int _rl_doing_an_undo = 0;
58
59/* How many unclosed undo groups we currently have. */
60int _rl_undo_group_level = 0;
61
62/* The current undo list for THE_LINE. */
63UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
64
65/* **************************************************************** */
66/* */
67/* Undo, and Undoing */
68/* */
69/* **************************************************************** */
70
cc88a640
JK
71static UNDO_LIST *
72alloc_undo_entry (what, start, end, text)
d60d9f65
SS
73 enum undo_code what;
74 int start, end;
75 char *text;
76{
cc88a640
JK
77 UNDO_LIST *temp;
78
79 temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
d60d9f65
SS
80 temp->what = what;
81 temp->start = start;
82 temp->end = end;
83 temp->text = text;
cc88a640
JK
84
85 temp->next = (UNDO_LIST *)NULL;
86 return temp;
87}
88
89/* Remember how to undo something. Concatenate some undos if that
90 seems right. */
91void
92rl_add_undo (what, start, end, text)
93 enum undo_code what;
94 int start, end;
95 char *text;
96{
97 UNDO_LIST *temp;
98
99 temp = alloc_undo_entry (what, start, end, text);
d60d9f65
SS
100 temp->next = rl_undo_list;
101 rl_undo_list = temp;
102}
103
37905921 104/* Free an UNDO_LIST */
d60d9f65 105void
37905921
PP
106_rl_free_undo_list (ul)
107 UNDO_LIST *ul;
d60d9f65 108{
37905921 109 UNDO_LIST *release;
cc88a640 110
37905921 111 while (ul)
d60d9f65 112 {
37905921
PP
113 release = ul;
114 ul = ul->next;
d60d9f65
SS
115
116 if (release->what == UNDO_DELETE)
cc88a640 117 xfree (release->text);
d60d9f65 118
cc88a640 119 xfree (release);
d60d9f65 120 }
37905921
PP
121}
122
123/* Free the existing undo list. */
124void
125rl_free_undo_list ()
126{
127 UNDO_LIST *release, *orig_list;
128
129 orig_list = rl_undo_list;
130 _rl_free_undo_list (rl_undo_list);
d60d9f65 131 rl_undo_list = (UNDO_LIST *)NULL;
cc88a640
JK
132 replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
133}
134
135UNDO_LIST *
136_rl_copy_undo_entry (entry)
137 UNDO_LIST *entry;
138{
139 UNDO_LIST *new;
140
141 new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
142 new->text = entry->text ? savestring (entry->text) : 0;
143 return new;
144}
145
146UNDO_LIST *
147_rl_copy_undo_list (head)
148 UNDO_LIST *head;
149{
150 UNDO_LIST *list, *new, *roving, *c;
151
152 if (head == 0)
153 return head;
154
155 list = head;
156 new = 0;
157 while (list)
158 {
159 c = _rl_copy_undo_entry (list);
160 if (new == 0)
161 roving = new = c;
162 else
163 {
164 roving->next = c;
165 roving = roving->next;
166 }
167 list = list->next;
168 }
169
170 roving->next = 0;
171 return new;
d60d9f65
SS
172}
173
174/* Undo the next thing in the list. Return 0 if there
175 is nothing to undo, or non-zero if there was. */
176int
177rl_do_undo ()
178{
179 UNDO_LIST *release;
9255ee31 180 int waiting_for_begin, start, end;
37905921 181 HIST_ENTRY *cur, *temp;
d60d9f65
SS
182
183#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
184
9255ee31 185 start = end = waiting_for_begin = 0;
d60d9f65
SS
186 do
187 {
cc88a640 188 if (rl_undo_list == 0)
d60d9f65
SS
189 return (0);
190
191 _rl_doing_an_undo = 1;
9255ee31 192 RL_SETSTATE(RL_STATE_UNDOING);
d60d9f65
SS
193
194 /* To better support vi-mode, a start or end value of -1 means
195 rl_point, and a value of -2 means rl_end. */
196 if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
197 {
198 start = TRANS (rl_undo_list->start);
199 end = TRANS (rl_undo_list->end);
200 }
201
202 switch (rl_undo_list->what)
203 {
204 /* Undoing deletes means inserting some text. */
205 case UNDO_DELETE:
206 rl_point = start;
207 rl_insert_text (rl_undo_list->text);
cc88a640 208 xfree (rl_undo_list->text);
d60d9f65
SS
209 break;
210
211 /* Undoing inserts means deleting some text. */
212 case UNDO_INSERT:
213 rl_delete_text (start, end);
214 rl_point = start;
215 break;
216
217 /* Undoing an END means undoing everything 'til we get to a BEGIN. */
218 case UNDO_END:
219 waiting_for_begin++;
220 break;
221
222 /* Undoing a BEGIN means that we are done with this group. */
223 case UNDO_BEGIN:
224 if (waiting_for_begin)
225 waiting_for_begin--;
226 else
9255ee31 227 rl_ding ();
d60d9f65
SS
228 break;
229 }
230
231 _rl_doing_an_undo = 0;
9255ee31 232 RL_UNSETSTATE(RL_STATE_UNDOING);
d60d9f65
SS
233
234 release = rl_undo_list;
235 rl_undo_list = rl_undo_list->next;
37905921
PP
236
237 /* If we are editing a history entry, make sure the change is replicated
238 in the history entry's line */
239 cur = current_history ();
240 if (cur && cur->data && (UNDO_LIST *)cur->data == release)
241 {
242 temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
243 xfree (temp->line);
244 FREE (temp->timestamp);
245 xfree (temp);
246 }
247
cc88a640
JK
248 replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
249
250 xfree (release);
d60d9f65
SS
251 }
252 while (waiting_for_begin);
253
254 return (1);
255}
256#undef TRANS
257
258int
259_rl_fix_last_undo_of_type (type, start, end)
260 int type, start, end;
261{
262 UNDO_LIST *rl;
263
264 for (rl = rl_undo_list; rl; rl = rl->next)
265 {
266 if (rl->what == type)
267 {
268 rl->start = start;
269 rl->end = end;
270 return 0;
271 }
272 }
273 return 1;
274}
275
276/* Begin a group. Subsequent undos are undone as an atomic operation. */
277int
278rl_begin_undo_group ()
279{
280 rl_add_undo (UNDO_BEGIN, 0, 0, 0);
281 _rl_undo_group_level++;
282 return 0;
283}
284
285/* End an undo group started with rl_begin_undo_group (). */
286int
287rl_end_undo_group ()
288{
289 rl_add_undo (UNDO_END, 0, 0, 0);
290 _rl_undo_group_level--;
291 return 0;
292}
293
294/* Save an undo entry for the text from START to END. */
295int
296rl_modifying (start, end)
297 int start, end;
298{
299 if (start > end)
300 {
301 SWAP (start, end);
302 }
303
304 if (start != end)
305 {
306 char *temp = rl_copy_text (start, end);
307 rl_begin_undo_group ();
308 rl_add_undo (UNDO_DELETE, start, end, temp);
309 rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
310 rl_end_undo_group ();
311 }
312 return 0;
313}
314
315/* Revert the current line to its previous state. */
316int
317rl_revert_line (count, key)
318 int count, key;
319{
cc88a640 320 if (rl_undo_list == 0)
9255ee31 321 rl_ding ();
d60d9f65
SS
322 else
323 {
324 while (rl_undo_list)
325 rl_do_undo ();
5bdf8622
DJ
326#if defined (VI_MODE)
327 if (rl_editing_mode == vi_mode)
328 rl_point = rl_mark = 0; /* rl_end should be set correctly */
329#endif
d60d9f65 330 }
5bdf8622 331
d60d9f65
SS
332 return 0;
333}
334
335/* Do some undoing of things that were done. */
336int
337rl_undo_command (count, key)
338 int count, key;
339{
340 if (count < 0)
341 return 0; /* Nothing to do. */
342
343 while (count)
344 {
345 if (rl_do_undo ())
346 count--;
347 else
348 {
9255ee31 349 rl_ding ();
d60d9f65
SS
350 break;
351 }
352 }
353 return 0;
354}